我正在学习如何设置makefile,并遇到了问题。为了证明这一点,我创建了一个由源文件main.m
和test.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'.
答案 0 :(得分:12)
您的make -d
输出显示make
认为您的构建目录已更新,因此需要重建该文件。
我想这是因为你的构建系统部分或文件系统中的其他东西的某些操作导致该目录的某些时间戳被更新。
您可以通过向该规则添加build
,使|
成为仅限订单的先决条件来解决问题:
$(OBJECTS): $(OBJ)/%.o: %.m | build
我也删除了/
,因为它没有做任何事情。
既然你问了一些其他的编辑说明:
添加clean
目标。类似的东西:
clean:
rm -rf $(EXECUTABLE) $(OBJ)
设置./
时,您不需要OBJ
。只需OBJ = build
即可。
如上所述,您不需要/
上的build
。但这并不重要,因为无论如何你不应该把它提到它。无论你在哪里,都可以build
重新$(OBJ)
。
mkdir
将失败。您可能应该使用-
:
$(OBJ):
-mkdir $(OBJ)
请注意,我已使用上面#3中提到的$(OBJ)
替换了。
自动生成依赖项非常有用。你所展示的项目不够大,不足以真正需要它,但它很容易添加,所以为什么不呢。你需要做几件事。首先,获取适当的依赖文件名:
DEPFILES = $(addprefix $(OBJ)/,$(SOURCES:.m=.d))
然后让编译器通过添加-MMD
标志来生成它们:
gcc -MMD -c $< -o $@
最后,如果它们可用,请将它们包含在makefile中,方法是在makefile的末尾添加一行:
-include $(DEPFILES)