避免使用 makefile 进行不必要的重新编译
Posted
技术标签:
【中文标题】避免使用 makefile 进行不必要的重新编译【英文标题】:Avoiding unecessary recompilation with makefile 【发布时间】:2015-02-27 19:28:51 【问题描述】:我正在使用带有 gcc 的 makefile。每个 c 文件都有一个随附的标题:
main.c main.h test.c test.h
main.c 包括 main.h 和 test.h
test.c 包含 test.h
我想避免重新编译每个 c 文件。 Makefile 在没有 -B 参数的情况下运行。
我可以手动编写整个 makefile 并指定每个依赖项。编辑头文件时,仅重新编译必要的 c 文件。 test.h 中的编辑将重新编译这两个 c 文件,而 main.h 中的更改只会重新编译 main.c。应该的。
当我切换到更自动化的方法时,这不起作用:
OBJ = main.o test.o
%.o: %.c %.h
$(CC) -c -o $@ $<
main: $(OBJ)
$(CC) -o main $(OBJ)
test.h 中的更改只会重新编译 test.c。使用旧版本的 test.h 标头将 main.c 留在旧版本中。如果我想使用这种方法,我不得不使用 -B 运行 makefile。
我可以手动指定标题:
DEPS = main.h sort.h
%.o: %.c $(DEPS)
$(CC) -c -o $@ $<
然后在 main.h 中的更改重新编译 main.c 和 test.c,后者是不必要的。
如果我有很多文件,更新 makefile 中的每一个更改是很麻烦的,并且使用自动化方法会增加编译时间。
是否有更好的解决方案,仅重新编译所需文件,或者手动指定所有内容的唯一方法?
【问题讨论】:
查找 gcc 选项以根据包含文件输出 Makefile 依赖项。 make.mad-scientist.net/papers/… @chqrlie 抱歉,这对我来说是个死胡同,我是 make&gcc 的新手,因此在这里寻求建设性的答案。 如果您无法按照示例进行自动依赖跟踪,那么最后一段中您的问题的答案是“没有更好的解决方案(您能够实现),所以手动指定是唯一的方法”。 @MadScientist 不,我无法跟踪很长的外部链接,因为我不知道自动依赖跟踪具体是什么。这就是我在这里问的原因。我虽然这是一个问答网站。 【参考方案1】:您可以使用另一行指定main.o
的其他依赖项:
OBJ = main.o test.o
main.o: test.h
【讨论】:
我得到一个错误:没有规则来制作目标'test.h','main.o'需要。停止 我从您的帖子中了解到,您有文件main.h
、main.c
、test.h
和 test.c
。这不是真的吗?
没关系我有错字:-(。谢谢你这解决了我的问题。
请注意,如果您创建的 .c
文件没有使用相同前缀的关联头文件(例如,foo.c
但没有 foo.h
),则此 makefile 将失败。
【参考方案2】:
但是,如果您决定手动指定,那么您做错了;您不想将依赖项添加到对 every 对象文件生效的模式中。您为每个目标文件单独定义它,因此只有在正确的文件发生更改时才会重新构建它们:
OBJ = main.o test.o
%.o: %.c
$(CC) -c -o $@ $<
main: $(OBJ)
$(CC) -o main $(OBJ)
main.o: main.h test.h
test.o: test.h
维护最后几行是自动生成依赖项所做的工作,如果您决定尝试使用它。
【讨论】:
这有点冗长,但更容易手动维护。这就是大多数人所做的,对于大多数项目来说已经足够了。一旦你掌握了 make 和 C 编译器,你就可以达到 Jedi 级别,可以自动计算行数。我花了 10 多年的时间才最终决定值得付出努力实现自动化。 另一个经常被忽视的依赖是%.o: %.c Makefile
等。每当你改变Makefile时,重新编译所有东西是明智的,以防某些编译选项或命令行定义发生了变化。以上是关于避免使用 makefile 进行不必要的重新编译的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 gprof 的 makefile 重新编译依赖项?