构建目标列表生成器时如何处理 OMake 中未知目标的构建规则

发布于 2024-08-26 17:01:54 字数 603 浏览 10 评论 0原文

我有一个使用 OMake 作为构建系统的项目,我正在尝试处理一个相当困难的极端情况。

我有一些定义文件和一个可以获取这些定义文件并创建 GraphViz 文件的工具。但存在两个问题:

  • 每个定义文件可以生成多个图形,并且它可以生成的图形列表被编码在文件中。我的转储工具确实有一个 -list 选项,它列出了定义文件将生成的所有图形。
  • 该转储工具构建在源代码树中。
  • 我希望 OMakefile 中提供此列表,以便我可以使用其他规则将 DOT 文件转换为 SVG,并有一个依赖于所有 SVG 的虚假目标(目标:使用单个构建命令构建所有图形的 SVG 描述)。

如果我只有第一个问题,那就很容易了 - 我将运行该工具来构建一个列表,然后使用该列表来构建一个调用转储器来输出 GraphViz 文件的目标。然而,我相当坚持在需要之前强制构建转储工具。

如果这是 make,我只需递归运行 make 来构建转储工具。但是,OMake 不允许递归调用,并且 build 函数只能在 osh 中使用。

对于解决这个问题有什么好的建议吗?

I have a project which uses OMake for its build system, and I am trying to handle a rather tough corner case.

I have some definition files and a tool which can take these definition files and create GraphViz files. There are two problems, though:

  • Each definition file can produce multiple graphs, and the list of graphs it can produce is encoded in the file. My dump tool does have a -list option which lists all the graphs a definition file will produce.
  • This dump tool is built in the source tree.
  • I want this list available in the OMakefile so I can use other rules to convert the DOT files to SVG, and have a phony target depend on all the SVGs (goal: a single build command which builds SVG descriptions of all my graphs).

If I only had the first problem, it would be easy - I would run the tool to build a list, and then use that list to build a target which invokes the dumper to output the GraphViz files. However, I am rather stuck on forcing the dump tool to be built before it is needed.

If this were make, I would just run make recursively to build the dump tool. OMake does not allow recursive invocation, however, and the build function is only usable from osh.

Any suggestions for a good solution to this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笔芯 2024-09-02 17:01:54

好的,这是我的建议。首先,这是一个用 bash 制作的快速生成器,它可以采用“--list”参数来创建一个 omake 变量来包含要做的事情的列表。该生成器称为“generator.txt”,因为我们将通过将其重命名为 .sh 来“制作”它。

#!/bin/bash

if [ "$1" = "--list" ]; then
    echo -e 'FILES[] = \n\ta\n\tb\n\tc'
else
    echo 1 > a.dot
    echo 2 > b.dot
    echo 3 > c.dot
fi

然后,OMakefile 本身:

.INCLUDE: rules : generator.txt
    cp generator.txt generator.sh
    chmod 755 generator.sh  
    ./generator.sh
    ./generator.sh --list > rules

DOTS[] =
    $(addsuffix .dot, $(FILES))

SVGS[] =
    $(addsuffix .svg, $(FILES))

# rule to turn a .dot into a .svg
%.svg: %.dot
    cp $*.dot $*.svg

.DEFAULT: $(SVGS)

.PHONY: clean
clean:
    rm -f generator.sh a.* b.* c.* rules

这里的技巧是从生成器.txt 生成“规则”文件,并将其包含在 OMakefile 中。每当generator.txt(生成器的源代码)发生变化时,我们都会重新创建(构建)生成器,运行它(创建文件a.dot、b.dot、c.dot),最后使用 --list 运行它以生成我们的生成器FILE[] 变量包含要生成的文件列表。

然后,生成 DOTS 和 SVGS 变量以及将点转换为 svg 的规则就变得微不足道了。默认目标取决于 svgs 列表,它将按顺序构建所有内容。

这种方法的问题是构建生成器非常粗糙,因为我们必须将“INCLUDE”依赖项列表作为真实文件。尽管如此,这至少应该以正确的顺序执行操作。

请注意修改generator.txt(例如,添加另一个要生成的.dot,或更改.dot 内容的生成方式)如何正确强制重新生成generator.sh,然后重新生成任何生成的文件被修改。

编辑

我认为主要问题是 omake 期望能够在开始做任何工作之前生成整个依赖关系图。因此,它无法处理某些依赖项来构建生成器,然后生成更多依赖项来处理其输出。

我想有一些方法可以解决:

  • 第一个是将生成器构建为 .INCLUDE 指令的一部分,正如我首先描述的那样,这很麻烦,因为您必须将所有生成器构建过程放入其中 。

  • 第二个方法是失去一些灵活性,并处理一个输入到一个输出,例如让生成器仅生成一个包含所有串联输入的文件。正如您所知,您只有一个文件,因此可以轻松设置依赖项。

  • 第三个,也是我最喜欢的,是拥有一个两阶段构建系统。在子目录中,您有一个 OMakefile,它生成生成器并输出文件。在另一个子目录中,您有另一个 OMakefile,它读取第一个目录的内容以生成要处理的文件列表,然后运行转换。然后,在主目录中,bash 脚本在第一个目录中调用 omake,然后在第二个目录中调用 omake。这希望意味着您可以使用单个命令生成所有内容,而且重建也将是最小的:第一个 omake 仅在输入发生更改时重新生成文件,第二个 omake 仅会转换已更改的文件或新文件。< /p>

Okay, here is my proposal. First, here is a quick generator made in bash, that can take a "--list" argument that creates an omake variable to contain the list of things to do. The generator is called "generator.txt", as we are going to "make" it by renaming it into a .sh.

#!/bin/bash

if [ "$1" = "--list" ]; then
    echo -e 'FILES[] = \n\ta\n\tb\n\tc'
else
    echo 1 > a.dot
    echo 2 > b.dot
    echo 3 > c.dot
fi

Then, the OMakefile itself:

.INCLUDE: rules : generator.txt
    cp generator.txt generator.sh
    chmod 755 generator.sh  
    ./generator.sh
    ./generator.sh --list > rules

DOTS[] =
    $(addsuffix .dot, $(FILES))

SVGS[] =
    $(addsuffix .svg, $(FILES))

# rule to turn a .dot into a .svg
%.svg: %.dot
    cp $*.dot $*.svg

.DEFAULT: $(SVGS)

.PHONY: clean
clean:
    rm -f generator.sh a.* b.* c.* rules

The trick here is to generate the "rules" file from generator.txt, to be included in the OMakefile. Whenever generator.txt (the source for our generator) changes, we recreate (build) the generator, run it (creating files a.dot, b.dot, c.dot), and finally run it with --list to generate our FILE[] variable containing the list of files to generate.

Then, it becomes trivial to generate the DOTS and SVGS variables, and the rule that turns a dot into an svg. The default target depends on the list of svgs, which is going to build everything in order.

The problem with this approach is that building the generator is quite coarse as we must have the "INCLUDE" dependencies list being real files. Nevertheless, this should at least perform operations in the correct order.

Notice how modifying generator.txt (for example, adding another .dot to be generated, or changing the how the contents of a .dot will be generated) correctly forces the regeneration of generator.sh, and then of any generated file which would have been modified.

EDIT

I think the main problem is that omake expects to be able to generate the entire dependencies graph before starting to do any work. As such, it cannot work on some dependencies to build the generator, then generate more dependencies to work on its output.

I suppose there are ways to work around:

  • The first one is to have the generator built as part of the .INCLUDE directive, as I described first, which is a hassle because you have to put all the generator build process into that directive.

  • The second one would be to lose some flexibility, and work on one input to one output, for example having the generator generate only one file with all the concatenated inputs. As you know that you will have only one file, you can set dependencies easily.

  • The third one, which would be my favorite, is to have a 2 phase build system. In a sub directory, you have an OMakefile that generates the generator and outputs the files. In an other subdirectory, you have another OMakefile, that reads the contents of the first directory to generate the list of files to process, then runs the transformation. Then, in the main directory, a bash script calls omake in the first directory, then in the second. This hopefully should mean that you can generate everything with a single command, but also that a rebuild would be minimal: the first omake will only regenerate files if the inputs have changed, and the second omake will only transform the changed or new files.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文