Build GNU make-具有多个配方的目标,其中只需要一个配方 抽象描述

Build GNU make-具有多个配方的目标,其中只需要一个配方 抽象描述,build,makefile,dependencies,gnu-make,Build,Makefile,Dependencies,Gnu Make,我在Makefile中遇到以下情况: target_1 target_2 : some_recipe_that_creates_both target_1 : some_recipe_that_creates_only_target_1 请注意,如果没有target_1,就不可能有一个能够高效构建target_2的配方。因此,如果我已经需要构建target_2,我希望避免运行target_1-纯配方。理想情况下,这意味着make将按如下方式工作: 如果有人试图在没有targ

我在Makefile中遇到以下情况:

target_1 target_2 :
    some_recipe_that_creates_both

target_1 :
    some_recipe_that_creates_only_target_1
请注意,如果没有
target_1
,就不可能有一个能够高效构建
target_2
的配方。因此,如果我已经需要构建
target_2
,我希望避免运行
target_1
-纯配方。理想情况下,这意味着make将按如下方式工作:

  • 如果有人试图在没有
    target_2
    的情况下制作
    target_1
    ,则使用makefile示例中的第二个配方,因为它更快
  • 如果有人试图制作
    target_1
    target_2
    ,请使用makefile示例中的第一个配方,因为它比运行创建这两个配方的配方要快
有什么办法可以做到这一点吗?我知道双冒号规则,但他们会同时运行两个食谱,而不是只运行其中一个

请注意,我需要一个解决方案,该解决方案还支持带有
-j
参数的make(但没有递归make)

真实情况 以下文字仅出于完整性考虑,并且由于有评论询问此处的真实情况,它描述了
target_1
target_2
是什么:

我正在编译一个共享库和依赖它的可执行文件。如果我完成了共享库的编译,我希望确保exe仍然可以看到它需要的所有符号。有两种方法可以做到这一点:

  • 使exe链接依赖于共享对象
  • 将exe链接分为两个步骤(以空标记文件为目标)、exe链接和缺少符号检查(
    ldd-r
    )。问题是exe链接已经意味着缺少符号检查,因此缺少符号检查本质上是
    target_1
    ,而链接同时执行
    target_1
    target_2

我真的看不出你提供的样本背后有什么原因,我很可能没有抓住问题的所有细节。但是,感觉makefile设计器的分解工作还没有完成

据我理解:

  • 如果只需要生成
    target_1
    ,则makefile中存在一个现有的target
    target_1
    。所以,你只要使用它
  • 如果您只需要将
    设置为target_2
    ,则不存在这种可能性。为什么?
  • 如果您需要制作两个目标,您可以使用一种特殊的配方,它比构建整个
    target_1
    加上整个
    target_2
    要快,这可能是因为
    target_2
    target_1
    中冗余构建了一块(我说得对吗?)
  • 所以,感觉你需要这样的东西:

    target12_common:
        common_piece_absolutely_needed_by_target1_and_by_target2
    
    target2: target12_common
        some_recipe_that_creates_target2_only
    
    target1: target12_common
        some_recipe_that_creates_target1_only
    
    all: target1 target2
    

    这在您的系统中可行吗?

    这有点像黑客攻击,但下面类似的方法可能会奏效

    ifneq ($(filter target_1,$(if $(filter target_2,$(MAKECMDGOALS)),,$(MAKECMDGOALS))),)
    target_1 :
        some_recipe_that_creates_only_target_1
    else
    target_1 : target_2
    endif
    
    target_2 :
        some_recipe_that_creates_both
    

    问题:当您在
    中说
    second
    时,如果有人试图在没有target_2的情况下制作target_1,那么使用第二个配方,因为它更快,您指的是代码示例中的第二个配方还是您陈述中的第二个配方?第二颗子弹也是如此。考虑代码示例更有意义,但我只想确认一下。@chatraed-谢谢,我修正了我的问题,使其不那么模棱两可。查看我对问题的编辑,它描述了真实的场景。这是不可行的,因为链接器不会给出一个“公共片段”。你创建的某个食谱的持续时间(秒/分钟)是多少?@tohava:优化你的makefile后的预期收益是多少(最好/最坏的情况)?@chatared-在某些情况下,我知道
    ldd-r
    比完全链接少4倍。我这样做的主要原因不是为了减少总的构建时间,而是为了使构建更加增量,我试图从增量构建中减少大约1-10秒,在增量构建中,大多数可执行文件使用的共享库的源文件都发生了更改。很好,但它假定在命令行中直接指定了target_1和target_2。这可以防止使用指向他们和其他目标的
    all
    伪代码。@tohava更新,这更像是一种黑客行为,但现在应该适用于所有情况。你能给我解释一下这是如何工作的吗?在我看来,它似乎仍然不适用于
    makeall
    ,因为在这种情况下
    MAKECMDGOALS
    只包含
    all
    ,而不包含个人targets@tohava如果命令行目标包含1,但不包含2,则定义仅为1的规则。对于每一个其他情况,包括没有命令行目标,1是用2来定义的。假设您将1和2设置为
    all
    的依赖项,这将适用于任何目标组合,或者在没有指定目标时(并且
    all
    是默认目标,应该是)。您是对的,但我想要更一般的,因此,如果我有一些假的
    phony_target_1
    phony_target_2
    ,它只创建一个目标,并且在命令行中指定,它仍然可以工作。