Makefile 在每个子目录中运行make
我有一个目录(Makefile 在每个子目录中运行make,makefile,gnu-make,Makefile,Gnu Make,我有一个目录(root\u dir),其中包含许多子目录(subdir1,subdir2,…) 我想在root\u dir中的每个目录中运行make,使用放置在其中的Makefile。 (显然,假设每个子目录…都有自己的Makefile) 因此,基本上有两个问题: 如何(自动)获取Makefile中的目录列表 如何为make文件中的每个目录运行make 据我所知,为了在特定目录中运行make,我需要执行以下操作: $(MAKE) -C subdir 试试这个: SUBDIRS = foo ba
root\u dir
),其中包含许多子目录(subdir1,subdir2,…
)
我想在root\u dir
中的每个目录中运行make
,使用放置在其中的Makefile。
(显然,假设每个子目录…
都有自己的Makefile)
因此,基本上有两个问题:
make
make
,我需要执行以下操作:
$(MAKE) -C subdir
试试这个:
SUBDIRS = foo bar baz
subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done
这可能对你有帮助
编辑:您还可以执行以下操作:
最简单的方法是:
CODE_DIR = code
.PHONY: project_code
project_code:
$(MAKE) -C $(CODE_DIR)
.PHONY规则意味着project_代码不是需要修改的文件
构建,并且-C标志指示目录中的更改(相当于
在调用make之前运行cd代码)。您可以使用相同的方法
用于调用代码生成文件中的其他目标
例如:
clean:
$(MAKE) -C $(CODE_DIR) clean
my_target: my_subdirectory/my_prerequisite
'my_subdirectory/my_prerequisite' > 'my_target'
在一个配方中的for循环中进行子生成时,会出现各种问题。创建多个子目录的最佳方法如下:
SUBDIRS := $(wildcard */.)
all: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
.PHONY: all $(SUBDIRS)
include prorab.mk
$(eval $(prorab-build-subdirs))
(只是要指出这是GNU make specific;您没有提到对您正在使用的make版本的任何限制)
ETA这是一个支持多个顶级目标的版本
TOPTARGETS := all clean
SUBDIRS := $(wildcard */.)
$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ $(MAKECMDGOALS)
.PHONY: $(TOPTARGETS) $(SUBDIRS)
GNU make有一个名为prorab的库,它支持在子目录中包含独立的makefile 关于github的一些信息: 基本上,使用prorab调用子目录中的所有makefile如下所示:
SUBDIRS := $(wildcard */.)
all: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
.PHONY: all $(SUBDIRS)
include prorab.mk
$(eval $(prorab-build-subdirs))
由于我不知道MAKECMDGOALS变量,并且忽略了MadScientist自己有多个顶级目标的实现,所以我编写了一个替代实现。也许有人觉得它有用
SUBDIRS := $(wildcard */.)
define submake
for d in $(SUBDIRS); \
do \
$(MAKE) $(1) --directory=$$d; \
done
endef
all:
$(call submake,$@)
install:
$(call submake,$@)
.PHONY: all install $(SUBDIRS)
在MadScientist的回答之后,为了使子目录中的所有单个目标从顶层可用(您需要定义
SUBDIRS
变量,以便使用以下代码片段–您可以使用MadScientist的回答):
例如,使用上面的代码,您可以运行
make foo/my_program
或
此外,通过粘贴上面的代码,您甚至可以使用子目录中的单个目标作为顶层目标的先决条件。例如:
clean:
$(MAKE) -C $(CODE_DIR) clean
my_target: my_subdirectory/my_prerequisite
'my_subdirectory/my_prerequisite' > 'my_target'
…在上面的示例中,从顶层启动
make my_target
将首先构建my_子目录/my_prerequisite
程序,然后运行后者来构建my_target
文件。这是另一种方法.PHONY
是GNU特有的特性,可用于强制make
递归到每个子目录中。但是,一些非GNU版本的make
不支持.PHONY
,因此另一种选择是使用
4.7没有配方或先决条件的规则
如果规则没有先决条件或配方,以及规则的目标
是一个不存在的文件,然后使想象这个目标已经存在
每当运行其规则时更新。这意味着所有目标
根据这一点,他们的食谱将始终运行
举例说明:
clean: FORCE
rm $(objects)
FORCE:
在这里,目标“力”满足特殊条件,因此
依赖于它的目标清理被强制运行其配方。有
“FORCE”这个名字没有什么特别之处,但它通常是一个名字
用这种方式
如您所见,以这种方式使用“FORCE”与使用
“虚假:干净”
使用“.PHONY”更明确、更有效。然而,其他
make的版本不支持“.PHONY”;因此,"力"出现在许多领域
生成文件。见假目标
下面是一个将make
递归到每个子目录的最小示例,每个子目录大概都包含一个Makefile
。如果只运行make
,则只处理第一个子目录,它是不确定的。您还可以运行make subdir1 subdir2…
#注册项目根目录中的所有子目录。
子项:=$(通配符*/)
#将'make'递归到每个子目录中。
$(细分曲面):强制
$(MAKE)-C$@
#没有先决条件和配方的目标,并且没有名为“FORCE”的文件。
#'make'将始终运行此目标以及依赖它的任何其他目标。
部队:
下面是另一个顶级虚假目标的例子:all
和clean
。请注意,从命令行通过$(MAKECMDGOALS)
传递的all
和clean
目标分别由每个子目录的all
和clean
目标处理
#注册项目根目录中的所有子目录。
子项:=$(通配符*/)
#顶级假目标。
全部清除:$(细分曲面)强制
#类似于:
#.骗子:都是干净的
#全部清洁:$(细分曲面)
#GNU的.PHONY目标更有效,因为它显式声明非文件。
#将'make'递归到每个子目录中
#传递命令行中指定的目标(如果有)。
$(细分曲面):强制
$(MAKE)-C$@$(MAKECMDGOALS)
#部队目标。
部队:
您还可以在Makefile中定义一个函数(当然,您还需要在每个子目录中添加一个Makefile)。这取决于shell,但可能很有用:
define FOREACH
for DIR in packages/*; do \
$(MAKE) -C $$DIR $(1); \
done
endef
.PHONY: build
build:
$(call FOREACH,build)
.PHONY: clean
clean:
$(call FOREACH,clean)
.PHONY: test
test:
$(call FOREACH,test)
实际上我不想在Makefile中有一个目录列表,如果我还想要干净的目标呢?为什么$(子目录)在.PHONY中?这是因为目录修改日期/时间无关紧要吗?我有这个问题,因为目录不是伪造的。PHONY应该用于假目标。
。PHONY
用于您希望在每次运行makefile时生成的目标,而不管它是否存在或是否过期