如果不存在,如何创建一个创建目录的目标?

How to create a target that creates a directory if it doesn't exist?

在我的 makefile 配置中,所有目标文件都被编译到特定目录中。如果它不存在,编译器会抱怨。我想创建一个 makefile 目标来识别任何目标文件并在任何其他目标 运行 之前创建该目录并实际编译目标文件。

到目前为止,我已经尝试过模式匹配和双冒号规则。

obj: 
    mkdir obj

obj/%.o :: | obj

obj/example.o :: src/example.cc includes/example.hh
    $(build_obj_file) # macro to do the actual job

使用此代码,只有 obj/example.o 的最后一个目标 运行s。我本来希望两个对象目标分别为 运行。

当我用静态 obj/example.o 替换模式匹配时,我得到了想要的结果。此外,当我使用像 obj/example.o : obj/%.o :: obj.

这样的静态模式匹配时

我真的不想包含 obj 作为每个其他目标文件的附加依赖项,也不想为静态模式匹配创建所有目标文件的单独列表。无论哪种方式都非常脆弱且容易出错。

你有什么建议来解决这样的任务?

您不能使用模式规则 "add extra prerequisites" 一组目标。模式规则必须提供配方;如果他们不这样做,那么他们将被视为 delete the pattern rule.

因为您提供的真实 makefile 太少,所以很难提出适合您的解决方案。

如果您想使用 order-only 先决条件,您需要将它们添加到与您的目标匹配的模式规则中:

obj/%.o : src/%.cc | obj
         $(build_obj_file)

否则单独定义前提关系:

obj/example.o: | obj

使用 (GNU) make 和易于理解的规则,或多或少改编自 automake 生成的规则集:

MKDIR_P = mkdir -p

obj/%.o: src/%.cc
    @$(MKDIR_P) $(@D)
    $(COMPILE.cc) -o $@ -c $<

obj/example.o : includes/example.hh

这将为每个 object 文件 $@ 创建目标目录 $(@D),如果目标已经存在,mkdir -p 仍将以 0 退出,因此不会中止目标规则集。

使用 (GNU) make 并稍微难以理解,但规则更有效(obj 目录仅 mkdir -ped 一次):

MKDIR_P = mkdir -p

obj:
    @$(MKDIR_P) $@

obj/%.o: src/%.cc | obj
    $(COMPILE.cc) -o $@ -c $<

obj/example.o : includes/example.hh

| obj 部分将确保目标 object 文件不会仅仅因为有人在 obj/ 中添加或删除了文件并因此更改了 [=15] 而重建=] 目录的时间戳。

$(COMPILE.cc) 行基本上取自 GNU make -p 的输出。

请注意,手动维护 header 依赖项很容易出错,因此应该自动生成,最好由 MadScientist's comprehensively engineered robust method

此外,如果您的 Makefile 使用 GNUmakeism,请考虑重命名它 GNUmakefile

使用 automake,您无法将 object 文件放入特定目录进行编译,但是此问题的 automake 标记似乎是一个错误。