如何让Makefile重新编译已更改的文件?

时间:2011-10-19 00:49:32

标签: c makefile recompile

我一直在努力让make只编译已经编辑过的文件。但是我没有太大成功,所有文件都被重新编译。有人能解释我为什么吗?

我的档案是:

main.c
a_functions.c

其中 main.c 包含 main.h a_functions.c 包括 a.h

这是我的makefile:

CC=gcc
CFLAGS=-Wall -I. -c
EXEC_FILE=program1


all: program

a_functions.o: a_functions.c
a_functions.c: a.h
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)

根据建议改变makefile似乎也有同样的问题::

all: program

a_functions.o: a_functions.c a.h
    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

3 个答案:

答案 0 :(得分:75)

您正在讨论的具体问题 - 即使没有任何更改,也要重建program1(通过重新链接对象) - 在此规则中:

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

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

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 a.h
    main.o: main.c main.h
    
  2. 将这些对象链接在一起是没有意义的,除非一个(可能是main.o)中的某个东西调用另一个(可能是a_functions.o),所以我希望看到一个像这样的依赖:

    main.o: a.h
    

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

  3. 您声明了objects规则,但从未引用它。所以你永远不会真正使用它; Make使用%.o: %.c的默认规则。我建议这个:

    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 $@
    

答案 1 :(得分:11)

不确定这是否导致您的具体问题,但两行:

a_functions.c: a.h
main.c: main.h

肯定是错误的,因为通常没有命令根据它包含的标题重新创建C文件。

C文件不依赖于它们的头文件,这些C文件创建的对象

例如,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: a.h
main.o: main.c
main.c: main.h

为:

a_functions.o: a_functions.c a.h
main.o: main.c main.h

(假设a_functions.c包含a.hmain.c包含main.h),然后重试。

如果上述假设错误,您必须告诉我们哪些C文件包含哪些标题,以便我们告诉您正确的规则。


如果您的争论是makefile即使在这些更改之后仍在构建所有内容,那么您需要查看两件事。

第一个是ls -l在所有相关文件上的输出,以便您可以查看他们拥有的日期和时间。

第二个是make的实际输出。 make -d的输出特别有用,因为显示 make正在使用哪些文件和日期来确定要执行的操作。


在调查方面,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.

答案 2 :(得分:0)

事后很晚,实际上是基于paxdiablo的出色回答,但是在进行实验时,我发现您不需要为每个.o文件使用单独的目标,除非您做一些聪明的事情。

对于我的makefile:

all: program

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

clean: 
    rm -f *.o
    rm -f program

在make 4.1中,它会自动编译.o文件,如果您的.o文件具有与源文件相同的名称,则您无需执行任何操作。因此,它将自动搜索a_functions.c,a_functions.h,main.h和main.c。如果您没有所需的源代码名称,则会收到类似以下错误:

make: *** No rule to make target 'a_functions.o', needed by 'program'.  Stop.

我还为您添加了一个“干净”目标。如果您需要将软件作为源代码发布,或者只想删除所有已编译的目标文件和/或二进制文件,则“清理”很有用。

这就是您需要做的。

将其保存到“ Makefile”并运行:

$ make

构建您的二进制文件。还有

$ make clean 

清理代码中的编译对象和二进制文件。