来自 Makefile 子目录的源代码

发布于 2024-09-29 14:20:12 字数 501 浏览 2 评论 0原文

我有一个使用 Makefile 构建的 C++ 库。直到最近,所有源代码都位于一个目录中,并且 Makefile 执行了类似

SOURCES = $(wildcard *.cpp)

操作,效果很好。

现在我添加了一些位于子目录中的源,例如 subdir。我知道我可以这样做

SOURCES = $(wildcard *.cpp) $(wildcard subdir/*.cpp)

但我正在寻找一种方法来避免指定 subdir手动,也就是说,让 wildcard 查看子目录,或者以某种方式生成子目录列表并使用多个 wildcard 函数扩展它。此时,有一个非递归解决方案(即仅扩展第一层)就可以了。

我没有找到任何东西 - 我最好的猜测是使用 find -type d 列出子目录,但这感觉就像黑客。有没有内置的方法可以做到这一点?

I have a C++ library built using a Makefile. Until recently, all the sources were in a single directory, and the Makefile did something like this

SOURCES = $(wildcard *.cpp)

which worked fine.

Now I've added some sources that are in a subdirectory, say subdir. I know I can do this

SOURCES = $(wildcard *.cpp) $(wildcard subdir/*.cpp)

but I'm looking for a way to avoid specifying subdir manually, that is, make wildcard look into subdirectories, or generating a list of subdirectories somehow and expanding it with several wildcard functions. At this point, having a non-recursive solution (that is, expanding only the first level) would be fine.

I haven't found anything - my best guess is using find -type d to list the subdirectories, but it feels like a hack. Is there any built-in way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

笑忘罢 2024-10-06 14:20:12

这应该可以做到:

SOURCES = $(wildcard *.cpp) $(wildcard */*.cpp)

如果您改变主意并想要一个递归解决方案(即任何深度),它可以完成,但它涉及一些更强大的 Make 函数。你知道,那些允许你做你不应该做的事情的人。

编辑:
Jack Kelly 指出,$(wildcard **/*.cpp) 使用 GNUMake 3.81 可在任何深度工作,至少在某些平台上如此。 (他是怎么想出来的,我不知道。)

This should do it:

SOURCES = $(wildcard *.cpp) $(wildcard */*.cpp)

If you change you mind and want a recursive solution (i.e. to any depth), it can be done but it involves some of the more powerful Make functions. You know, the ones that allow you to do things you really shouldn't.

EDIT:
Jack Kelly points out that $(wildcard **/*.cpp) works to any depth, at least on some platforms, using GNUMake 3.81. (How he figured that out, I have no idea.)

鹿! 2024-10-06 14:20:12

递归通配符可以纯粹在 Make 中完成,无需调用 shell 或 find 命令。仅使用 Make 进行搜索意味着该解决方案也适用于 Windows,而不仅仅是 *nix。

# Make does not offer a recursive wildcard function, so here's one:
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

# How to recursively find all files with the same name in a given folder
ALL_INDEX_HTMLS := $(call rwildcard,foo/,index.html)

# How to recursively find all files that match a pattern
ALL_HTMLS := $(call rwildcard,foo/,*.html)

文件夹名称中的尾部斜杠是必需的。这个 rwildcard 函数不像 Make 的内置通配符函数那样支持多个通配符,但是通过使用 foreach 来添加该支持将很简单。

Recursive wildcards can be done purely in Make, without calling the shell or the find command. Doing the search using only Make means that this solution works on Windows as well, not just *nix.

# Make does not offer a recursive wildcard function, so here's one:
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

# How to recursively find all files with the same name in a given folder
ALL_INDEX_HTMLS := $(call rwildcard,foo/,index.html)

# How to recursively find all files that match a pattern
ALL_HTMLS := $(call rwildcard,foo/,*.html)

The trailing slash in the folder name is required. This rwildcard function does not support multiple wildcards the way that Make's built-in wildcard function does, but adding that support would be straightforward with a couple more uses of foreach.

轮廓§ 2024-10-06 14:20:12

如果您不想使用递归 makefile,这可能会给您一些想法:

subdirs := $(wildcard */)
sources := $(wildcard $(addsuffix *.cpp,$(subdirs)))
objects := $(patsubst %.cpp,%.o,$(sources))

$(objects) : %.o : %.cpp

If you don't want to use recursive makefiles, this might give you some ideas:

subdirs := $(wildcard */)
sources := $(wildcard $(addsuffix *.cpp,$(subdirs)))
objects := $(patsubst %.cpp,%.o,$(sources))

$(objects) : %.o : %.cpp
泅渡 2024-10-06 14:20:12

您可以在 wildcard 中使用多个规则:

SOURCES := $(wildcard *.cpp */*.cpp)

如果您需要更多深度:

SOURCES := $(wildcard *.cpp */*.cpp */*/*.cpp */*/*/*.cpp)

不幸的是,与我们有时读到的不同,glob (**) 不受 makefile 支持,并且将被解释为普通通配符 (*)。

例如,**/*.cpp 匹配 dir/file.cpp,但既不匹配 file.cpp 也不匹配 dir/sub/file。 cpp.

如果您需要无限深度,请使用 shellfind

SOURCES := $(shell find . -name "*.cpp")

You can use several rules in wildcard:

SOURCES := $(wildcard *.cpp */*.cpp)

if you need more depth:

SOURCES := $(wildcard *.cpp */*.cpp */*/*.cpp */*/*/*.cpp)

Unfortunately, and unlike what we sometimes read, glob (**) is not supported by makefile and will be interpreted as normal wildcard (*).

For example **/*.cpp match dir/file.cpp but neither file.cpp nor dir/sub/file.cpp.

If you need infinite depth use shell and find:

SOURCES := $(shell find . -name "*.cpp")
—━☆沉默づ 2024-10-06 14:20:12

常见做法是放置一个 Makefile 位于每个带有源代码的子目录中,然后

all: recursive
    $(MAKE) -C componentX
    # stuff for current dir

或者

all: recursive
    cd componentX && $(MAKE)
    # stuff for current dir

recursive: true

将每个 Makefile 的设置放在根源目录的 Makefile.inc 中可能是明智的。 recursive 目标强制 make 进入子目录。确保它不会重新编译需要递归的目标中的任何内容。

Common practice is to put a Makefile in each subdir with sources, then

all: recursive
    $(MAKE) -C componentX
    # stuff for current dir

or

all: recursive
    cd componentX && $(MAKE)
    # stuff for current dir

recursive: true

It may be wise to put settings for each Makefile in a Makefile.inc in the root source directory. The recursive target forces make to go into the subdirectories. Make sure that it doesn't recompile anything in a target requiring recursive.

欢你一世 2024-10-06 14:20:12

如果您可以使用 find shell 命令,您可以定义一个函数来使用它。

recurfind = $(shell find $(1) -name '$(2)')
SRCS := $(call recurfind,subdir1,*.c) $(call recurfind,subdir2,*.cc) $(call recurfind,subdir2,*.cu) \
        ...

If you can use find shell command, you may define a function to use it.

recurfind = $(shell find $(1) -name '$(2)')
SRCS := $(call recurfind,subdir1,*.c) $(call recurfind,subdir2,*.cc) $(call recurfind,subdir2,*.cu) \
        ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文