我刚刚在程序中从静态库切换到共享对象,并试图找出如何正确相应地更新我的Makefile。我找到了一个似乎正常工作的解决方案,使用双冒号规则。但是,我真的不确定我所做的事情的影响,以及这是否是解决这个问题的正确方法。
我不确定这里是否有任何区别,但作为背景,我的Makefile遵循Emile van Bergen建议的方法:http://evbergen.home.xs4all.nl/nonrecursive-make.html
共享对象全部收集在名为TGT_SO的变量中。我还有一堆目标文件需要包含在可执行文件中 - 我正在处理的特定规则是我的单元测试,这些目标文件都收集在一个名为TGT_TESTS的变量中。
以前,规则/配方很简单:
tests : $(TGT_LIB) $(TGT_TESTS)
$(BUILD_TESTS)
BUILD_TESTS = $(CXX) $(CF_ALL) $(LF_ALL) -o test/$@ $^
当然,这适用于TGT_LIB
,这是一堆档案。当然,对于TGT_SO
来说,这根本不起作用,这些都是共享对象,并且需要包含在-l...
中。
毫不奇怪,将其分为两个单独的规则(使用单冒号语法)并没有解决问题。它仍包含构建命令中的所有.so对象。
经过一些修补和阅读后,我接受了以下规则:
tests :: $(TGT_SO)
tests :: $(TGT_TESTS)
$(BUILD_TESTS)
据我所知,双冒号有效地将这些规则分为两个完全独立的规则 - 第一个规则确保共享对象按其各自的规则进行更新。第二条规则提供了构建共享对象的方法。
正如我在开始时所说的那样,上述规则似乎正在起作用,但鉴于我对Make的经验相当有限,我真的不确定我所做的事情的含义 - 特别是使用的功能文档描述为:"有点模糊,通常不太有用...",然后继续建议一个用例:"更新目标会有所不同,具体取决于哪些先决条件文件导致更新,这种情况很少见。" (引自Make documentation)
鉴于我想要做的事情必须非常普遍,而且我发现的解决方案似乎滥用/滥用了Make的功能,我希望有人可以就此提出一些建议。
作为额外的背景信息/澄清,项目的文件夹结构中存在分散的规则,这些规则实际上具有以下相同的效果:
$(TGT_TESTS) : $(TGT_SO)
特别谈到迄今为止收到的一个答案中提出的观点 - 而双冒号规则可能会导致如果(其中一个)TGT_SO发生变化而导致执行空白规则但(其中一个)TGT_TESTS没有(因为这种情况只会导致上述两条规则中的第一条被执行),实际上,任何一个TGT_SO对象的改变也会导致部分/全部TGT_TESTS被重建,从而导致第二条规则也被执行。
谢谢! 什穆埃尔
答案 0 :(得分:0)
怎么样:
tests : $(TGT_SO) $(TGT_TESTS)
$(BUILD_TESTS)
BUILD_TESTS = $(CXX) $(CF_ALL) $(LF_ALL) -o test/$@ $(filter %.o,$^)
您可以对$(TGT_SO)
或`$(过滤器%.so,$ ^)进行一些转换,以达到-lXX列表
我从未使用过双冒号规则,但是从手册中的描述来看,如果你只改变其中一个库(并且对象没有变化),那么只会执行第一个规则,这将导致在尝试应用隐式规则
(来自手册,重点是我的)
具有相同目标的双冒号规则实际上是完全的 彼此分开。处理每个双冒号规则 个别地,就像处理不同目标的规则一样。
目标的双冒号规则按照它们的顺序执行 出现在makefile中。但是,双冒号规则的情况 真正有意义的是那些执行食谱的顺序 没关系。
双冒号规则有点模糊,通常不太有用; 它们为用于更新的方法的情况提供了一种机制 目标根据导致的先决条件文件而有所不同 更新,这种情况很少见。
每个双冒号规则应指定配方;如果没有,那么 如果适用,将使用隐式规则。请参阅使用隐式规则。