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 意识到它不会每次都重建这些构建工件的任何建议?
解决方案
问题是,bazel 并没有真正构建你的 ruby 和 openssl。当它准备你的构建树并运行存储库规则时,它只是按照指示执行一个 shell 脚本,这显然是构建的,但这个事实对 bazel 来说基本上是不透明的(而且它也发生在 bazel 本身甚至构建之前)。
可能还有其他,但我认为以下是您的选择:
预先构建您的 ruby 环境及其结果作为外部依赖项。明显的缺点(可能会或可能不会很痛苦)是您需要为您需要支持的所有平台这样做(包括确保正确检测和相应的下载)。好处是您实际上只构建一次(每个平台),并且还可以控制所有主机上使用的工具。这可能是我的主要选择。
像任何其他 C 源代码一样构建 ssl 和 ruby,使它们成为另一个 bazel 目标。然而,这意味着您需要 bazelify 他们的构建(描述和维护其他 bazel 不知道项目的 bazel 构建)。
您可以沿着您开始的路径继续前进,并且(有点)将 bazel 排除在外。即,对于这些构建扩展了魔法,并且在构建脚本中使用确定性位置和可能的清单文件(也可以减少损坏的可能性)使得可以确定构建确实已经发生并且您可以只是收集它以前的结果。
推荐阅读
- sql - 检查相同的 id 是否具有确定的条件
- angularjs - 如何通过索引访问数组中的数据以获取 AngularJs 中的重复项
- java - 卡夫卡和 OpenJDK
- azure - Azure 函数 - 事件中心触发器已停止
- c# - 如何动态创建 XML 文件?
- laravel - Laravel Model::find() 自动按 id 对结果进行排序,如何停止呢?
- google-apps-script - 如何在 GAS 中运行/调试私有函数?
- python - settimeout() 忽略 Try/Except 的异常 - Python
- scrapy - 将项目(或其他变量)传递给 scrapy 的中间件(或其他模块)。
- build - Thinlto 的并发性在并行构建系统中有用吗?