hedronvision / bazel-compile-commands-extractor

Goal: Enable awesome tooling for Bazel users of the C language family.
Other
659 stars 109 forks source link

Wrong bazel-out path when target uses transition to modify features #158

Open kon72 opened 8 months ago

kon72 commented 8 months ago

In the reproducible code below, bazel build //:b would run the compilation under the directory bazel-out/darwin_arm64-fastbuild-ST-299abaa87f6b, but the generated compile commands have bazel-out/darwin_arm64-fastbuild-ST-3b9a2f2abd71 in place of that.

After some digging, it looks --features flags used in the aquery command is causing the bazel-out hash to change.

As a quick workaround, omitting features flag from aquery args fixed this issue. (But surely it's going to surface up some other problems...)

Minimal reproducible example

transition.bzl
def _test_transition_impl(settings, attr):
    _ignore = [attr]

    features = settings["//command_line_option:features"] + ["foo"]

    return {
        "//command_line_option:features": features,
    }

_test_transition = transition(
    implementation = _test_transition_impl,
    inputs = ["//command_line_option:features"],
    outputs = ["//command_line_option:features"],
)

def _test_rule_impl(ctx):
    return [DefaultInfo(files = depset(ctx.files.cc_target))]

test_rule = rule(
    implementation = _test_rule_impl,
    attrs = {
        "cc_target": attr.label(cfg = _test_transition, mandatory = True),
        "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
    },
)
BUILD
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
load("//:transition.bzl", "test_rule")

refresh_compile_commands(
    name = "refresh_compile_commands",
    targets = {
        ":b": "",
    },
)

cc_binary(
    name = "a",
    srcs = ["a.cc"],
)

test_rule(
    name = "b",
    cc_target = ":a",
)
スクリーンショット 2024-01-09 16 48 49
kon72 commented 7 months ago

It's ugly, but a solution I can come up with is:

  1. Run aquery with --features flags to query compile commands (that contain wrong bazel-out path)
  2. Run aquery again but this time without --features flags, to get a correct bazel-out path
  3. Replace wrong paths in commands with correct ones
cpsauer commented 7 months ago

Thanks so much for tracking it down and reporting, Kon.

We really do need those features off (for the reasons in the comments next to them), and compiler param files need to be on for the actual compilation on Windows. I can't think of a better solution offhand than the one you propose.

Might also be worth filing a Bazel issue?

cpsauer commented 7 months ago

Hmm, actually, I'm seeing this work okay for Android builds in my personal project. I'm wondering if, perhaps, they turned on param files by default in the Mac toolchain you're using, and that's why we're seeing it? I still can't think of a better solution, unfortunately.

cpsauer commented 7 months ago

I did a more thorough test on my main project and removing the --feature=-'s in refresh.template.py didn't seem to lead to changes in the bazel-out paths there, for the macOS host as well as for transitions to iOS and Android. So it must be something about that transition type? Super duper weird.