如何在每次调用时都不重建工件

时间:2019-07-05 14:38:45

标签: bazel

我想在工作区中下载并构建ruby。我一直在尝试通过模仿rules_go来实现这一点。我有那部分工作。我遇到的问题是,每次调用ruby_download_sdk时,它都会重建openssl和ruby工件。在下面的代码中,下载工件被缓存,但是始终执行openssl和ruby的构建。

def ruby_download_sdk(name, version = None):
    # TODO detect os and arch
    os, arch = "osx", "x86_64"

    _ruby_download_sdk(
        name = name, 
        version = version,
    )
    _register_toolchains(name, os, arch)

def _ruby_download_sdk_impl(repository_ctx):
    # TODO detect platform
    platform = ("osx", "x86_64")

    _sdk_build_file(repository_ctx, platform)
    _remote_sdk(repository_ctx)

_ruby_download_sdk = repository_rule(
    _ruby_download_sdk_impl,
    attrs = {
        "version": attr.string(),
    },
)

def _remote_sdk(repository_ctx):
    _download_openssl(repository_ctx, version = "1.1.1c")
    _download_ruby(repository_ctx, version = "2.6.3")

    openssl_path, ruby_path = "openssl/build", ""
    _build(repository_ctx, "openssl", openssl_path, ruby_path)
    _build(repository_ctx, "ruby", openssl_path, ruby_path)

def _build(repository_ctx, name, openssl_path, ruby_path):
    script_name = "build-{}.sh".format(name)
    template_name = "build-{}.template".format(name)

    repository_ctx.template(
        script_name,
        Label("@rules_ruby//ruby/private:{}".format(template_name)),
        substitutions = {
            "{ssl_build}": openssl_path,
            "{ruby_build}": ruby_path,
        }
    )
    repository_ctx.report_progress("Building {}".format(name))
    res = repository_ctx.execute(["./" + script_name], timeout=20*60)

    if res.return_code != 0:
        print("res %s" % res.return_code)
        print(" -stdout: %s" % res.stdout)
        print(" -stderr: %s" % res.stderr)

关于我如何使bazel知道的建议,以便它不会每次都重建这些构建工件?

1 个答案:

答案 0 :(得分:0)

问题是,bazel并不能真正构建您的红宝石和openssl。当它准备好您的构建树并运行存储库规则时,它只是按照说明执行了一个shell脚本,这显然是在构建过程中发生的,但是这一事实对于bazel基本上是不透明的(并且也发生在bazel自己构建之前)。 >

可能还有其他选择,但我认为以下是您的选择:

  • 将外部环境及其结果作为外部依赖项进行预构建。对于需要支持的所有平台(包括确保正确的检测和相应的下载),您需要这样做的明显缺点(可能会也可能不会很痛苦)。好处是您实际上只构建一次(每个平台),并且还可以控制在所有主机上使用的工具。这可能是我的主要选择。

  • 像其他C语言源一样构建ssl和ruby,使它们成为另一个目标。但是,这意味着您需要对他们的构建进行标准化(描述和维护不了解Bazel的项目的bazel构建)。

  • 您可以沿着开始的路径继续前进,而将bazel排除在外。即对于这些构建,可以扩展魔术,并在例如使用确定性位置的构建脚本中使用扩展脚本,还可以在清单文件中显示周围的内容(也可以减少损坏的可能性),从而有可能确定构建确实已经进行,您可以收集以前的结果。