如何让Bazel BUILD执行bash命令并通过私有令牌下载依赖?
针对Bazel新手的解决方案
1. 使用私有访问令牌下载私有制品库中的库
你现有的http_archive配置可以通过添加认证信息访问私有库,以下是两种安全且常用的实现方式:
方式一:通过请求头传递令牌
如果你的私有制品库支持Bearer Token认证,直接在http_archive中添加headers参数传入令牌:
http_archive( name = "<lib_name>", sha256 = "<你的sha256校验值>", strip_prefix = "<解压后需要去除的目录前缀>", url = "<私有库的下载URL>", headers = { "Authorization": "Bearer ${BAZEL_PRIVATE_TOKEN}", }, )
然后通过环境变量传入令牌值(避免硬编码到配置文件):
BAZEL_PRIVATE_TOKEN="你的私有令牌" bazel build //...
也可以把环境变量配置到本地.bazelrc文件(注意不要提交到版本控制):
build --action_env=BAZEL_PRIVATE_TOKEN="你的私有令牌"
方式二:URL参数嵌入令牌(仅适支持该方式的库)
部分私有库允许在URL中直接携带令牌参数,配置示例:
http_archive( name = "<lib_name>", sha256 = "<你的sha256校验值>", strip_prefix = "<解压后需要去除的目录前缀>", url = "<私有库的下载URL>?token=${BAZEL_PRIVATE_TOKEN}", )
同样通过环境变量传入令牌,避免敏感信息泄露。
注意:无论哪种方式,绝对不要把私有令牌直接写在WORKSPACE文件中。
2. BUILD文件的修改
当通过http_archive拉取到第三方库后,需要在BUILD文件中引用该库的构建目标:
步骤1:确认第三方库的目标名称
首先要明确你拉取的库在其自带的BUILD文件中定义的目标名称,比如C++库可能是@<lib_name>//:core,Java库可能是@<lib_name>//:main。
步骤2:在你的目标中添加依赖
以C++二进制文件为例,修改BUILD文件:
cc_binary( name = "my_binary", srcs = ["main.cpp"], deps = [ "@<lib_name>//:core", # 引用第三方库的目标 ], )
特殊情况:第三方库无BUILD文件
如果下载的压缩包中没有自带BUILD配置,需要在http_archive中添加build_file_content参数手动定义构建规则:
http_archive( name = "<lib_name>", sha256 = "<你的sha256校验值>", strip_prefix = "<解压后需要去除的目录前缀>", url = "<私有库的下载URL>", headers = {"Authorization": "Bearer ${BAZEL_PRIVATE_TOKEN}"}, build_file_content = """ cc_library( name = "core", srcs = glob(["src/**/*.cpp"]), hdrs = glob(["include/**/*.h"]), includes = ["include"], visibility = ["//visibility:public"], ) """, )
3. 在Bazel构建中执行bash命令
Bazel提供三种常用方式执行bash命令,适配不同场景:
方式一:用genrule生成文件时执行
如果需要在构建过程中生成文件,使用genrule:
genrule( name = "generate_config", srcs = ["config_template.txt"], outs = ["config.json"], cmd = """ # $< 代表第一个srcs文件,$@ 代表输出文件 sed "s/VERSION/1.0.0/g" $< > $@ """, )
在其他目标中依赖生成的文件:
cc_binary( name = "my_binary", srcs = ["main.cpp"], data = [":generate_config"], )
方式二:用sh_binary封装可执行脚本
如果需要直接运行bash脚本,使用sh_binary:
sh_binary( name = "my_script", srcs = ["my_script.sh"], data = ["input.txt"], # 脚本依赖的文件 )
执行脚本:
bazel run //:my_script
方式三:在WORKSPACE阶段执行(自定义repository_rule)
如果需要在拉取依赖阶段执行bash命令(比如处理下载后的文件),自定义repository_rule:
def _my_private_repo_impl(ctx): # 带认证下载文件 ctx.download_with_auth( url = ctx.attr.url, sha256 = ctx.attr.sha256, headers = {"Authorization": "Bearer " + ctx.attr.token}, ) # 执行bash命令解压文件 ctx.execute(["unzip", "xyz.zip"]) # 生成BUILD文件 ctx.file("BUILD.bazel", ctx.attr.build_file_content) my_private_repo = repository_rule( implementation = _my_private_repo_impl, attrs = { "url": attr.string(), "sha256": attr.string(), "token": attr.string(), "build_file_content": attr.string(), }, )
在WORKSPACE中调用自定义规则:
my_private_repo( name = "<lib_name>", url = "<私有库URL>", sha256 = "<sha256值>", token = "${BAZEL_PRIVATE_TOKEN}", build_file_content = """ cc_library( name = "core", srcs = glob(["src/**/*.cpp"]), hdrs = glob(["include/**/*.h"]), ) """, )
内容的提问来源于stack exchange,提问作者Sameer J
相关产品推荐
相关产品推荐

