You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过py_binary与genrule生成C++文件并解决构建报错

解决Bazel生成C++文件并引入到cc_binary的问题

问题根源

Bazel采用沙盒构建机制,不允许genrule直接写入原代码目录(比如你的weights文件夹),所有生成文件必须放在Bazel管理的输出目录下。之前的报错正是因为尝试直接写入原目录,导致Bazel无法追踪到生成的文件。

修复步骤

1. 调整Python脚本参数

修改scripts/blob_to_cpp.py,让它支持接收输入文件路径、输出头文件路径、输出源文件路径三个参数,确保能将生成内容写入Bazel指定的输出位置:

import sys

def main():
    if len(sys.argv) != 4:
        print("Usage: blob_to_cpp.py <input_blob> <output_header> <output_source>")
        sys.exit(1)
    
    input_path = sys.argv[1]
    header_path = sys.argv[2]
    source_path = sys.argv[3]

    # 保留你原有的文件生成逻辑,将内容写入header_path和source_path
    # 示例(替换成你的实际逻辑):
    with open(header_path, "w") as h:
        h.write(f"#pragma once\n// Generated from {input_path}")
    with open(source_path, "w") as s:
        s.write(f"#include \"{header_path.split('/')[-1]}\"\n// Generated content")

if __name__ == "__main__":
    main()

2. 编写正确的生成宏和BUILD规则

在根目录BUILD文件中,替换原有的宏和规则,确保生成文件被Bazel正确追踪,并能被cc_binary通过#include "weights/rt_alb.h"引入:

# 1. 声明Python工具
py_binary(
    name = "blob_to_cpp",
    srcs = ["scripts/blob_to_cpp.py"],
)

# 2. 定义生成C++文件并封装为cc_library的宏
def generate_cpp_from_blob_cc_library(name, blob_file):
    # 从blob文件名提取基础名称(比如weights/rt_alb.tza -> rt_alb)
    base_name = blob_file.split("/")[-1].split(".")[0]
    gen_header = f"weights/{base_name}.h"
    gen_source = f"weights/{base_name}.cpp"

    genrule(
        name = f"{name}_gen",
        srcs = [blob_file],
        outs = [gen_header, gen_source],
        # 调用Python脚本,传入输入文件和两个输出文件的路径
        cmd = "$(location //:blob_to_cpp) $(SRCS) $(location {gen_header}) $(location {gen_source})",
        tools = ["//:blob_to_cpp"],
    )

    # 将生成的文件封装为cc_library,供cc_binary依赖
    cc_library(
        name = name,
        srcs = [gen_source],
        hdrs = [gen_header],
        # 将当前目录加入include路径,让cc_binary能通过"weights/rt_alb.h"找到头文件
        includes = ["."],
        visibility = ["//visibility:public"],
    )

# 3. 调用宏生成权重对应的C++库
generate_cpp_from_blob_cc_library(
    name = "rt_alb_weights",
    blob_file = "weights/rt_alb.tza",
)

# 4. 定义你的cc_binary,依赖生成的库
cc_binary(
    name = "Demo",
    srcs = ["main.cpp"],
    deps = [":rt_alb_weights"],
)

3. 验证include路径

在你的main.cpp中,直接使用#include "weights/rt_alb.h"即可,Bazel会通过cc_library的includes = ["."]配置,将生成的weights虚拟目录加入编译的include路径。

关键说明

  • 所有生成文件必须在genrule的outs中声明,Bazel会自动管理这些文件的生成路径(位于bazel-out目录下)。
  • 通过cc_library封装生成的文件,既能保证构建顺序(先生成文件再编译),又能通过includes属性让cc_binary找到头文件。

内容的提问来源于stack exchange,提问作者Vertexwahn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:46:07