buck2
buck2 copied to clipboard
Overriding a rule name (buck.type) to match its public, exported name?
Consider an API like the following for exposing rules to users:
__private_name = rule(...)
public_api = struct(
rule01 = __private_name
)
The goal of an API like this is to just be easier to read and write; you don't need to know the public symbols coming out of a module and when applied consistently makes it a little easier to find things. It's nothing groundbreaking. Just me exploring the API design space.
So now when I write BUILD
files I use public_api.rule01
to declare targets. Great.
But this falls down when querying target nodes. The buck.type
of a rule is given by the name given to the global top-level rule
, not based on what's exported from a module (which would be hard to understand/make sense of, in any case.) In other words, the following query fails:
buck cquery 'kind("public_api.rule01", ...)'
This works:
buck cquery 'kind("__private_name", ...)'
Which exposes the internal name from the module. This isn't necessarily specific to struct()
-like APIs; a simple case like public_name = __private_name
suffers from the same issue too, I think. The internal name is leaked through to the public user.
You can verify this with a cquery; in the following example the exported name of the rule for users is rust.binary
, not __rust_binary
:
austin@GANON:~/src/buck2-nix.sl$ buck cquery src/hello: --output-all-attributes
Build ID: ab0ce60d-bea1-458b-b886-5c02c610306d
Jobs completed: 1. Time elapsed: 0.0s.
{
"root//src/hello:main (prelude//platform:default-632fe5438d4aecc1)": {
"buck.type": "__rust_binary",
"buck.deps": [
"prelude//toolchains/rust:rust-stable (prelude//platform:default-632fe5438d4aecc1)"
],
"buck.package": "root//src/hello:TARGETS",
"buck.oncall": null,
"buck.target_configuration": "prelude//platform:default-632fe5438d4aecc1",
"buck.execution_platform": "prelude//platform:default",
"name": "main",
"default_target_platform": null,
"target_compatible_with": [],
"compatible_with": [],
"exec_compatible_with": [],
"visibility": [],
"tests": [],
"_toolchain": "prelude//toolchains/rust:rust-stable (prelude//platform:default-632fe5438d4aecc1)",
"file": "root//src/hello/main.rs",
"out": "hello"
}
}
So the question is: would it be possible to allow a rule to specify its buck.type
name in some manner so that queries and rule uses can be consistent? Perhaps just another parameter to rule()
that must be a constant string? If that could work?
It's worth noting this is mostly a convenience so that a rule user isn't confused by the leaked name. I can keep the nice struct()
-like API and have the __private_names
follow a similar naming logic so that "translating" between the two isn't hard. Not that big a deal.
I can imagine this might be too deeply woven into the implementation to easily fix.
I think this seems like a fine improvement. Right now buck.type comes from some internal data that probably can't be changed (as it's used to lookup the rule impl function during analysis), but I don't see any reason why we couldn't just store a separate user-configurable (with current default) field on rules. We could even call it "kind" and then buck.kind would use it (and the kind()
query function could match against it) and maybe we could then get buck.type to be back to the fully-qualified symbol (it used to be this, but to match buck1 behavior we switched it to just the local name of the symbol).