【问题标题】:GNU make: Multiple targets in a single rule [duplicate]GNU make:单个规则中的多个目标[重复]
【发布时间】:2011-10-28 05:15:56
【问题描述】:

可能重复:
GNU Makefile rule generating a few targets from a single source file

如果我有这样的 Makefile 规则:

a b c:
    echo "Creating a b c"
    touch a b c

output: a b c
    cat a b c > output

然后我运行 ma​​ke -j9 output

make 看到 3 个依赖项 (a,b,c),寻找如何生成它们:(上面的“a b c”规则),但接下来会发生什么?它应该没有意识到“a b c”规则只需要运行一次即可创建所有 3 个目标吗?

这是 make 实际做的:

[pavel@orianna test]$ make -j9 output -n
echo "Creating a b c"
touch a b c
echo "Creating a b c"
touch a b c
echo "Creating a b c"
touch a b c                                                                                                                                                                                                                                                                    
cat a b c > output                                                                                                                                                                                                                                                             
[pavel@orianna test]$

相同的配方运行 3 次,每个依赖项运行一次以规则“输出”!

有人知道它为什么会这样吗?

【问题讨论】:

标签: makefile gnu-make


【解决方案1】:

你的a b c: 规则告诉Make这是如何构建任何个这些目标,而不是如何构建所有个目标。 Make 不够聪明,无法分析命令并推断运行规则一次将构建所有三个命令。 Make 知道(根据output 规则)它必须重建abc,这就是它的作用。它为a 运行第一条规则,为b 运行一次,为c 运行一次。

如果您想单独重建它们,请执行以下操作:

a b c:
    echo "Creating $@"
    touch $@

如果您想一次全部重建它们,请执行以下操作:

.PHONY: things
things:
    echo "Creating a b c"
    touch a b c

output: things
    cat a b c > output

或者更好:

THINGS = a b c
.PHONY: things
things:
    echo "Creating $(THINGS)"
    touch $(THINGS)

output: things
    cat $(THINGS) > output

【讨论】:

  • 很好的答案!谢谢你。创建虚假目标是唯一的方式,还是有更简洁的方式来表达“a and b and c are built by this rule”?
  • @Pavel,我不知道更清洁的方法(无论如何我可能会选择第一个选项)。但话又说回来,我仍在试图找出 AUZKamath 的答案。
  • 请参阅cmcrossroads.com/ask-mr-make/… 了解处理这种情况的方法的调查,包括在 gmake 中指定具有多个输出的规则的唯一“正确”方法(当然是模式规则!)。跨度>
【解决方案2】:

a b c 是三个不同的目标/目标,没有先决条件。也就是说,它会在被要求时构建目标。

a b c:
    echo "Creating a b c"
    touch a b c

您要求 make 构建以 b c 作为先决条件的目标命名输出。 所以目标 a b c 是按顺序构建的,最后构建输出。

现在,在您的情况下,所有目标都会在调用其中任何一个时始终构建。因此,为了避免冗余构建,您必须向目标 a、b、c 添加先决条件。仅当“a”不存在时才构建目标“a”。 'b' 和 'c' 也是如此

a b c: $@
    echo "Creating a b c"
    touch a b c

但是,这是不可取的。理想情况下,Makefile 目标应该非常具体。

【讨论】:

  • 这行得通,但我不知道如何。杰克凯利派你来的吗?
  • 但是,当使用make -j3 a b c 运行它时,会创建三个作业。
  • 谁能解释一下这是如何工作的?我无法通过阅读 gnu.org/software/make/manual/make.html#index-_0024_0040 来解释它
  • @krmlr @Xiphias 诀窍是当make 考虑a 时,它会看到规则a: a。仅当目标比其任何先决条件更旧或任何先决条件不存在时,才会重建目标。在这里,第一种情况永远不会成立,而第二种情况只有在 a 尚不存在时才成立。在touchb: bc: c 之后不需要重建。 (至于-j3,三个进程看到了a: ab: bc: c,并在任何touch之前对其进行了处理。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 2018-12-28
相关资源
最近更新 更多