我正在尝试编写一个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/
,否则我会得到“没有规则来制作目标”。从好的方面来说,我可以轻松地使用prog
目标中的patsubst来指定目标文件。
第二种方法类似,但在OBJ
变量上使用vpath和文本替换:
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
(因为我不能在没有基础的目标文件上做任何patsubst)。
这两种方法都有效,每种方法都有其优势,但哪种方法是“正确的”方法,如果不是,那么实现这种建筑的正确方法是什么?
答案 0 :(得分:21)
你的第一个例子就在那里:
SRC = $(wildcard src/*.cpp)
OBJ = $(patsubst src/%.cpp, obj/%.o, $(SRC))
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o prog
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $< -o $@