Support select() on aspect attributes
- Dominant language
- Java
- Stars
- 25.8k
- Forks
- 4.6k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 75
Description
### Description of the problem / feature request:
When an aspect declares `attrs = {foo:...}`, the build fails when the rule it's attached to sets `foo = select(...)`:
```
ERROR: /home/workspace/BUILD:3:1: //:hello: attribute 'pure' has a select() and aspect
//:def.bzl%go_archive_aspect also declares '//:hello'. Aspect attributes don't currently
support select().
```
Before my fix to #5120, this was a crash. My fix turned it into a proper error. But there's no conceptual reason why this shouldn't work.
### Feature requests: what underlying problem are you trying to solve with this feature?
Reduce instances where rule users can't use `select()` for no clear reason.
### Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Copied from #5120:
```
# BUILD.bazel
load("//:def.bzl", "go_binary")
go_binary(
name = "hello",
srcs = ["hello.go"],
pure = select({"//conditions:default": "auto"}),
)
```
```
# def.bzl
def _go_archive_aspect_impl(ctx):
return []
go_archive_aspect = aspect(
_go_archive_aspect_impl,
attrs = {
"pure": attr.string(values = [
"on",
"off",
"auto",
]),
},
)
def _go_binary_impl(ctx):
return []
go_binary = rule(
_go_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = [".go"]),
"deps": attr.label_list(aspects = [go_archive_aspect]),
"pure": attr.string(
values = [
"on",
"off",
"auto",
],
default = "auto",
),
},
)
```
### What operating system are you running Bazel on?
Linux.
### What's the output of `bazel info release`?
`release 0.23.2`
### What's the output of `git remote get-url origin ; git rev-parse master ; git rev-parse HEAD` ?
https://github.com/gregestren/bazel.git
52cf982bfad2836f7b7239a67ee322d90f43c4d5
21d03fed6f78ad3473e4f83d83e1a33b18119b69
### Have you found anything relevant by searching the web?
Just #5120.
### Any other information, logs, or outputs that you want to share?
While conceptually simple, this won't be a 10-minute fix.
The problem is that aspect definitions are created during Bazel's *loading* phase, which is before Bazel knows what values `select()s` actually bind to. And aspect definitions read their attribute values as a part of initialization.
So to fix this we have to refactor aspect definitions to either **a)** not read their attribute values or **b)** read them in some lazy way that can be deferred until the aspect implementation triggers.
Contributor guide
Research direction
Start with the minimal BUILD.bazel and def.bzl reproduction, then trace how aspect definitions read attribute values during Bazel's loading phase and how the aspect implementation is triggered. Done means the rule can set the aspect attribute with select() without an error while preserving the declared attribute behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100