在每个子目录中运行make

Ale*_*lex 38 makefile gnu-make

我有一个目录(root_dir),其中包含许多子目录(subdir1, subdir2, ...).

我想make在每个目录中运行root_dir,使用放置在其中的Makefile.(显然假设每个subdir...内部都有自己的Makefile).

所以基本上有两个问题:

  1. 如何在Makefile中自动获取目录列表?
  2. 如何为make文件中的每个目录运行make?

我知道为了在特定目录中运行make,我应该注意以下事项:

$(MAKE) -C subdir
Run Code Online (Sandbox Code Playgroud)

Mad*_*ist 81

在单个配方中执行for循环内的子make有各种问题.执行多个子目录的最佳方法是这样的:

SUBDIRS := $(wildcard */.)

all: $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@

.PHONY: all $(SUBDIRS)
Run Code Online (Sandbox Code Playgroud)

(只是要指出这是GNU make具体的;你没有提到对你正在使用的make版本的任何限制).

ETA这是一个支持多个顶级目标的版本.

TOPTARGETS := all clean

SUBDIRS := $(wildcard */.)

$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@ $(MAKECMDGOALS)

.PHONY: $(TOPTARGETS) $(SUBDIRS)
Run Code Online (Sandbox Code Playgroud)

  • 如果我还想要清洁目标怎么办? (4认同)
  • 为什么 $(SUBDIRS) 在 .PHONY 中?那是因为目录修改日期/时间无关紧要吗?我有这个问题,因为目录不是假的。.PHONY 应该用于虚假目标。 (2认同)
  • @shuva 您很可能希望在子目录中运行 makefile,无论子目录是否已更改,因为该 makefile 可能有自己的虚假目标 (2认同)

avi*_*nat 6

尝试这个 :

SUBDIRS = foo bar baz

subdirs:
    for dir in $(SUBDIRS); do \
        $(MAKE) -C $$dir; \
    done
Run Code Online (Sandbox Code Playgroud)

这可以帮助您链接

编辑:您也可以这样做:

最简单的方法是:

CODE_DIR = code

.PHONY: project_code

project_code:
       $(MAKE) -C $(CODE_DIR)
Run Code Online (Sandbox Code Playgroud)

.PHONY规则表示project_code不是需要构建的文件,并且-C标志指示目录更改(等同于在调用make之前运行cd代码)。您可以使用相同的方法在代码Makefile中调用其他目标。

例如:

clean:
   $(MAKE) -C $(CODE_DIR) clean
Run Code Online (Sandbox Code Playgroud)

资源

  • 其实我不想在makefile中有目录列表 (2认同)

Aar*_*urs 6

这是MadScientist 回答的另一种方法。.PHONY是 GNU 特定的功能,可用于强制make递归到每个子目录。但是,某些非 GNU 版本make不支持.PHONY,因此替代方法是强制目标

4.7 无配方或先决条件的规则

如果规则没有先决条件或配方,并且规则的目标是一个不存在的文件,则 make 会认为该目标在其规则运行时已更新。这意味着依赖于该目标的所有目标将始终运行其配方。

一个例子将说明这一点:

clean: FORCE
        rm $(objects)
FORCE:
Run Code Online (Sandbox Code Playgroud)

这里目标“FORCE”满足特殊条件,因此依赖于它的目标清理被迫运行其配方。“FORCE”这个名字没有什么特别之处,但这是一个常用的名字。

如您所见,以这种方式使用 'FORCE' 与使用 '.PHONY: clean' 的结果相同。

使用“.PHONY”更加明确和高效。但是,其他版本的 make 不支持“.PHONY”;因此'FORCE' 出现在许多makefile 中。请参阅虚假目标。

以下是递归make到每个子目录的最小示例,每个子目录大概包含一个Makefile. 如果您只是运行make,则只会处理不确定的第一个子目录。您也可以运行make subdir1 subdir2 ....

clean: FORCE
        rm $(objects)
FORCE:
Run Code Online (Sandbox Code Playgroud)

这是另一个带有顶级虚假目标的示例:allclean. 请注意,allclean目标,通过从命令行传递$(MAKECMDGOALS),由每个子目录的处理allclean目标分别。

# Register all subdirectories in the project's root directory.
SUBDIRS := $(wildcard */.)

# Recurse `make` into each subdirectory.
$(SUBDIRS): FORCE
        $(MAKE) -C $@

# A target without prerequisites and a recipe, and there is no file named `FORCE`.
# `make` will always run this and any other target that depends on it.
FORCE:
Run Code Online (Sandbox Code Playgroud)