为什么即使我刚编译源代码,我的makefile也会重新编译?

时间:2012-09-24 10:46:27

标签: c makefile

我有一个简单的makefile,可以在Linux上使用p.cgcc文件编译为可执行文件。 p.c文件取决于a.h文件。 我的makefile看起来像这样:

//makefile
CC = gcc

build: p.c a.h
    $(CC) -o out p.c
clean:
    rm -f *.exe
rebuild: clean build

6 个答案:

答案 0 :(得分:6)

您的makefile不会生成它承诺生成的文件,即buildcleanrebuild。由于这些目标不是文件,因此应将其标记为phony targets

.PHONY: build clean rebuild

build目标应为:

build : out

out : p.c a.h
    $(CC) -o $@ p.c

答案 1 :(得分:2)

这部分

build: p.c a.h
    $(CC) -o out p.c

说“我正在编译$(CC)-o out p.c,结果将是一个名为'build'的文件”。由于你骗了make(这会创建out文件),它会尝试再次构建'build'。

这里有Makefile编写器的教训:始终使用$@变量(表示目标)来避免此错误:

out: p.c a.h
    $(CC) -o $@ p.c

有关更多建议,请参阅Paul's Rules for Makefiles

答案 2 :(得分:1)

学习者,这是使用变量存储可执行文件名称的示例。这样,您只需要在Makefile开头的一个位置指定它:

EXECUTABLE = out

.PHONY: build clean rebuild

build: $(EXECUTABLE)

$(EXECUTABLE): p.c a.h
    $(CC) -o $@ p.c

clean:
    rm -f $(EXECUTABLE)

rebuild: clean build

通常,您也可以在变量中列出.c.h个文件,这样您就可以轻松地从构建中添加/删除文件,而无需在Makefile中搜索所有位置他们被使用了。

答案 3 :(得分:0)

Makefile具有一般语法:

target : dependencies
    commands to make target from dependencies

因此,您的Makefile期望使用build目标创建名为build : p.c a.h的文件。 由于每次调用时命令都不会实际生成此文件,因此必须重做命令。

(PS:Linux二进制文件没有.exe扩展名)

答案 4 :(得分:0)

如果您想避免始终重新编译源,那么您的目标应该依赖于对象文件,而不是源文件:

target.exe : p.o
        $(CC) -o $@ $?; 

p.o: p.c a.h
        $(CC) -c $@ $?;

典型的makefile通常没有每个目标文件的显式规则,也不会列出实现和头文件之间的显式依赖关系;你经常会看到像

这样的隐式规则
%.o : %.c 
        $(CC) -c $(CFLAGS) $?;

(其中$?表示该目标的先决条件列表),或者,如果您的项目简单(一个源文件),您甚至不需要它;你通常可以逃脱

全部:目标 target:target.o

假设您有一个名为target.c的文件,上面将使用默认编译器和CFLAGS选项构建target

同样,一个典型的makefile(至少根据我的经验)没有明确列出标头依赖关系;相反,它依赖于编译器选项来自动生成这些依赖关系列表(对于gcc,该选项是-M)。有关示例,请参阅here

答案 5 :(得分:0)

我了解到,“目标”和“输出文件”名称必须完全匹配,以使 make 能够识别是否不需要重新编译。因此,在Windows环境下(如我尝试过mingw32-make.exe make ),应该是这样的:

build.exe: p.c a.h
    gcc -o build.exe p.c

build.exe: p.c a.h
    gcc -o build p.c    # .exe is added automatically to generated file

当调用 make 时,此代码将始终导致重新编译:

build: p.c a.h
    gcc -o build p.c    # target is "build" and it is not the same as "build.exe" which is the output of compilation