Apply cpu transition to cc_binary rule in Bazel

Viewed 168

I've a c target that always must be compiled for darwin_x86_64, no matter the --cpu set when calling bazel build. It's the only target that always must be compiled for a specific cpu in a big project.

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)

In the bazel documentation it seems to be possible to do this using transitions. Maybe something like:

def _force_x86_64_impl(settings, attr):
    return {"//command_line_option:cpu": "darwin_x86_64"}

force_x86_64 = transition(
    implementation = _force_x86_64_impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]
)

But how do I tie these two together? I'm probably missing something obvious, but I can't seem to find the relevant documentation over at bazel.build.

2 Answers

You've got the transition defined, now you need to attach it to a rule.

r = rule(
    implementation = _r_impl,
    attrs = {
        "_allowlist_function_transition": attr.label(
            default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
        ),
        "srcs": attr.label(cfg = force_x86_64),
    },
)

def _r_impl(ctx):
    return [DefaultInfo(files = ctx.attr.srcs[0][DefaultInfo].files)]

This defines a rule that attaches the appropriate transition to the srcs you pass it, and then simply forwards the list of files from DefaultInfo. Depending on what you're doing, this might be sufficient, or you might also want to forward the runfiles contained in DefaultInfo and/or other providers.

Use target_compatible_with

Example (only compiled on Windows):

cc_library(
    name = "win_driver_lib",
    srcs = ["win_driver_lib.cc"],
    target_compatible_with = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
    ],
)
Related