Build GNU make-具有多个配方的目标,其中只需要一个配方 抽象描述
我在Makefile中遇到以下情况: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
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
,则使用makefile示例中的第二个配方,因为它更快target_1
- 如果有人试图制作
和target_1
,请使用makefile示例中的第一个配方,因为它比运行创建这两个配方的配方要快target_2
-j
参数的make(但没有递归make)
真实情况
以下文字仅出于完整性考虑,并且由于有评论询问此处的真实情况,它描述了target_1
和target_2
是什么:
我正在编译一个共享库和依赖它的可执行文件。如果我完成了共享库的编译,我希望确保exe仍然可以看到它需要的所有符号。有两种方法可以做到这一点:
- 使exe链接依赖于共享对象
- 将exe链接分为两个步骤(以空标记文件为目标)、exe链接和缺少符号检查(
)。问题是exe链接已经意味着缺少符号检查,因此缺少符号检查本质上是ldd-r
,而链接同时执行target_1
和target_1
)target_2
target_1
,则makefile中存在一个现有的targettarget_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
,它只创建一个目标,并且在命令行中指定,它仍然可以工作。