2016-12-14 94 views
0

是否有简单的方法将单个配方应用于多个模式规则?Makefile多个模式的单个配方

考虑这个目录结构

|- src 
| - file1.cpp 
|- test 
| - file2.cpp 
| - file3.cpp 
| - metrics 
| - file4.cpp 
| - file5.cpp 

我想编写一个模式规则来编译test目录下的所有.cpp文件。这里是我现在有:

$(OBJS)/%.o: test/%.cpp 
    @mkdir -p $(OBJS) 
    g++ $(FLAGS) $(CPPFLAGS) -c $< -o [email protected] 

$(OBJS)/%.o: test/metrics/%.cpp 
    @mkdir -p $(OBJS) 
    g++ $(FLAGS) $(CPPFLAGS) -I test -c $< -o [email protected] 

TEST_CPP := $(wildcard test/*.cpp) $(wildcard test/**/*.cpp) 
TEST_OBJ := $(addprefix $(OBJS)/,$(notdir $(TEST_CPP:.cpp=.o))) 

$(BIN)/testRunner: $(TEST_OBJ) 
    @mkdir -p $(BIN) 
    g++ $(FLAGS) $(CPPFLAGS) $^ $(LIBS) -o [email protected] 

我想避免重复的目标文件的食谱。我想象中的解决方案将是这个样子:

$(OBJS)/%.o: test/%.cpp 
$(OBJS)/%.o: test/metrics/%.cpp 
    @mkdir -p $(OBJS) 
    g++ $(FLAGS) $(CPPFLAGS) -c $< -o [email protected] 

(目前,该OBJ文件目录是平的,但是,我没有问题,复制源目录结构,如果他们简化了生成文件。)

回答

3

没有办法做到你想要的。你可以得到的最接近的是把配方到一个变量,并使用相同的变量每个配方,像这样:

define BUILD_O 
     @mkdir -p $(OBJS) 
     g++ $(FLAGS) $(CPPFLAGS) -c $< -o [email protected] 
endef 

$(OBJS)/%.o : test/%.cpp 
     $(BUILD_O) 
$(OBJS)/%.o : test/metrics/%.cpp 
     $(BUILD_O) 

作为替代,因为你希望所有的对象去到同一个目录但在不同的目录找货源,你可以使用VPATH而不是写只是一个单一的模式规则,就像这样:

VPATH = test test/metrics 

$(OBJS)/%.o : %.cpp 
     @mkdir -p $(@D) 
     g++ $(FLAGS) $(CPPFLAGS) -c $< -o [email protected] 

我强烈建议你返工你的makefile文件使用标准的变量名,虽然,使用$(CXX),不g++,对于C++编译器的名称和$(CXXFLAGS),不$(FLAGS),对于C++编译器选项。

编辑

如果您需要自定义标记,然后以正常的方式来做到这一点无论是通过target-specific variables,或通过constructed macro names

目标特定的变量应该是这样的:

test: $(test_targets) 
test: FLAGS += -Dtest 

production: $(production_targets) 
production: FLAGS += -Dproduction 

那么当您运行make test你会得到-Dtest增加;当你运行make production时,你会得到-Dproduction。这里有一些问题:如果你运行make myfoo.o那么你不会得到这些(见文档)。

构建宏名应该是这样的:

test_FLAGS = -Dtest 
production_FLAGS = -Dproduction 

rootdir = $(firstword $(subst /, ,$1)) 

VPATH = test test/metrics production production/widgets 

$(OBJS)/%.o : %.cpp 
     @mkdir -p $(@D) 
     g++ $(FLAGS) $(CPPFLAGS) $($(call rootdir,$(<D))_FLAGS) -c $< -o [email protected] 
+0

是否有适用VPATH只有一定的规则的方法吗?假设我想为“test”.o文件使用不同的标志/库/包含,而不是“产品”.o文件。我可以为'$(OBJS)/ test /%。o'和'$(OBJS)/ production /%。o'设置不同的模式规则。但是,有没有办法将'$(OBJS)/ test'中的.o文件的模式匹配限制为'/ test'中的源文件? – Zack

+0

'VPATH'是全局的,但你可以使用'vpath $(OBJS)/ test /%。o test'这样的'vpath'指令(同样也适用于生产)。 –

+0

你不能像这样使用'vpath':'vpath'中的模式适用于你正在寻找的名字列表,而不是目标列表。换句话说,你的例子告诉make应该在'test'中查找.o文件,而不是'.cpp'文件。 – MadScientist