facebook / facebook/buck2

Overriding a rule name (buck.type) to match its public, exported name?

Open
#95 1 comment 0 reactions 0 assignees View on GitHub
enhancement
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.