如何使Makefile只重新编译更改的文件?

我一直在挣扎一下让编译只有编辑的文件。 但是,我没有太多的成功,所有的文件得到重新编译。 有人能解释我为什么吗?

我的文件是:

main.c a_functions.c 

其中main.c包含main.h,a_functions.c包含ah

这是我的makefile:

 CC=gcc CFLAGS=-Wall -I. -c EXEC_FILE=program1 all: program a_functions.o: a_functions.c a_functions.c: ah main.o: main.c main.c: main.h objects: a_functions.c main.c $(CC) a_functions.c main.c $(CFLAGS) program: a_functions.o main.o $(CC) a_functions.o main.o -o $(EXEC_FILE) 

根据build议更改生成文件似乎有相同的问题::

 all: program a_functions.o: a_functions.c ah gcc a_functions.c -c main.o: main.c main.h gcc main.c -c program: a_functions.o main.o gcc a_functions.o main.o -o program1 

你正在谈论的具体问题 – 即使没有任何改变,重build程序1(通过重新链接对象) – 是在这个规则:

 program: a_functions.o main.o gcc a_functions.o main.o -o program1 

这个规则的目标是program ,并且假定它是一个文件。 但由于没有这样的文件,每次运行Make,Make都认为这个文件需要重build,并执行规则。 我build议这样做:

 program1: a_functions.o main.o gcc a_functions.o main.o -o program1 

或者更好,这个:

 program1: a_functions.o main.o gcc $^ -o $@ 

或者更好的是这个:

 $(EXEC_FILE): a_functions.o main.o $(CC) $^ -o $@ 

(不要忘记改变all规则来匹配。)

其他几点:

  1. 正如@paxdiablo指出的那样,

     a_functions.o: a_functions.c ah main.o: main.c main.h 
  2. 把这些对象链接在一起是没有意义的,除非在其中一个(可能是main.o )调用另一个(可能是main.o )的东西,所以我期望看到这样的依赖:

     main.o: ah 

    所以我怀疑你有一些错误的声明。

  3. 你声明了一个objects规则,但从来没有引用它。 所以你从来没有真正使用它; Make使用%.o: %.c . %.o: %.c的默认规则。 我build议这样做:

     OBJECTS = a_functions.o main.o $(OBJECTS): %: %.c $(CC) $< $(CFLAGS) -o $@ 

    (在这种情况下,您可以将$(EXEC_FILE): a_functions.o main.o$(EXEC_FILE): $(OBJECTS) 。)或者只是这样:

     %.o: %.c $(CC) $< $(CFLAGS) -o $@ 

不知道这是否导致您的具体问题,但两条线:

 a_functions.c: ah main.c: main.h 

肯定是错误的,因为通常没有命令来重新创build一个基于它包含的头文件的C文件。

C文件不依赖于它们的头文件,这些C文件创build的对象可以。

例如,一个main.c的:

 #include <hdr1.h> #include <hdr2.h> int main (void) { return 0; } 

会在makefile中像这样:

 main.o: main.c hdr1.h hdr2.h gcc -c -o main.o main.c 

更改:

 a_functions.o: a_functions.c a_functions.c: ah main.o: main.c main.c: main.h 

至:

 a_functions.o: a_functions.c ah main.o: main.c main.h 

(假设a_functions.c包含ahmain.c包含main.hmain.h试。

如果上面的假设是错误的,那么您将不得不告诉我们什么C文件包含什么头文件,以便我们可以告诉您正确的规则。


如果你的争论是即使在这些改变之后makefile仍然在构build一切,你需要看两件事情。

首先是所有相关文件的ls -l输出,以便您可以查看它们的date和时间。

第二个是make的实际输出。 make -d的输出会特别有帮助,因为它显示了使用什么文件和date来确定要做什么。


在调查方面,根据以下成绩单, make似乎可以正常工作:

 ===== pax$ cat qq.h #define QQ 1 ===== pax$ cat qq.c #include "qq.h" int main(void) { return 0; } ===== pax$ cat qq.mk qq: qq.o gcc -o qq qq.o qq.o: qq.c qq.h gcc -c -o qq.o qq.c ===== pax$ touch qq.c qq.h ===== pax$ make -f qq.mk gcc -c -o qq.o qq.c gcc -o qq qq.o ===== pax$ make -f qq.mk make: `qq' is up to date. 
Interesting Posts