使用 cc_common API 的自定义 C++ 规则

Custom C++ rule with the cc_common API

我正在尝试使用 cc_common API 编写自定义规则来编译 C++ 代码。这是我目前的实现尝试:

load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")   
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "C_COMPILE_ACTION_NAME") 

def _impl(ctx):
    cc_toolchain = find_cpp_toolchain(ctx)
    feature_configuration = cc_common.configure_features(
        cc_toolchain = cc_toolchain,
        unsupported_features = ctx.disabled_features,
    )
    compiler = cc_common.get_tool_for_action(
        feature_configuration=feature_configuration,
        action_name=C_COMPILE_ACTION_NAME
    )
    compile_variables = cc_common.create_compile_variables(
        feature_configuration = feature_configuration,
        cc_toolchain = cc_toolchain,
    )
    compiler_options = cc_common.get_memory_inefficient_command_line(
        feature_configuration = feature_configuration,
        action_name = C_COMPILE_ACTION_NAME,
        variables = compile_variables,
    )

    outfile = ctx.actions.declare_file("test.o")
    args = ctx.actions.args()
    args.add_all(compiler_options)
    ctx.actions.run(
        outputs = [outfile],
        inputs = ctx.files.srcs,
        executable = compiler,
        arguments = [args],
    )

    return [DefaultInfo(files = depset([outfile]))]

但是,此操作失败并出现错误 "execvp(external/local_config_cc/wrapped_clang, ...)": No such file or directory。我认为这是因为 get_tool_for_action returns 表示路径的字符串,而不是 File 对象,因此 Bazel 不会将 wrapped_clang 添加到沙箱。在禁用沙盒的情况下执行规则似乎证实了这一点,因为它已成功完成。

有没有办法在不禁用沙箱的情况下实施此自定义规则?

如果您使用 ctx.actions.run_shell,您可以将与工具链关联的文件添加到输入 (ctx.attr._cc_toolchain.files)。此外,您还需要添加编译器环境变量。例如

srcs = depset(ctx.files.srcs)
tools = ctx.attr._cc_toolchain.files
...
compiler_env = cc_common.get_environment_variables(
   feature_configuration = feature_configuration,
   action_name = C_COMPILE_ACTION_NAME,
   variables = compiler_variables,
)
...
args = ctx.actions.args()
args.add_all(compiler_options)
ctx.actions.run_shell(
    outputs = [outfile],
    inputs = depset(transitive = [srcs, tools]), # Merge src and tools depsets
    command = "{compiler} $*".format(compiler = compiler),
    arguments = [args],
    env = compiler_env,
)

Bazel 不会自动将文件添加为操作输入,您必须像在第二种方法 (ctx.attr._cc_toolchain.files) 中那样明确地执行此操作。这样,ctx.actions.run 应该就可以正常工作了。