Makefile总是重新编译一个文件

Makefile always recompiling a file

本文关键字:文件 一个 编译 新编译 Makefile      更新时间:2023-10-16

我正在学习如何设置makefiles,并且遇到了一个问题。为了演示这一点,我创建了一个由源文件main.mtest.m组成的简单"项目"。

我试图设置make来编译这些文件(只有当某些东西发生变化时),并将目标文件存储在其他地方(这里是build/)

我的Makefile。

OBJ = ./build
SOURCES=main.m test.m
OBJECTS=$(addprefix $(OBJ)/,$(SOURCES:.m=.o))
EXECUTABLE=test
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
        gcc $(OBJECTS) -o $(EXECUTABLE)
$(OBJECTS): $(OBJ)/%.o: %.m build/
        gcc -c $< -o $@
build/:
        mkdir build

当我第一次运行它时(只有Makefile和当前目录中的源代码),它做了我期望它做的事情:

gcc -c main.m -o build/main.o
gcc -c test.m -o build/test.o
gcc ./build/main.o ./build/test.o -o test

但是,如果我再次运行make:

gcc -c main.m -o build/main.o
gcc ./build/main.o ./build/test.o -o test

我做错了什么?也注意到任何其他错误在Makefile是赞赏的,因为我正在努力学习创建"好的"Makefile。

编辑:

我从make -d中发现的:

Finished prerequisites of target file `build/main.o'.
Prerequisite `main.m' is older than target `build/main.o'.
Prerequisite `build/' is older than target `build/main.o'.
No need to remake target `build/main.o'.

Finished prerequisites of target file `build/test.o'.
Prerequisite `test.m' is older than target `build/test.o'.
Prerequisite `build/' is newer than target `build/test.o'.
Must remake target `build/test.o'.

您的make -d输出显示make认为您的构建目录已被更新,因此需要重新构建该文件。

我猜这是因为在你的构建系统部分的某些操作或在你的文件系统中的其他东西导致该目录上的一些时间戳被更新。

您可以通过在该规则中添加|使build成为仅限订单的先决条件来解决这个问题:

$(OBJECTS): $(OBJ)/%.o: %.m | build

我也删除了/,因为它没有做任何事情。

既然你问了,其他一些编辑注释:

  1. 添加clean目标。比如:

    clean:
        rm -rf $(EXECUTABLE) $(OBJ)
    
  2. 设置OBJ时不需要./。只要OBJ = build就够了。

  3. 您不需要build上的/如上所述。但这并不重要,因为你不应该引用它。将build替换为$(OBJ)

  4. 如果目录已经存在,
  5. mkdir将失败。您可能应该在命令前加上-:

    $(OBJ):
        -mkdir $(OBJ)
    

    请注意,我已经用上面#3中提到的$(OBJ)进行了替换。

  6. 自动生成依赖项非常有用。如图所示,您的项目并不大到真正需要它,但它很容易添加,所以为什么不呢?你需要做几件事。首先,获取适当的依赖文件名:

    DEPFILES = $(addprefix $(OBJ)/,$(SOURCES:.m=.d))
    

    然后让编译器通过添加-MMD标志来生成它们:

    gcc -MMD -c $< -o $@
    

    最后,如果它们可用,通过在makefile的末尾添加一行,将它们包含在makefile中:

    -include $(DEPFILES)