c - 递归生成文件未构建

标签 c recursion makefile

我在不同的目录中有一堆 C 文件,并且我的递归 Makefile 出现 make: Nothing to be do for 'all' 错误;但是,如果我调整依赖关系,我可以让它工作......但我不明白为什么我必须这样做。

这是我原来的 Makefile:

APP_DIRS=rescoco ressys resvm

.PHONY: all

all: $(APP_DIRS)

$(APP_DIRS):
    $(MAKE) --directory $@

clean:
    $(RM) *~

现在,如果我将行: .PHONY 更改为 .PHONY: all $(APP_DIRS) ,它就可以正常构建。

另一种可能性是,如果我将行: $(APP_DIRS): 更改为 $(APP_DIRS): clean ,则可以正常构建。

(注意:删除 .PHONY 目标不会改变任何内容)


那么这是怎么回事呢? Makefile 是否试图告诉我我没有正确列出依赖项?我想 make 会做类似的事情:

  • 要构建.PHONY,我首先必须构建all
  • 要构建all,我首先必须构建$(APP_DIRS)
  • $(APP_DIRS) 没有先决条件,因此执行该命令(这将导致递归 make 运行)。

显然我错了;但为什么?

<小时/>

仅供引用,如果重要的话,我的文件结构如下:

Makefile       #top level makefile as seen above
/rescoco
    rescoco.c
    Makefile   #builds rescoco src and moves archive to ../lib directory
/ressys
    ressys.c
    Makefile   #same as above but for ressys
/resvm
    resvm.c
    Makefile   #same as above but for resvm
/lib

我的构建命令只是make。当我使用 make -nmake -n all 运行时,我根本没有得到任何输出:

:~/proj$ make -n all
make: Nothing to be done for 'all'.
:~/proj$ 

最佳答案

您首先应该注意的事情:

  • 如果您有目录作为依赖项,则仅当目录的修改时间戳更新时,make 才会考虑构建目标(即执行此类目录目标的配方)。 仅当您在目录中添加新文件时才会发生这种情况,但在目录中修改文件时不会发生这种情况。在子目录中添加文件不会更改目录的时间戳。
  • PHONY 目标适用于执行此类目标时不会创建具有目标名称的文件。换句话说,无论文件是否存在,您都希望 make 执行该规则。

所以你的 Makefile 本质上只告诉了这一点:

  • 构建目标 all ,我需要构建$(APP_DIRS) 。自 all是一个假目标,我将始终执行 all 的配方.
  • $(APP_DIRS)不是PHONY目标并且没有任何依赖关系。所以*仅当 $(APP_DIRS)尚不存在(即文件或目录),我将执行该配方,否则我不会对此目标执行任何操作。
  • clean没有先决条件,也不是 PHONY ,所以我希望仅在由 make 显式调用时(从命令行或另一个 Makefile)执行此规则。另外clean不是PHONY ,所以我希望配方创建一个名为 clean 的文件执行后(这对您的情况不正确)

因此更改.PHONY行至:

.PHONY: all $(APP_DIRS)

使 Makefile 始终执行 $(APP_DIRS) 的配方。

因此,如果您希望 make 始终遍历所有 $(APP_DIRS) 目录并在它们上再次调用 make,则需要添加 $(APP_DIRS).PHONY ,这使得 $(APP_DIRS) 成为 PHONY 目标,并执行配方,而不管文件/目录的时间戳(如果存在)。

对于您的特定用例,我认为这是您应该使用的 Makefile:

APP_DIRS=rescoco ressys resvm

.PHONY: all clean $(APP_DIRS)

all: $(APP_DIRS)

$(APP_DIRS):
    $(MAKE) --directory $@

clean:
    $(RM) *~

奖金:

  • 改变$(APP_DIRS):$(APP_DIRS): clean意味着$(APP_DIRS)取决于clean目标。
  • 虽然clean未标记为 PHONY,make 不会看到名为 clean 的文件在当前目录中。因此它继续尝试执行 clean 的配方。 .
  • 由于 $(APP_DIRS) 的依赖项(即 clean )已构建,这使得 Makefile 执行构建 $(APP_DIRS) 的配方。

这给我们带来了一个有趣的观察: - 任何依赖于 PHONY 目标的目标都将始终被重建(即配方将被执行)。

采用这个简单的 Makefile:

all: target1

target1: target2
    @echo "$@"
    @touch $@

target2: target3
    @echo "$@"
    @touch $@

target3:
    @echo "$@"

.PHONY: all target3

第一次运行make ,我看到这个输出:

target3
target2
target1

此后,文件 target1target2被创建。即使如此,如果我运行 make再次,我会看到输出:

target3
target2
target1

如您所见,PHONY依赖关系向上传播,而不是向下传播。 target2被重建只是因为 target3是假冒的,并且 target1被重建只是因为 target2已重建。

关于c - 递归生成文件未构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15554172/

相关文章:

python - 从 strace 输出中提取唯一的系统调用名称(通过正则表达式?)

c - 进行 64 位无符号整数除法时如何管理 65 位分配?

list - 递归处理列表和列表的子列表给出类型不匹配

python - 是否有一种非递归方法将每个列表元素分成自己的列表?

python - 无法弄清楚如何内存子集函数

java - 尝试使用 JNI : libjvm. 在 C++ 代码中使用 jar 时出错,因此未找到

linux - 当 Make 存在最终目标时如何不重新制作先决条件

c - 仅 C 语言实现(私有(private))常量是否有命名约定?

c - 为什么没有错误显示此代码在 C 中?

c++ - 移动 cmake 发布和调试文件夹