【问题标题】:GNU make - Target with several recipes where only one recipe is neededGNU make - 以多个配方为目标,其中只需要一个配方
【发布时间】:2015-08-30 05:45:14
【问题描述】:

摘要说明

我在 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-only 配方。理想情况下,这意味着 make 的工作方式如下:

  • 如果有人尝试在不使用 target_2 的情况下创建 target_1,则使用 makefile 示例中的第二个配方,因为它更快。
  • 如果有人尝试创建 target_1target_2,请使用 makefile 示例中的第一个配方,因为它比运行创建两者的配方要快。

有什么方法可以实现吗?我知道双冒号规则,但他们会同时运行两种配方,而不是只运行其中一种。

请注意,我需要一个支持使用 -j 参数进行 make 的解决方案(但没有递归 make)。

真实场景

以下文字仅出于完整性考虑,并且由于 cmets 询问此处的真实场景是什么,它描述了 target_1target_2 是什么:

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

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

【问题讨论】:

  • 问题:当您在If someone tries to make target_1 without target_2, then use the SECOND recipe since it is faster 中说second 时,您指的是代码示例中的第二个秘诀还是您语句中的第二个秘诀?第二个子弹也是如此。考虑代码示例更有意义,但我只是想确认一下。
  • @chatraed - 谢谢,我已将我的问题修正为不那么模棱两可。

标签: build makefile dependencies gnu-make


【解决方案1】:

这有点小技巧,但类似以下的方法可能会起作用

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

【讨论】:

  • 很好,但它假定 target_1 和 target_2 是直接在命令行中指定的。这可以防止使用引用他们和其他目标的all PHONY。
  • @tohava 更新了,它更像是一个 hack,但它现在应该适用于所有情况。
  • 你能解释一下这是如何工作的吗?在我看来,它似乎仍然不适用于 make all,因为在这种情况下,MAKECMDGOALS 将只包含 all 而不是单个目标
  • @tohava 如果命令行目标包含 1 但不包含 2,则定义仅生成 1 的规则。对于其他所有情况,包括没有命令行目标,1 是根据 2 定义的。假设您将 1 和 2 设置为 all 的依赖项,这将适用于任何目标组合,或者没有指定目标时(以及 @987654327 @ 是默认目标,它应该是)。
  • 你是对的,但我想要更通用的东西,所以如果我有一些虚假的 phony_target_1phony_target_2 只创建一个目标并在命令行中指定它仍然会工作。
【解决方案2】:

我真的看不到你提供的那个样本的背后,而且我有可能没有发现问题的所有细节。但是,感觉就像makefile设计者的分解工作根本没有完成。

据我了解:

  1. 如果您只需要制作target_1,则在makefile 中有一个现有的目标target_1。所以,你就用它吧。
  2. 如果只需要制作target_2,则没有这种可能。为什么?
  3. 如果您需要同时创建两个目标,请使用比构建整个 target_1 加上整个 target_2 更快的特殊配方,可能是因为 target_2target_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

在你的系统中可行吗?

【讨论】:

  • 查看我对问题的编辑,它描述了真实情况。这是不可行的,因为链接器不会给出“共同部分”。
  • some_recipe_that_creates_both 的持续时间是多少秒/分钟?
  • @tohava:优化您的 makefile(最佳/最坏情况)后的预期收益是多少?
  • @chatared - 在某些情况下,我知道ldd -r 比完整链接少 4 倍。我这样做的主要原因不是减少总构建时间,而是为了使构建更具增量性,我试图从增量构建中减少大约 1-10 秒,其中仅使用共享库的源文件大多数可执行文件已更改。
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 2013-02-11
  • 2013-04-07
相关资源
最近更新 更多