我有一个具有多个目标的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_*现在,我想创建一个名为utest_all的目标,以便当我键入make utest_all时,所有目标utest_*都将生成多个输出文件,其名称与目标名称相同。
注意:可以有很多utest_*。
更新:
utest_allUTEST_XXX_NAME当我输入make utest_all时,make将帮助构建指定为utest_all依赖项的所有目标。但是问题是,如果我为一个新类添加单元测试(例如QuerierManagerTest.cpp ),那么我必须做以下三件事:
UTEST_QUERIER_MANAGER_SRCS)、对象(例如,UTEST_QUERIER_MANAGER_OBJS、outputs (UTEST_QUERIER_MANAGER_NAME) )。utest_queriermanager: # blah blah...。utest_queriermanager作为utest_all的依赖项。以某种方式重新定义utest_all。我想忽略后面的两个步骤,这样如果我为一个新类添加单元测试,我只需要做第一步。简而言之,我想要自动化第二步和第三步(或者如果不需要的话甚至删除它们)。
发布于 2017-07-16 00:38:27
首先,我们必须从这个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_serverquerier)。我们可以自动地做到这一点,但是为了更简单的解决方案,我将冒昧地保留可执行文件的名称(如utest_ServerQuerier)中的情况。
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)因此,我们不再需要为新类编写新规则,我们所要做的就是将它们的名称添加到CLASSES**.**中。
但也许我们甚至不需要那样做。
步骤7:这里似乎有一个简单的模式:只有当文件Foo.cpp和FooTest.cpp存在时,类Foo才应该在列表中。我们可以推测,没有FooTest.cpp就不可能存在Foo.cpp。因此,如果这是正确的,我们可以消除所有三个手动步骤,并使所有的自动化通过使导出测试列表。
TESTFILES := $(wildcard *Test.cpp)
CLASSES := $(patsubst %Test.cpp, %, $(TESTFILES))https://stackoverflow.com/questions/45116830
复制相似问题