【问题标题】:Building dependencies by a recursive call to make?通过递归调用建立依赖关系?
【发布时间】:2018-06-22 23:29:25
【问题描述】:

我读过一些文章,解释了在使用子目录编译项目的情况下,递归 makefile 是多么邪恶。

但是,我发现了这种自动生成依赖项的方便方法

exec = main
objs  = main.o A.o B.o C.o   # main and object modules

deps = $(objs:.o=.d)         # dependencies file

all: $(deps)
    $(MAKE) $(exec)

-include $(deps)

%.d: %.c                        # how to build dependency files
    $(CC) -MM $(CFLAGS) $< > $@

main: $(objs)          # How to build the main exec

如果需要,构建目标“all”会更新依赖文件,然后在需要时考虑重新构建主 exec。

这种方法是否存在根本缺陷?

【问题讨论】:

  • 只是关于“被认为有害”的论文的注释:许多人在标题中认为不应该使用递归,但这实际上并不是论文所谈论的。它讨论了将依赖关系图拆分为多个 makefile 是如何不好的。但是,在某些情况下,递归不会这样做(例如,在您的情况下,您正在构建一套与主要对象分开的先决条件)。递归可以是一个强大的工具,不应该只是根据标题扔掉......就像大多数强大的工具一样,使用它的方法是正确的和错误的。

标签: c makefile


【解决方案1】:

如果您使用的是 GNU make,那么这个 hack 是不必要的。 GNU make 是smart enough 自动重建包含的任何(make)文件,然后自行重启:

由于“.d”文件和其他文件一样是 makefile,make 将根据需要重新制作它们,而无需您做进一步的工作。见Remaking Makefiles

关于其他 make 实现,GNU make 手册有这样的说法:

对于旧的 make 程序,传统做法是使用 [-M] 编译器功能通过“make depend”之类的命令按需生成先决条件。该命令将创建一个包含所有自动生成的先决条件的文件。然后makefile 可以使用include 来读取它们(参见Include)。

【讨论】:

【解决方案2】:

正如其他贡献者所说,gnu make 将 .d 依赖文件视为 Makefile 并在需要时自动重建它们。

这使得递归调用变得不必要了,问题也就解决了。

当然,像往常一样,“被认为有害”的论文标题必须用一粒盐来阅读,如果真的阅读的话,从悠久的传统(Knuth 对 Dijkstra 论文的“反驳”引用了 Disjktra 自己害怕被相信非常教条”和“其他人将其奉为宗教”。“狂热的拥护者越过董事会”!)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 2019-10-18
    相关资源
    最近更新 更多