Bazel中 Analysis阶段运行的Rule不能访问文件怎么办?

在Analysis阶段会运行rule的实现函数,但此时所有文件还只是“声明”, 不能在这个阶段读取任何文件内容。

📌 为什么在 Analysis 阶段运行了你的 rule?

这是 Bazel 的设计哲学:

Bazel 想要构建是 声明式的、可追踪的、可并行的、可缓存的
所以它把  构建动作(actions) 运行动作(execution)严格分开

📌 在Analysis阶段是做什么呢?

构建动作的图  (constuct action graph)。

For each target in post-order, run the rule implementation.


Rules CAN
        declare output files and actions that produce them.
        access attributes and file names from current target.
        access "providers" (metadata) from attribute targets.
        return providers for use by dependent targets.
Rules CANNOT
        read or write files directly.
        run commands directly.

Runs on the host machine, in parallel. Action graph cached in memory.

📌 想读取依赖文件内容该怎么办呢?

在 Bazel 中,如果你需要基于某个文件内容做某种转换或构建,可行的一个方法是:

✅ 在 Analysis 阶段 声明该文件为输入
✅ 在 Execution 阶段 通过构建动作(action)中的命令 来读取它的内容、处理它。

📌 示例:你想要构建一个 target,它依赖一个 JSON 文件,提取里面的版本号并生成一个头文件。

🚫 错误方式(想在 rule 里读取 JSON 文件):

# 错误示意:rule implementation 想在 Analysis 阶段直接读取内容
with open(ctx.file.config_json.path) as f:
    data = json.load(f)
    version = data["version"]

这在 Bazel 中是 不允许的,因为:

  • Analysis 阶段 禁止访问文件内容

  • .path 是未来文件路径,实际还没被复制或生成。


✅ 正确做法:声明为输入 + 写个脚本在 Execution 阶段读取

def _my_rule_impl(ctx):
    output = ctx.actions.declare_file("version_header.h")
    ctx.actions.run(
        inputs = [ctx.file.config_json],
        outputs = [output],
        arguments = [ctx.file.config_json.path, output.path],
        executable = ctx.executable._script,
    )
    return DefaultInfo(files = depset([output]))

my_rule = rule(
    implementation = _my_rule_impl,
    attrs = {
        "config_json": attr.label(allow_single_file = True),
        "_script": attr.label(
            allow_single_file = True,
            executable = True,
            default = "//tools:extract_version_script",  # 你写的脚本
        ),
    },
)

 


🔧 脚本 extract_version_script(Python/POSIX shell):

比如 Python 实现:

# extract_version_script.py
import json
import sys

with open(sys.argv[1]) as f:
    data = json.load(f)
    version = data["version"]

with open(sys.argv[2], "w") as out:
    out.write(f"#define VERSION \"{version}\"\n")

 


✅ 这样做的好处:

  1. 规则是 声明式的

  2. 所有输入输出都在 Bazel 的控制之中;

  3. 文件内容读取只发生在执行阶段

  4. 结果是可缓存的、可重现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值