首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Makefile:将几个具有相同前缀的目标组合到一个目标中

Makefile:将几个具有相同前缀的目标组合到一个目标中
EN

Stack Overflow用户
提问于 2017-07-15 09:51:05
回答 1查看 1.3K关注 0票数 1

我有一个具有多个目标的makefile,其前缀相同,如下所示:

代码语言:javascript
复制
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_all
  • 添加UTEST_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。我想忽略后面的两个步骤,这样如果我为一个新类添加单元测试,我只需要做第一步。简而言之,我想要自动化第二步和第三步(或者如果不需要的话甚至删除它们)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-16 00:38:27

首先,我们必须从这个makefile中删除一些冗余。

步骤1:使用我们已经为目标名称定义的变量。

代码语言:javascript
复制
$(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规则中使用的那些。

代码语言:javascript
复制
$(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:注意到这两个规则有完全相同的命令,并合并它们。

代码语言:javascript
复制
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)中的情况。

代码语言:javascript
复制
UTEST_SERVER_QUERIER_NAME := utest_ServerQuerier

UTEST_SERVER_PROTO_NAME := utest_ServerProtocol

步骤5:现在我们可以将每个名称简化为它的本质:

代码语言:javascript
复制
CLASSES := ServerQuerier ServerProtocol

UTESTS := $(addprefix utest_, $(CLASSES))

步骤6:现在查看规则。

代码语言:javascript
复制
utest_ServerQuerier: ServerQuerier.o ServerQuerierTest.o   

utest_ServerProtocol: ServerProtocol.o ServerProtocolTest.o

模式是显而易见的,因此我们可以将这些规则直接折叠成模式规则:

代码语言:javascript
复制
$(UTESTS): utest_%: %.o %Test.o $(UTEST_COM_OBJS)
    $(CXX) -std=c++0x $(CXXFLAGS) $^ -o $@ -pthread -lgtest -lgmock -L. $(LIB)

因此,我们不再需要为新类编写新规则,我们所要做的就是将它们的名称添加到CLASSES**.**中。

但也许我们甚至不需要那样做。

步骤7:这里似乎有一个简单的模式:只有当文件Foo.cppFooTest.cpp存在时,类Foo才应该在列表中。我们可以推测,没有FooTest.cpp就不可能存在Foo.cpp。因此,如果这是正确的,我们可以消除所有三个手动步骤,并使所有的自动化通过使导出测试列表。

代码语言:javascript
复制
TESTFILES := $(wildcard *Test.cpp)
CLASSES := $(patsubst %Test.cpp, %, $(TESTFILES))
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45116830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档