facebook / buck2

Build system, successor to Buck
https://buck2.build/
Apache License 2.0
3.53k stars 215 forks source link

aquery.eval() does not respect target platform passed to `ctx.configured_targets()` #514

Closed zjturner closed 9 months ago

zjturner commented 10 months ago
def _foo_impl(ctx):
    targets = ctx.configured_targets("...", target_platform=ctx.cli_args.platform)
    aquery = ctx.aquery()

    ctx.output.print("Found targets {} with platform {}".format(targets, ctx.cli_args.platform))
    for target in targets:
        ctx.output.print("Handling target {}".format(target))
        query_string = "attrfilter(identifier, .cpp.argsfile, all_actions({}))".format(target.label.raw_target())
        actions = list(aquery.eval(query_string))

        for action in actions:
            ctx.output.print("Found action {}".format(action))

foo = bxl_main(
    impl = _foo_impl,
    cli_args = {
        "platform": cli_args.option(cli_args.target_label()),
    }
)

Assume the default platform is called P but there is another platform defined with the name Q.

If you run this as buck2 bxl :foo.bxl:foo -- platform=Q you will get the following output:

Found targets [T (Q)] with platform Q
Iterated target configured_target_node(name = T (Q), ...)
Found action (target: T (P), id: `6`)

I found that if I use a different queryfunction like deps(), then the target platform is respected.

wendy728 commented 9 months ago

There are 2 problems here:

  1. You're assuming that ctx.configured_targets() is being passed with its configuration into eval(), but it's not actually:

query_string = "attrfilter(identifier, .cpp.argsfile, all_actions({}))".format(target.label.raw_target())

You're using raw_target(), which means you're stripping the node of the configuration. This is not to say that you're able to pass in the configured version into query_string, though. This brings me to my next point.

  1. In order to use a configuration with aquery.eval(), you should either set the global target platform via --target-platform on the buck2 command, or pass in the target platform into aquery() instantiation directly (aquery = ctx.aquery(target_platform = "foo//bar:baz"). eval() is a special query which operates on strings rather than structured Starlark types, and strings do not support any kind of configuration. This tidbit probably should be explicitly said in the docs, so I will add this soon. deps() works because it actually accepts structured Starlark types such as configured nodes, and will respect this configuration in computations.
zjturner commented 9 months ago

Thanks, the fact that I can pass a platform to aquery() is the piece I missed!