我想创建一个Makefile,根据调用的目标,在不同的文件夹中构建对象文件。
例如,我希望当我使用目标make
调用target1
时,它会在调用时使用名为“obj/t1
”和“obj/t2
”的文件夹创建对象target2
。
我创建了这个小Makefile:
.PHONY=target1 target2 clean setup
SOURCE_ROOT_FOLDER := src
SOURCES := $(shell find $(SOURCE_ROOT_FOLDER) -iname "*.cpp")
OBJ_ROOT_FOLDER := obj
target1:SUB_OBJ_FOLDER := t1
target2:SUB_OBJ_FOLDER := t2
OBJECTS = $(subst $(SOURCE_ROOT_FOLDER), $(OBJ_ROOT_FOLDER)/$(SUB_OBJ_FOLDER), \
$(SOURCES:.cpp=.o))
$(OBJ_ROOT_FOLDER)/$(SUB_OBJ_FOLDER)/%.o: $(SOURCE_ROOT_FOLDER)/%.cpp
@echo "Creating subfolder $(OBJ_ROOT_FOLDER)/$(SUB_OBJ_FOLDER)"
mkdir -p $(dir $@)
@echo "Compiling $< to obj file: $@"
touch $@
target1: $(OBJECTS)
@echo Files $(OBJECTS) have been compiled!
target2: $(OBJECTS)
clean:
rm -rf $(OBJ_ROOT_FOLDER)
setup:
@mkdir -p src
@mkdir -p src/classA
@mkdir -p src/classB
@touch src/file.cpp
@touch src/classA/fileA.cpp
@touch src/classB/fileB.cpp
您可以调用setup
目标来重现文件夹中的简单虚假项目并自行执行。
make target1
的输出是:
Creating subfolder obj/t1
mkdir -p obj//classB/
Compiling src/classB/fileB.cpp to obj file: obj//classB/fileB.o
touch obj//classB/fileB.o
Creating subfolder obj/t1
mkdir -p obj//classA/
Compiling src/classA/fileA.cpp to obj file: obj//classA/fileA.o
touch obj//classA/fileA.o
Creating subfolder obj/t1
mkdir -p obj//
Compiling src/file.cpp to obj file: obj//file.o
touch obj//file.o
Files obj/t1/classB/fileB.o obj/t1/classA/fileA.o obj/t1/file.o have been compiled!
因为你可以看到变量SUB_OBJ_FOLDER
在配方中以正确的方式设置,但它似乎在目标中未定义(因为@
扩展为空字符串),即使OBJECTS
变量在target1
规则中正确扩展(因为您可以检查输出中写入的最终文本)。
所以我无法理解为什么变量SUB_OBJ_FOLDER
似乎没有使用调用此规则的父目标进行扩展。
答案 0 :(得分:1)
您SUB_OBJ_FOLDER
和target1
的变量target2
确实设置正确,但未在这些目标之外设置。这意味着makefile目标$(OBJ_ROOT_FOLDER)/$(SUB_OBJ_FOLDER)/%.o
始终扩展为obj//%.o
。
假设您将始终将此makefile与一个make target(target1
或target2
)一起使用,解决方案是使用MAKECMDGOALS
变量来设置SUB_OBJ_FOLDER
。这将是你的makefile中的变化:
#target1:SUB_OBJ_FOLDER := t1
#target2:SUB_OBJ_FOLDER := t2
SUB_OBJ_FOLDER := $(MAKECMDGOALS:target%=t%)
如果要在命令行上同时支持target1
和target2
,它将会更复杂,并且需要为每个感兴趣的目标包含一个辅助makefile。