如何将调用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
相关产品推荐
相关产品推荐

