来自Makefile中子目录的源代码

时间:2010-10-27 17:58:45

标签: makefile

我有一个使用Makefile构建的C ++库。直到最近,所有的源都在一个目录中,Makefile做了类似的事情

SOURCES = $(wildcard *.cpp)

工作得很好。

现在我添加了一些子目录中的一些来源,比如subdir。我知道我可以做到这一点

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

但我正在寻找一种方法来避免手动指定subdir,即make wildcard查看子目录,或以某种方式生成子目录列表并使用多个{{1}扩展它} 功能。此时,使用非递归解决方案(即仅扩展第一级)就可以了。

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

7 个答案:

答案 0 :(得分:69)

这应该这样做:

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

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

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

答案 1 :(得分:19)

递归通配符可以完全在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的更多用法添加支持将是直截了当的。

答案 2 :(得分:15)

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

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

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

答案 3 :(得分:9)

Common practice是在每个子目录中放置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进入子目录。确保它不会重新编译需要recursive的目标中的任何内容。

答案 4 :(得分:7)

这是一份附注,并没有回答你的问题,但有一篇论文“Recursive Make Considered Harmful”。值得一读。

这是链接。 http://aegis.sourceforge.net/auug97.pdf

答案 5 :(得分:2)

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

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

答案 6 :(得分:2)

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

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

如果您需要更多深度:

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

不幸的是,与我们有时阅读的内容相反,makefile不支持glob(**),它将被解释为普通通配符(**/*.cpp匹配*/*.cpp而不是{{1 }}。

如果您需要无限深度,请使用*/*/*.cpp

shell
相关问题