Overriding a rule name (buck.type) to match its public, exported name?
- Dominant language
- Rust
- Stars
- 4.4k
- Forks
- 394
- PR merge metrics
- No merged PRs in 30d
Description
Consider an API like the following for exposing rules to users:
```python
__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:
```bash
buck cquery 'kind("public_api.rule01", ...)'
```
This works:
```bash
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.
Contributor guide
Assessment
This issue has not been assessed yet.