【问题标题】:How to break a list of words into smaller chunks in GNU Make如何在 GNU Make 中将单词列表分成更小的块
【发布时间】:2021-11-11 16:51:29
【问题描述】:

我的目标是在 GNU Make 中找到一种方法来动态创建规则以构建相等块的文件集。让我试着解释一下……

假设我有一个包含我们需要构建的所有源文件的 make 变量:

SOURCE_FILES := one.c two.c three.c four.c five.c six.c

现在我希望能够动态地将文件列表分解为 N 个子列表,并为每个子列表动态生成规则。例如,如果 N = 3 我会得到

one.o two.o: one.c two.c
    @command to build just the 2 files

three.o four.o: three.o four.c
    @command to build just the 2 files

five.o six.o: five.c six.c
    @command to build just the 2 files

如果 N = 2,我希望有以下规则:

one.o two.o three.o: one.c two.c three.c
    @command to build just the 3 files

four.o five.o six.o: four.c five.c six.c
    @command to build just the 2 files

我在想,一旦我将单词列表分解为子列表,我就可以使用eval 创建规则,我想我可以尝试使用wordlist 创建子列表。我可以使用words 获得源文件的总数,但我不确定如何进行除法或迭代。我正在尝试在 Make 中完成这一切,而不使用 shell 来尝试使其与 shell 无关。

这样做的全部原因是我们的专有编译器在调用每个源文件时都很昂贵。但是将所有文件作为输入调用一次需要太长时间。所以我希望找到一个可以创建多个规则的快乐媒介,这样我就可以利用-j N 选项来并行构建。

最后,我计划制定一个可以进行链接的规则:

executable.elf : one.o two.o three.o four.o five.o six.o
    @command to link the object files

【问题讨论】:

  • 你熟悉static pattern rules吗?我不确定他们是否会提供帮助,但总的来说它们非常有用。不过,您可能必须使用虚拟的 .stamp 目标。

标签: makefile gnu-make gnu


【解决方案1】:

在你遇到拆分文件的问题之前,基本的想法是不正确的,至少不像写的那样。

这条规则:

one.o two.o: one.c two.c
        @command to build just the 2 files

没有按照您想要的方式工作。具有多个目标的明确规则并不意味着“运行此配方一次以创建所有这些输出文件”。它被 make exactly 解释,就好像你写了这样:

one.o: one.c two.c
        @command to build just the 2 files
two.o: one.c two.c
        @command to build just the 2 files

这意味着如果您启用并行构建,make 将运行配方两次,而不是一次。

【讨论】:

  • 如果您愿意在您的构建中要求 GNU make 4.3 版,该版本有一个新功能 &:,它是执行您想要的“分组目标”。
  • 嗯...这似乎不正确。 one.c -> one.o 和 two.c -> two.o 如果 Make 真的最终做了两个菜谱并将两个 C 文件分别提供给每个菜谱,它肯定不会工作。我不认为我可以将 Make 版本推送到 4.3,但即使我这样做了,那么文件拆分将如何工作?
  • 您可以使用$(words ...) 函数(参见 GNU make 手册)将列表拆分为更小的列表。然而,由于 GNU make 并没有真正的数学或类似的函数,你必须选择一个硬编码的大小。您可以使用call 编写一个递归函数来拆分事物。您还必须使用eval 来创建规则。这会有点棘手,但可以做到。或者,您可以在 shell 中完成所有操作,然后在 shell 中拆分内容并写出可以包含在内的 makefile。
  • 做到这一点非常、非常、非常困难。基本上,您必须将生成多个输出的规则转换为生成单个输出的规则。您可以使用规则涉及的哨兵文件,例如.foo : one.c two.c ; @command ; touch $@,然后创建另一个规则,使两个目标文件都依赖于该目标,如下所示:one.o two.o : .foo ; @:(注意此规则必须有一个配方!!但它什么都做不了,就像这个例子)。存在一些问题,例如如果删除了目标文件而不是哨兵文件,它将无法工作,等等。
  • 我没有。这就是我建议升级的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多