如何在Bazel中以构建规则而非WORKSPACE规则拉取远程文件?
解决Bazel中用构建规则拉取远程文件的问题
首先得明确你碰到这个报错的核心原因:http_file是仓库规则(repository rule),这类规则只能在WORKSPACE文件或者被WORKSPACE直接加载的初始化脚本里调用——它们是用来在Bazel初始化仓库阶段拉取依赖的,没法在BUILD文件的构建流程中间接调用,这就是为啥你会看到'repository rule http_file' can only be called during workspace loading这个错误。
如果你确实需要用构建规则(而非WORKSPACE规则)来拉取远程文件,这里有两个可行的方案:
方案一:用genrule快速实现
直接在BUILD文件里写genrule,结合curl和sha256sum完成下载和校验:
genrule( name = "download_foo", outs = ["foo"], cmd = """ # 拉取远程文件到输出路径 curl -L -o $@ "https://example.com" # 校验文件哈希,确保完整性 echo "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 $@" | sha256sum --check """, # 标记输出文件为可执行 executable = True, )
这个规则会在构建阶段执行,完全避开WORKSPACE规则的加载限制,而且通过sha256校验保证文件没被篡改。
方案二:自定义构建规则(复用性更强)
如果需要在多个地方复用这个逻辑,推荐写一个自定义的Starlark构建规则:
- 先创建一个
download_file.bzl文件,定义规则逻辑:
def _download_file_impl(ctx): # 执行下载和校验的shell命令 ctx.actions.run_shell( outputs = [ctx.outputs.out], command = """ curl -L -o $@ "{url}" echo "{sha256} $@" | sha256sum --check """.format( url = ctx.attr.url, sha256 = ctx.attr.sha256, ), ) # 返回默认信息,标记是否可执行 return [DefaultInfo(executable = ctx.attr.executable)] download_file = rule( implementation = _download_file_impl, attrs = { "url": attr.string(mandatory = True, doc = "远程文件的URL"), "sha256": attr.string(mandatory = True, doc = "文件的SHA256哈希值"), "executable": attr.bool(default = False, doc = "是否将输出标记为可执行文件"), }, outputs = {"out": "%{name}"}, )
- 然后在BUILD文件里加载并使用这个规则:
# 替换成你存放download_file.bzl的路径 load("//tools:download_file.bzl", "download_file") download_file( name = "foo", url = "https://example.com", sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", executable = True, )
注意事项
- 以上方案依赖构建环境中的
curl和sha256sum工具,Linux/macOS一般默认自带;如果是Windows环境,可能需要替换成Invoke-WebRequest和Get-FileHash这类PowerShell命令,或者确保环境里有Git Bash等提供类Unix工具的环境。 - 自定义规则可以根据需求扩展,比如支持多URL fallback、代理配置等,比genrule更灵活。
内容的提问来源于stack exchange,提问作者sdgfsdh
相关产品推荐
相关产品推荐

