12

我正在学习如何设置 makefile,但遇到了问题。为了证明这一点,我创建了一个简单的“项目”,由源文件main.mtest.m.

我正在尝试设置 make 来编译这些文件(仅在发生更改的情况下),并将目标文件存储在其他地方(herebuild/

我的制作文件:

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'.
4

1 回答 1

12

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

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

您可以通过向该规则添加 a来build创建仅限订单的先决条件来解决此问题:|

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

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

既然你问了,其他一些编辑说明:

  1. 添加clean目标。就像是:

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

  3. 您不需要上面提到的/on 。build但这并不重要,因为无论如何您都不应该提及它。替换你看到build$(OBJ)任何地方。

  4. mkdir如果目录已经存在,将会失败。您可能应该为该命令添加前缀-

    $(OBJ):
        -mkdir $(OBJ)
    

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

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

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

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

    gcc -MMD -c $< -o $@
    

    最后,如果它们可用,则将它们包含在您的 makefile 中,方法是在您的 makefile 末尾添加一行:

    -include $(DEPFILES)
    
于 2013-05-24T20:53:40.580 回答