如何在make中检查目录是否不存在并创建它

23
在我的项目目录中,有一些子目录:code/export/docs/object/make 的作用只是编译来自代码目录的所有文件,并将 .o 文件放入 object 目录中。
问题是我告诉 git 忽略所有的 .o 文件,因为我不想上传它们,所以它也不跟踪 object 目录。实际上,我对此感到满意,我也不希望将 object/ 上传到我的 GitHub 账户中,但是使用当前的解决方案(即 object/ 目录中的简单空文本文件),该目录确实会被上传,并且在构建之前需要存在(makefile 只是假定它存在)。
这似乎不是最佳解决方案,所以有没有一种方法可以在构建 makefile 之前检查目录是否不存在并在必要时创建它?这将允许在调用 make 命令时不存在 object 目录,并在此后创建它。
4个回答

35

唯一正确的方法是使用仅限顺序先决条件,请参见: https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html。注意片段中的 |

如果您不使用仅限顺序先决条件,则该目录中的每个修改(例如复制或创建文件)都会再次触发依赖于目录创建目标的规则!

object/%.o: code/%.cc | object
    compile $< somehow...

object:
    mkdir -p $@

2
好点子!这样只有在不存在时才会创建它,而不是每次执行规则时都尝试创建(对于每个对象文件)。 - Alexandro de Oliveira

23

只需要对它设置一个目标:

object/%.o: code/%.cc object
    compile $< somehow...

object:
    mkdir $@

如果您想防止出现名为“object”的文件,则需要更加小心,但这是基本想法。


11
通常最好使用一个仅限于顺序的前置条件来实现这一点(也就是说,使用code/%.cc | object),以便object不会影响$^ - Idelic
@Idelic:很棒的技巧,我不知道$^不包括仅限顺序先决条件。谢谢! - Beta
所以,我不能例如有一个名为“debug”的目标和一个名为“debug”的文件夹... - iheanyi
该代码无法按照预期工作,因为当添加任何对象到该目录中时,对象目录的时间戳会发生变化。请参考其他答案。 - mookid

20

在目标中插入一个mkdir命令。

object/%.o : code/%.cc
    @mkdir -p object
    compile $< somehow...

'-p'选项会在目录已经存在的情况下不报错。


可行但不够优化:每次都会 fork 一个 shell 进程,而不是只在需要时才进行。 - MarcH

1
您可以使用$(@D)变量来创建目标目录。$(@D)指的是目标文件所在的目录。因此,您可以使用以下代码:
out/%.o: src/%.c
    mkdir -p $(@D)
    $(CC) $^ -o $@

如果文件夹是一个变量,那么这也非常有效,例如:

OBJ:=objects

$(OBJ)/%.o: src/%.c
   mkdir -p $(@D)
   $(CC) $^ -o $@

使用$(@D)可以更改OBJ变量,而无需在配方中同时更改mkdir行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接