Skip to content

Target-level modifiers are not applied when depending on an attrs.dep() #1181

@cbarrete

Description

@cbarrete

Problem and repro

Consider the following:

BUCK

cxx_binary(
    name = "bin",
    srcs = ["main.cpp"],
    modifiers = ["//build/platforms:release"],
)

command_alias(
    name = "cmd",
    exe = ":bin",
)

main.cpp

#include <iostream>

int main()
{
#ifdef NDEBUG
    std::cout << "release" << std::endl;
#else
    std::cout << "debug" << std::endl;
#endif
    return 0;
}
> buck2 run :bin
release
> buck2 run :cmd
debug

I would expect :bin to be built as a dependency of :cmd the same way as it is when built directly via the CLI, but it is not.

This is a simplistic example, but basically any modifiers set on targets in the build graph seem to be completely ignored.

I believe this to be a bug, because if a target requires some modifiers to be applied, the build may be completely broken, and buck2 run :cmd will result in a build failure, rather than just the wrong configuration being built.

Some of the things I have tried

Writing a simpler rule

I've written my own command rule, in case there was something weird about command_alias. There is not, I got the same behavior.

Using attrs.arg() or attrs.configured_dep()

Using attrs.arg() and using a string parameter macro to pass :bin (either via $(exe_target) or $(location)) made no difference.

attrs.configured_dep() does not really help, because while it can change the base platform being used, it does not affect modifier application (they get skipped all the same).

Setting the modifier on the CLI

This "works", but is not compatible with my actual use case, where we have modifiers set deep in the build graph, and asking users to also know about them and set them on the CLI is not reasonable.

Using target_compatible_with

Using target_compatible_with instead of (or besides) modifiers is useful to catch missing constraints earlier in the build, but it does not solve the issue: end-users still need to specify all constraints at the top-level target being built, no matter how deep in the build tree those constraints are being used, and how irrelevant they are to the end user.

This is a considerable abstraction leak.

Transistions

Transitions can be used to add constraints to some parts of the build tree.

We could use them for this purpose, but they are significantly more cumbersome to use, less user friendly, and our understanding is that modifiers are supposed to replace them for this use case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions