Gcc Makefile:将具有相同前缀的多个目标合并为一个目标
我有一个Gcc Makefile:将具有相同前缀的多个目标合并为一个目标,gcc,makefile,Gcc,Makefile,我有一个makefile,其中有多个目标使用相同的前缀命名,如下所示: STR_COMPRESS_SRCS:=string_compress.cpp UTEST_UTIL_SRCS:=string_parser.cpp UTEST_COM_SRCS:=utest_main.cpp \ $(UTEST_UTIL_SRCS) \ $(STR_COMPRESS_SRCS) UTEST_COM_OBJS=$(UTEST_COM_SRCS:
makefile
,其中有多个目标使用相同的前缀命名,如下所示:
STR_COMPRESS_SRCS:=string_compress.cpp
UTEST_UTIL_SRCS:=string_parser.cpp
UTEST_COM_SRCS:=utest_main.cpp \
$(UTEST_UTIL_SRCS) \
$(STR_COMPRESS_SRCS)
UTEST_COM_OBJS=$(UTEST_COM_SRCS:.cpp=.o)
UTEST_FLAGS=-DUNIT_TEST -DGTEST_USE_OWN_TR1_TUPLE=0
UTEST_SERVER_QUERIER_SRCS:=ServerQuerier.cpp \
ServerQuerierTest.cpp
UTEST_SERVER_QUERIER_OBJS:=$(UTEST_SERVER_QUERIER_SRCS:.cpp=.o)
UTEST_SERVER_QUERIER_NAME:=utest_serverquerier
UTEST_SERVER_PROTO_SRCS:=ServerProtocol.cpp \
ServerProtocolTest.cpp
UTEST_SERVER_PROTO_OBJS:=$(UTEST_SERVER_PROTO_SRCS:.cpp=.o)
UTEST_SERVER_PROTO_NAME:=utest_serverprotocol
%.o: %.cpp
$(CXX) -std=c++0x -c $< -o $@ $(INC) $(UTEST_FLAGS)
utest_all: utest_serverquerier utest_serverprotocol
utest_serverquerier: $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS) -o $(UTEST_SERVER_QUERIER_NAME) -pthread -lgtest -lgmock -L. $(LIB)
utest_serverprotocol: $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS) -o $(UTEST_SERVER_PROTO_NAME) -pthread -lgtest -lgmock -L. $(LIB)
clean:
-@rm *.o utest_*
STR\u COMPRESS\u SRCS:=string\u COMPRESS.cpp
UTEST_UTIL_SRCS:=字符串_parser.cpp
UTEST_COM_SRCS:=UTEST_main.cpp\
$(UTEST\U UTIL\U SRCS)\
$(STR\u COMPRESS\u SRCS)
UTEST_COM_OBJS=$(UTEST_COM_SRCS:.cpp=.o)
UTEST_FLAGS=-DUNIT_TEST-DGTEST_USE_OWN_TR1_TUPLE=0
UTEST_服务器_查询器_SRCS:=serverqueryer.cpp\
ServerQuerierTest.cpp
UTEST\u服务器\u查询器\u对象:=$(UTEST\u服务器\u查询器\u SRCS:.cpp=.o)
UTEST_服务器\u查询器\u名称:=UTEST_服务器查询器
UTEST_服务器\u协议\u SRCS:=ServerProtocol.cpp\
ServerProtocolTest.cpp
UTEST_服务器\u协议\u对象:=$(UTEST_服务器\u协议\u SRCS:.cpp=.o)
UTEST_服务器\u协议名称:=UTEST_服务器协议
%.o:%.cpp
$(CXX)-std=c++0x-c$<-o$@$(INC)$(UTEST_标志)
utest\U all:utest\U服务器查询器utest\U服务器协议
utest_服务器查询器:$(utest_COM_OBJS)$(utest_服务器查询器_OBJS)
$(CXX)-std=c++0x$(CXXFLAGS)$(UTEST_COM_OBJS)$(UTEST_服务器_查询器_OBJS)-o$(UTEST_服务器_查询器_名称)-pthread-lgtest-lgmock-L.$(LIB)
utest\u服务器协议:$(utest\u COM\u OBJS)$(utest\u服务器\u协议\u OBJS)
$(CXX)-std=c++0x$(CXXFLAGS)$(UTEST_COM_OBJS)$(UTEST_服务器_协议_OBJS)-o$(UTEST_服务器_协议_名称)-pthread-lgtest-lgmock-L.$(LIB)
清洁:
-@rm*.o OUTEST_*
现在我想创建一个名为utest\u all
的单一目标,这样当我键入make utest\u all
时,所有目标utest\u*
都将生成多个与目标同名的输出文件
注意:可以有许多utest.*
更新:
- 添加了
utest\u all
- 添加了
UTEST\u XXX\u名称
makeutest\u all
时,make
将帮助构建指定为utest\u all
依赖项的所有目标。但问题是,如果我为一个新类添加单元测试(例如,querymanagertest.cpp
),那么我必须做以下三件事:
- 定义指定的变量:源文件(例如
),对象(例如UTEST\u queryer\u MANAGER\u SRCS
),输出(UTEST\u queryer\u MANAGER\u OBJS
)UTEST\u queryer\u MANAGER\u NAME
- 为目标添加目标和规则,例如,
utest\u queryermanager:#诸如此类…
- 将目标
添加为utest\u queryermanager
的依赖项utest\u all
通过重新定义
utest\u all
。我想忽略后面的两个步骤,这样,如果我为一个新类添加单元测试,我只需要执行第一步。简言之,我想自动化第二步和第三步(如果不需要,甚至删除它们).首先,我们必须删除此生成文件中的一些冗余
步骤1:使用我们已经为目标名称定义的变量
$(UTEST_SERVER_QUERIER_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS) -o $(UTEST_SERVER_QUERIER_NAME) -pthread -lgtest -lgmock -L. $(LIB)
$(UTEST_SERVER_PROTO_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS) -o $(UTEST_SERVER_PROTO_NAME) -pthread -lgtest -lgmock -L. $(LIB)
步骤2:使用一些,就像我们在%.o
规则中已经使用的那样
$(UTEST_SERVER_QUERIER_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
$(UTEST_SERVER_PROTO_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
步骤3:注意这两个规则具有完全相同的命令,并合并它们
UTESTS := $(UTEST_SERVER_QUERIER_NAME) $(UTEST_SERVER_PROTO_NAME)
$(UTEST_SERVER_QUERIER_NAME): $(UTEST_SERVER_QUERIER_OBJS)
$(UTEST_SERVER_PROTO_NAME): $(UTEST_SERVER_PROTO_OBJS)
$(UTESTS): $(UTEST_COM_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
现在来看看我们是如何构造这些变量的
步骤4:现有的makefile使用名称中带有大写字母的源文件(如ServerQuerierTest.cpp
)来构建名称为小写的可执行文件(如utest\u serverquerier
)。我们可以自动执行此操作,但我会在可执行文件的名称中保留大小写(例如utest\u serverqueryer
),以获得更简单的解决方案
UTEST_SERVER_QUERIER_NAME := utest_ServerQuerier
UTEST_SERVER_PROTO_NAME := utest_ServerProtocol
第5步:现在我们可以将每个名称简化为其本质:
CLASSES := ServerQuerier ServerProtocol
UTESTS := $(addprefix utest_, $(CLASSES))
第6步:现在看看规则
utest_ServerQuerier: ServerQuerier.o ServerQuerierTest.o
utest_ServerProtocol: ServerProtocol.o ServerProtocolTest.o
模式很明显,因此我们可以将这些规则折叠到模式规则中:
$(UTESTS): utest_%: %.o %Test.o $(UTEST_COM_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
因此,我们不再需要为新类编写新规则,我们只需将它们的名称添加到类中
但也许我们甚至不必这么做
第7步:这里似乎有一个简单的模式:类Foo
应该在列表中,当且仅当文件Foo.cpp
和FooTest.cpp
存在时。我们可以假设FooTest.cpp
没有Foo.cpp
就不存在。因此,如果这是正确的,我们可以消除所有三个manual通过让Make推断测试列表,逐步完成并自动化所有操作
TESTFILES := $(wildcard *Test.cpp)
CLASSES := $(patsubst %Test.cpp, %, $(TESTFILES))
首先,我们必须从这个makefile中删除一些冗余 步骤1:使用我们已经为目标名称定义的变量
$(UTEST_SERVER_QUERIER_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS) -o $(UTEST_SERVER_QUERIER_NAME) -pthread -lgtest -lgmock -L. $(LIB)
$(UTEST_SERVER_PROTO_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS) -o $(UTEST_SERVER_PROTO_NAME) -pthread -lgtest -lgmock -L. $(LIB)
步骤2:使用一些,就像我们在%.o
规则中已经使用的那样
$(UTEST_SERVER_QUERIER_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_QUERIER_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
$(UTEST_SERVER_PROTO_NAME): $(UTEST_COM_OBJS) $(UTEST_SERVER_PROTO_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
步骤3:注意这两个规则具有完全相同的命令,并合并它们
UTESTS := $(UTEST_SERVER_QUERIER_NAME) $(UTEST_SERVER_PROTO_NAME)
$(UTEST_SERVER_QUERIER_NAME): $(UTEST_SERVER_QUERIER_OBJS)
$(UTEST_SERVER_PROTO_NAME): $(UTEST_SERVER_PROTO_OBJS)
$(UTESTS): $(UTEST_COM_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
现在来看看我们是如何构造这些变量的
步骤4:现有的makefile使用名称中带有大写字母的源文件(如ServerQuerierTest.cpp
)来构建名称为小写的可执行文件(如utest\u serverquerier
)。我们可以自动执行此操作,但我会在可执行文件的名称中保留大小写(例如utest\u serverqueryer
),以获得更简单的解决方案
UTEST_SERVER_QUERIER_NAME := utest_ServerQuerier
UTEST_SERVER_PROTO_NAME := utest_ServerProtocol
第5步:现在我们可以将每个名称简化为其本质:
CLASSES := ServerQuerier ServerProtocol
UTESTS := $(addprefix utest_, $(CLASSES))
第6步:现在看看规则
utest_ServerQuerier: ServerQuerier.o ServerQuerierTest.o
utest_ServerProtocol: ServerProtocol.o ServerProtocolTest.o
模式很明显,因此我们可以将这些规则折叠到模式规则中:
$(UTESTS): utest_%: %.o %Test.o $(UTEST_COM_OBJS)
$(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)
因此,我们不再需要为新类编写新规则,我们只需将它们的名称添加到类中
但也许我们甚至不必这么做
步骤7:这里似乎有一个简单的模式:类Foo
应该在列表中,当且仅当文件Foo.cpp
和FooTest.cpp