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

如何将调用native.genrule与native.cc_library的宏转为Bazel规则?

ISPC转Bazel规则:生成文件缺失问题排查与解决建议

问题描述

现有一个调用native.genrule和native.cc_library的ispc_cc_library宏,需要转换为Bazel规则。已编写ispc_library2规则及ispc_cc_library2宏,但测试时出现生成的square.o、square.h文件缺失错误,不清楚如何正确传递生成产物给cc_library,求解决建议。

原宏代码

def ispc_cc_library(name, out, ispc_main_source_file, srcs, defines = [], **kwargs):
    generated_header_filename = out

    ispc_defines_list = ""
    if "defines" in kwargs:
        ispc_defines_list = "-D" + " -D".join(kwargs["defines"])
    elif len(defines) > 0:
        ispc_defines_list = "-D" + " -D".join(defines)

    native.genrule(
        name = "%s_ispc_gen" % name,
        srcs = srcs,
        outs = [name + ".o", generated_header_filename],
        cmd = select({
            "@platforms//os:linux": "$(location @ispc_linux_x86_64//:ispc) %s --target=avx2 --target-os=linux --arch=x86-64 --addressing=64 --pic $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generated_header_filename, name),
            "@rules_ispc//:osx_arm64": "$(location @ispc_osx_arm64//:ispc) %s --target=neon --target-os=macos --arch=aarch64 --addressing=64 --pic $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generated_header_filename, name),
            "@rules_ispc//:osx_x86_64": "$(location @ispc_osx_x86_64//:ispc) %s --target=sse2 --target-os=macos --arch=x86-64 --addressing=64 --pic $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generated_header_filename, name),
            "@platforms//os:windows": "$(location @ispc_windows_x86_64//:ispc) %s --target=avx2 --target-os=windows --arch=x86-64 --addressing=64 $(locations %s) --header-outfile=$(location %s) -o $(location %s.o)" % (ispc_defines_list, ispc_main_source_file, generated_header_filename, name),
        }),
        tools = select({
            "@platforms//os:linux": ["@ispc_linux_x86_64//:ispc"],
            "@rules_ispc//:osx_arm64": ["@ispc_osx_arm64//:ispc"],
            "@rules_ispc//:osx_x86_64": ["@ispc_osx_x86_64//:ispc"],
            "@platforms//os:windows": ["@ispc_windows_x86_64//:ispc"],
        }),
    )
    native.cc_library(
        name = name,
        srcs = [name + ".o"],
        hdrs = [name + ".h"],
        defines = defines,
        **kwargs
    )

尝试的规则代码

def _ispc_cc_library_impl(ctx):
    info = ctx.toolchains["@rules_ispc//tools:toolchain_type"].ispc_info
    default_target_os = info.default_target_os

    generated_header_filename = ctx.attr.generated_header_filename

    ispc_defines_list = ""
    if len(ctx.attr.defines) > 0:
        ispc_defines_list = "-D" + " -D".join(ctx.attr.defines)

    srcs = ctx.files.srcs
    inputs = depset(srcs)  # see https://bazel.build/extending/rules

    output_file1 = ctx.actions.declare_file(generated_header_filename)
    output_file2 = ctx.actions.declare_file(ctx.attr.name + ".o")

    args = ctx.actions.args()
    args.add("-o", generated_header_filename)
    args.add(ispc_defines_list)
    args.add("--target=neon")
    args.add("--target-os=%s" % default_target_os)
    args.add("--arch=aarch64")
    args.add("--addressing=64")
    args.add("--pic")
    args.add("square.ispc")#ctx.attr.ispc_main_source_file)
    args.add("--header-outfile=%s" % generated_header_filename)
    args.add("-o")
    args.add(ctx.attr.name + ".o")

    ctx.actions.run(
        inputs = inputs,
        outputs = [output_file1, output_file2],
        arguments = [args],
        executable = info.ispc_path,
    )

    return [
        DefaultInfo(files = depset([output_file1, output_file2])),
    ]

ispc_library2 = rule(
    implementation = _ispc_cc_library_impl,
    doc = """Compiles a ISPC program and makes it available as a C++ library

This rule uses a precompiled version of ISPC v1.19.0 for compilation.""",
    attrs = {
        "generated_header_filename": attr.string(
            doc = """
            Name of the generated header file.
            """,
        ),
        "ispc_main_source_file": attr.label(
            allow_single_file = [".ispc"],
            doc = """
            File to compile.
            """,
        ),
        "srcs": attr.label_list(
            allow_files = [".ispc", ".isph"],
            doc = """
            The list of ISPC source files that are compiled to create the library.
            Only `.ispc` and `.isph` files are permitted.
            """,
        ),
        "defines": attr.string_list(
            doc = """
            List of defines handed over to the ISPC compiler.
            """,
        ),
        #"out": attr.output_list(),
    },
    #outputs = {
    #    "out": "{generated_header_filename}.o"
    #},
    toolchains = ["@rules_ispc//tools:toolchain_type"],
)

def ispc_cc_library2(name, generated_header_filename, ispc_main_source_file, srcs, defines = [], **kwargs):
    ispc_library2(
        name = "%s_ispc_gen" % name,
        generated_header_filename = generated_header_filename,
        ispc_main_source_file = ispc_main_source_file,
        srcs = srcs,
        defines = defines,
        **kwargs
    )
    native.cc_library(
        name = name,
        srcs = [name + ".o"],
        hdrs = [name + ".h"],
        defines = defines,
        #deps = ["%s_ispc_gen" % name],
        **kwargs
    )

错误信息

ERROR: /Users/vertexwahn/rules_ispc/tests/defines/BUILD.bazel:12:17: Linking defines/libsquare.a failed: missing input file '//defines:square.o'
ERROR: /Users/vertexwahn/rules_ispc/tests/defines/BUILD.bazel:12:17: Middleman _middlemen/_S_Sdefines_Csquare-cc_library-compile failed: missing input file '//defines:square.h'
ERROR: /Users/vertexwahn/rules_ispc/tests/defines/BUILD.bazel:12:17: Linking defines/libsquare.a failed: 1 input file(s) do not exist
ERROR: /Users/vertexwahn/rules_ispc/tests/defines/BUILD.bazel:12:17: Middleman _middlemen/_S_Sdefines_Csquare-cc_library-compile failed: 1 input file(s) do not exist
ERROR: /Users/vertexwahn/rules_ispc/tests/defines/BUILD.bazel:12:17: //defines:square: missing input file '//defines:square.o'
ERROR: /Users/vertexwahn/rules_ispc/tests/defines/BUILD.bazel:12:17 Linking defines/libsquare.a failed: 1 input file(s) do not exist

复现步骤

git clone https://github.com/Vertexwahn/rules_ispc.git
cd rules_ispc/tests/defines
bazel build //defines:main # 执行后会失败

解决建议

1. 修正产物引用逻辑

cc_library不能直接用文件名引用生成文件,必须通过生成目标的标签路径引用。修改ispc_cc_library2宏:

def ispc_cc_library2(name, generated_header_filename, ispc_main_source_file, srcs, defines = [], **kwargs):
    gen_name = "%s_ispc_gen" % name
    ispc_library2(
        name = gen_name,
        generated_header_filename = generated_header_filename,
        ispc_main_source_file = ispc_main_source_file,
        srcs = srcs,
        defines = defines,
        **kwargs
    )
    native.cc_library(
        name = name,
        srcs = [":%s/%s.o" % (gen_name, name)],
        hdrs = [":%s/%s" % (gen_name, generated_header_filename)],
        defines = defines,
        **kwargs
    )

2. 修复ISPC执行参数错误

  • 替换硬编码的square.ispc为实际主源文件路径
  • 调整参数顺序,符合ISPC命令规范,避免重复/错误参数:
def _ispc_cc_library_impl(ctx):
    info = ctx.toolchains["@rules_ispc//tools:toolchain_type"].ispc_info
    default_target_os = info.default_target_os

    generated_header_filename = ctx.attr.generated_header_filename

    # 正确处理定义参数
    srcs = ctx.files.srcs
    main_src = ctx.file.ispc_main_source_file
    inputs = depset(srcs + [main_src])

    output_file1 = ctx.actions.declare_file(generated_header_filename)
    output_file2 = ctx.actions.declare_file(ctx.attr.name + ".o")

    args = ctx.actions.args()
    # 添加定义参数
    if ctx.attr.defines:
        args.add_all(ctx.attr.defines, format_each="-D%s")
    # 添加编译目标参数
    args.add("--target=neon")
    args.add("--target-os=%s" % default_target_os)
    args.add("--arch=aarch64")
    args.add("--addressing=64")
    args.add("--pic")
    # 指定输入文件
    args.add(main_src.path)
    # 指定输出文件和头文件
    args.add("--header-outfile", output_file1.path)
    args.add("-o", output_file2.path)

    ctx.actions.run(
        inputs = inputs,
        outputs = [output_file1, output_file2],
        arguments = [args],
        executable = info.ispc_path,
    )

    return [
        DefaultInfo(files = depset([output_file1, output_file2])),
    ]

3. 确保输入文件完整

将主ISPC源文件加入inputs集合,避免编译时找不到依赖文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:25:04