gnu的正确语法使得处理不同的先决条件的方式不同

时间:2014-05-20 03:24:08

标签: c++ makefile

我刚刚在程序中从静态库切换到共享对象,并试图找出如何正确相应地更新我的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的功能,我希望有人可以就此提出一些建议。

编辑2014-05-21

作为额外的背景信息/澄清,项目的文件夹结构中存在分散的规则,这些规则实际上具有以下相同的效果:

$(TGT_TESTS) : $(TGT_SO)

特别谈到迄今为止收到的一个答案中提出的观点 - 而双冒号规则可能会导致如果(其中一个)TGT_SO发生变化而导致执行空白规则但(其中一个)TGT_TESTS没有(因为这种情况只会导致上述两条规则中的第一条被执行),实际上,任何一个TGT_SO对象的改变也会导致部分/全部TGT_TESTS被重建,从而导致第二条规则也被执行。

谢谢! 什穆埃尔

1 个答案:

答案 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中。但是,双冒号规则的情况   真正有意义的是那些执行食谱的顺序   没关系。

     

双冒号规则有点模糊,通常不太有用;   它们为用于更新的方法的情况提供了一种机制   目标根据导致的先决条件文件而有所不同   更新,这种情况很少见。

     

每个双冒号规则应指定配方;如果没有,那么   如果适用,将使用隐式规则。请参阅使用隐式规则。