如何在bazel的分析时运行shell命令?

时间:2017-12-03 19:55:59

标签: versioning bazel

我正在尝试将mercurial版本烘焙到我的Bazel文件中,以便我可以得到这样的内容:

# These I set manually, since they're "semantic"
MAJOR_VERSION = 2
MINOR_VERSION = 3
BUGFIX_VERSION = 1

# This should be the result of `hg id -n`
BUILD_VERSION = ?

apple_bundle_version(
    name = "my_version",
    build_version = "{}.{}.{}.{}".format(MAJOR_VERSION, MINOR_VERSION, BUGFIX_VERSION, BUILD_VERSION),
    short_version_string = "{}.{}.{}".format(MAJOR_VERSION, MINOR_VERSION, BUGFIX_VERSION),
)

这显然不是密封的,所以我知道这违反了Bazel的一些假设,所以我对其他选择持开放态度。

以下是一些可能的选择:

  1. 实际上在Bazel分析期间运行hg id -n,我不知道该怎么做。

  2. 将构建版本传递给via命令行,例如--define=build_version=$(hg id -n)。不幸的是,这需要一个单独的命令来包装bazel build

  3. 手动设置BUILD_VERSION。显然,这会很烦人。

  4. 有没有办法做#1?我有什么其他选择?

2 个答案:

答案 0 :(得分:8)

是的,您可以使用自定义--workspace_status_command以及处理信息并生成包含此数据的源文件的规则来执行此操作。

编辑:我删除了有关--stamp旗帜的部分,但不需要。

摘要

  1. 使用--workspace_status_command=/path/to/binary构建一个运行hg的自定义二进制文件或shell脚本,并输出所需的信息。
  2. 使用genrule撰写stamp=1
  3. 详细

    1。 --workspace_status_command=/path/to/binary

    --workspace_status_command=<path>标志允许您指定二进制文件。

    Bazel在每次构建之前运行此二进制文件。二进制文件应该将键值对写入stdout。 Bazel将钥匙分成两个桶:&#34;稳定&#34;和&#34;易变的&#34;。 (名称&#34;稳定&#34;和&#34;易变?&#34;有点反直觉,所以不要过多考虑它们。)

    然后Bazel将键值对写入两个文件:

    • bazel-out/stable-status.txt包含密钥的名称以STABLE_开头的所有键和值
    • bazel-out/volatile-status.txt包含其余的键及其值

    合同是:

    • &#34;稳定&#34;密钥&#39;如果可能,值应该很少改变。如果stable-status.txt的内容发生更改,则会使依赖于它们的操作无效,例如genrule.cmd如果该genrule stamp=1。换句话说,如果一个稳定的键的值发生变化,它将使Bazel重建标记的动作。因此,稳定状态不应包含时间戳等内容,因为它们会一直更改,并且会使Bazel重建每个构建的标记操作。
    • &#34;挥发性&#34;密钥&#39;价值观可能经常变化。 Bazel希望他们能像时间戳一样随时更改,并适时更新volatile-status.txt文件。为了避免一直重建标记动作,Bazel假装易失性文件永远不会改变。换句话说,如果易失性状态文件是唯一内容已更改的文件,则不会使依赖于它的操作无效。如果操作的其他输入已更改,则Bazel会重建该操作,然后操作可以使用更新的易失性状态。但仅仅是不稳定的状态改变不会使行动失效。

    my-status.sh的示例:

    #!/bin/bash
    echo STABLE_GIT_BRANCH $(git rev-parse HEAD)
    echo MY_TIMESTAMP $(date)
    

    2。用genrule写一个stamp=1

    这个属性没有记录,让我感到惊讶。我将提交一个关于此的错误。

    foo/BUILD的示例:

    genrule(
        name = "x",
        srcs = ["input.txt"],
        outs = ["x.txt"],
        cmd = " ; ".join([
            "( echo 'volatile data:'",
            "cat bazel-out/volatile-status.txt",
            "echo ---",
            "echo 'stable data:'",
            "cat bazel-out/stable-status.txt",
            ") > $@",
        ]),
        stamp = 1,
    )
    

    全部放在一起

    genrule没有重建

    ...仅bazel-out/volatile-status.txt更改时:

      $ bazel build --workspace_status_command=/tmp/foo/ws.sh //foo:x &>/dev/null && cat bazel-genfiles/foo/x.txt
    volatile data:
    BUILD_TIMESTAMP 1512379211456
    MY_TIMESTAMP Mon Dec 4 10:20:11 CET 2017
    ---
    stable data:
    BUILD_EMBED_LABEL 
    BUILD_HOST <redacted>
    BUILD_USER <redacted>
    STABLE_GIT_BRANCH d3fed125d00f6f61bfbfe05f4566656cdac1ea6e
    
      $ cat bazel-out/volatile-status.txt 
    BUILD_TIMESTAMP 1512379425898
    MY_TIMESTAMP Mon Dec 4 10:23:45 CET 2017
    
      $ bazel build --workspace_status_command=/tmp/foo/ws.sh //foo:x &>/dev/null && cat bazel-genfiles/foo/x.txt
    volatile data:
    BUILD_TIMESTAMP 1512379211456
    MY_TIMESTAMP Mon Dec 4 10:20:11 CET 2017
    ---
    stable data:
    BUILD_EMBED_LABEL 
    BUILD_HOST <redacted>
    BUILD_USER <redacted>
    STABLE_GIT_BRANCH d3fed125d00f6f61bfbfe05f4566656cdac1ea6e
    
      $ cat bazel-out/volatile-status.txt 
    BUILD_TIMESTAMP 1512379441919
    MY_TIMESTAMP Mon Dec 4 10:24:01 CET 2017
    

    重建了genrule

    ...当稳定状态或genrule的输入发生变化时:

      $ echo bar > foo/input.txt 
    
      $ bazel build --workspace_status_command=/tmp/foo/ws.sh //foo:x &>/dev/null && cat bazel-genfiles/foo/x.txt
    volatile data:
    BUILD_TIMESTAMP 1512379566646
    MY_TIMESTAMP Mon Dec 4 10:26:06 CET 2017
    ---
    stable data:
    BUILD_EMBED_LABEL 
    BUILD_HOST <redacted>
    BUILD_USER <redacted>
    STABLE_GIT_BRANCH d3fed125d00f6f61bfbfe05f4566656cdac1ea6e
    
    
      $ git checkout HEAD~1 &>/dev/null
    
      $ bazel build --workspace_status_command=/tmp/foo/ws.sh //foo:x &>/dev/null && cat bazel-genfiles/foo/x.txt
    volatile data:
    BUILD_TIMESTAMP 1512379594890
    MY_TIMESTAMP Mon Dec 4 10:26:34 CET 2017
    ---
    stable data:
    BUILD_EMBED_LABEL 
    BUILD_HOST <redacted>
    BUILD_USER <redacted>
    STABLE_GIT_BRANCH b3da717469e23f5293297175a80709956416fd2c
    

答案 1 :(得分:3)

默认情况下,apple_bundle_version规则使用正则表达式来解析您在Bazel命令行上传递给--embed_label的任何内容。

因此,实现这一目标的最简单方法是首先编写类似这样的内容:

bazel build //your:target --embed_label="$(hd id -n)"

这会将BUILD_EMBED_LABEL设置为工作区信息文件中的Mercurial版本,例如:

BUILD_EMBED_LABEL 156
BUILD_HOST ...
BUILD_USER ...

然后你必须告诉apple_bundle_version你的版本号应该是什么样的:

VERSION_PREFIX = "{}.{}.{}".format(MAJOR, MINOR, BUGFIX)

apple_bundle_version(
    name = "my_version",
    # This is where you define that BUILD_EMBED_LABEL will look like
    # this, where each thing inside {} is one of the capture groups
    # below. So in this case, it will be a number.
    build_label_pattern = "{build}",
    capture_groups = {
        "build": "\d+",
    },
    # CFBundleVersion should be the VERSION_PREFIX above, plus a dot
    # followed by {build} extracted from BUILD_EMBED_LABEL.
    build_version = VERSION_PREFIX + ".{build}",
    # CFBundleShortVersionString will just be the VERSION_PREFIX.
    short_version_string = VERSION_PREFIX,
)

这样的事情应该可以解决问题。

获得更高级

如果您不想在每次构建时手动传递hg id -n的结果,apple_bundle_version规则是可扩展的,因此您可以自动执行此操作。 version及其相关规则ios_application属性的唯一要求是它指向返回AppleBundleVersionInfo提供商的目标 - 它不必是apple_bundle_version }。

该提供程序传播包含您的包版本和短包版本字符串的小JSON文件,因此您可以编写自己的规则,将hg id -n作为自定义操作调用,将其写入具有右侧的JSON格式文件密钥,然后将该目标用作应用程序的version属性。