buck2
buck2 copied to clipboard
aquery function confusion (deps vs all_actions)
I wanted to do something that I thought was pretty simple. Get all the actions for a particular target. I tried all_actions()
, and for a while I thought that was doing the right thing.
Later I came to find out that this would include actions that, I guess, aren't normally run when you build the target. I came to this conclusion after noticing that when I run buck2 aquery all_actions(<some-target-literal>)
I will occasionally see both PIC and non-PIC entries in the output for the exact same file. I know this isn't correct, because when I just build the target buck2 build <the-same-target-literal>
, no actions execute which build the PIC version.
So I started playing around with other query functions. I tried buck2 aquery deps(<some-target-literal>, 1)
and found that this more closely matches the real set of actions that run when you build the target. But that returns a bunch of dependent targets that I didn't want. Like toolchain targets, and other actions for targets that aren't that exact same target literal.
Then I found that I can use filter(<target>, deps(<target>, 1))
to get the exact set that I wanted.
But that didn't work either because that was actually missing some targets that were needed. For example, it didn't include the action for writing the .cpp.argsfile
for an exe target, whereas all_actions()
did.
So now I'm back to being stuck again.
Ultimately, what I'm really interested in the following: For a given target literal, I want
- All c_compile and cxx_compile actions.
- All write actions that output argsfiles referenced by any action from 1.
Is this possible?
Separately, what is the reason for all_actions()
seemingly including actions that don't execute when you buck2 build
the same target? And why is all_actions(T)
a superset of filter(T, deps(T, 1))
instead of being identical?
All c_compile and cxx_compile actions.
Maybe attrfilter
would work? (These are buck1 docs, we are working on adding this to buck2 docs, but the concept/args are the same). You could filter the results based on the category
attr matching c_compile or cxx_compile.
All write actions that output argsfiles referenced by any action from 1.
We don't support outputs
attr on actions, and we aren't planning to. I think maybe you can also use attrfilter
on cmd
attr to search for the expected file extension, but maybe this is brittle. cc @cjhopman for any other ideas
Separately, what is the reason for all_actions() seemingly including actions that don't execute when you buck2 build the same target? And why is all_actions(T) a superset of filter(T, deps(T, 1)) instead of being identical?
I think all_actions()
is for obtaining all the registered actions declared within the analysis of a given target, which I think will end up including both pic
and non pic
actions. deps()
operates just on the action's inputs, so I think it doesn't necessarily include all of the actions that all_actions()
would find, since the target literal might have declared other actions.
cc @cjhopman in case the above explanation is incorrect, or there's more to add
I also found in the prelude where pic actions are added unconditionally. Why is this? If nothing ever consumes pic objects, what’s the point of creating actions to generate them?
When we do analysis for a C++ library we produce a static, shared and pic version. All three of those are available as subtargets, e.g. buck2 build :foo[shared]
. But they are also available in the providers, so that depending on how the consumer (e.g. the C++ binary) wants they can grab the shared, static or pic versions. We only build the actions that are actually required for the final DefaultInfo
.
So to answer the question we create the actions since we don't know when we create them if someone will want them or not. We only run the actions if they are actually required. With things like anon_targets we can actually defer creating the actions until they are required, at the cost of other complexity. We don't bother for C++ libraries (only three variations, most of the action cost is in the compilation rather than the link) but we do for Swift libraries (they can be infinite variations).