我正在尝试编写一个将源文件和目标文件分开的 Makefile,但我似乎无法找到完成此任务的正确方法。我有两种可行的方法,但我希望有人能指出“正确”的方法来做到这一点。
我的项目被分成一个src
和obj
文件夹,其中 Makefile 与这些文件夹处于同一级别。
第一种方法使用通配符函数查找源文件,src
然后使用文本替换确定对应的目标文件。
SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(patsubst src/,obj/,$(OBJ))
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)
然而,这似乎有效,每次我运行make prog
它都会重新编译所有目标文件。该OBJ
变量必须src/
在所有对象的前面,否则我会得到“没有规则来制作目标”。从好的方面来说,我可以轻松地在目标中使用 patsubstprog
来指定目标文件。
第二种方法类似,但在OBJ
变量上使用 vpaths 和文本替换:
vpath = %.cpp src
vpath = %.o obj
SRC = $(wildcard src/*.cpp)
OBJ = $(subst src/,,$(SRC:.cpp=.o))
POBJ = $(patsubst src/,obj/$(SRC:.cpp=.o))
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(POBJ)
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)
这消除了目标文件的重新编译,但需要我POJB
为prog
目标添加另一个变量(因为我不能只对没有 basedir 的目标文件执行任何 patsubst)。
两种方法都有效,并且每种方法都比另一种具有优势,但是哪一种是“正确”的方法,如果两者都不是,那么实现这种类型的建筑的正确方法是什么?