Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce visibility on select() keys #12877

Closed
wants to merge 5 commits into from

Conversation

gregestren
Copy link
Contributor

@gregestren gregestren commented Jan 22, 2021

Example:

my_rule(
  name = "buildme",
  deps = select({
    "//other/package:some_config": [":mydeps"]
  }))

Today, //other/package:some_config is exempt from visibility checking, even though it's technically a target dep of
buildme.

While this dep is "special" vs. other deps in various ways, there's no obvious reason why it needs to be special in this way. It adds an unclear corner case exception to visibility's API.

Implementation:

select() keys are not "normal" dependencies and don't generally follow the same code path. Hence them not being automatically visibility checked like others.

In particular, normal dependencies are found in ConfiguredTargetFunction and validity-checked in RuleContext.Builder. select() keys' only purpose is to figure out which other normal dependencies should exist. There's generally no need to pass them to RuleContext.Builder. Instead, Blaze passes their ConfigMatchingProviders, which remain useful for analysis phase attribute lookups.

RuleContext.Builder needs a ConfiguredTargetAndData to do validity-checking. This patch propagates that information for select() keys too.

We could alternatively refactor the validity checking logic. But that's an even more invasive change. Or do ad hoc validity checking directly in ConfiguredTargetFunction. But that's duplicating logic we really want to keep consolidated.

Backward compatibility:

This would break existing builds if config_setting defaulted to private visibility. So this change specially defaults config_setting to public visibility, with clarifying documentation. When ready we'll want to create an incompatible change to make config_setting the same as everything else.

Fixes #12669.

RELNOTES: config_setting now honors visibility attribute (and defaults to //visibility:public)

@gregestren
Copy link
Contributor Author

gregestren commented Jan 22, 2021

This PR is proof-of-concepty. I haven't added tests and would like to resolve some philosophical questions before advancing:

  1. Should we strive for all rules supporting visibility checking? I don't think select() keys are the only rules that skip it. @katre - what about toolchain deps?
  2. This change highlights that select() deps follow a different code path than normal deps. That's why it's a 10-file change with an entirely new data class to support it. And that much more Bazel code to support. For just this maybe it's worth it. But if we had to repeat this ad hocness for X other rule types, maybe that suggests deeper design brittleness.
  3. We also have a workaround: route through aliases.

@katre
Copy link
Member

katre commented Jan 22, 2021

  1. The actual toolchain targets that are identified with register_toolchains and --extra_toolchains probably skip visibility, but the toolchains themselves (the cc_toolchain or java_toolchain targets that are consumed by rules) are visibility checked.
    a. Also, visibility is skipped for platforms that are loaded via register_execution_platforms, --extra_execution_platforms, --platforms, and --host_platforms.
  2. I'm not sure how we'd restructure configurable attributes to be more neatly supported. I think at this point the change makes sense.
  3. The workaround requires everyone who uses a select to follow it, which seems onerous.

This PR LGTM.

Example:

my_rule(
  name = "buildme",
  deps = select({
    "//other/package:some_config": [":mydeps"]
  }))

Today, //other/package:some_config is exempt from visibility checking, even
though it's technically a target dep of "buildme". While this dep is "special"
vs. other deps in various ways, there's no obvious reason why it needs to
be special in this way. It adds an unclear corner case exception to
visibility's API.

Implementation:
---------------
select() keys are not "normal" dependencies and don't generally follow the same code path. Hence them not being automatically visibility checked like others.

In particular, normal dependencies are found in ConfiguredTargetFunction and validity-checked in RuleContext.Builder. select() keys' only purpose is to figure out which other normal dependencies should exist. So there's generally no need to pass them to RuleContext.Builder. Instead, Blaze passes their ConfigMatchingProviders, which remain useful for analysis phase attribute lookups.

RuleContext.Builder needs a ConfiguredTargetAndData to do validity-checking.  This patch passes that information along for select() keys too.

We could alternatively refactor the validity checking logic. But that's an even more invasive change. Or do ad hoc validity checking directly in ConfiguredTargetFunction. But that's duplicating logic we really don't want to keep consistent.

Backward compatibility:
-----------------------
This has a very good chance of breaking builds, since all targets default to private visibility and it's unlikely existing config_settings have changed that. Pushing this forward requires an incompatible change flag.

PiperOrigin-RevId: 353131136
Change-Id: Ia5056745d135732bd35ba0ab099800d982f33f74
@gregestren
Copy link
Contributor Author

Thanks for all the feedback, @katre . Added tests and some documentation.

1 similar comment
@gregestren
Copy link
Contributor Author

Thanks for all the feedback, @katre . Added tests and some documentation.

site/docs/visibility.md Outdated Show resolved Hide resolved
@@ -795,33 +791,23 @@ public SkyValue compute(SkyKey key, Environment env) throws ConfiguredTargetFunc
throw e;
}

Map<Label, ConfigMatchingProvider> configConditions = new LinkedHashMap<>();
Map<Label, ConfiguredTargetAndData> asConfiguredTargets = new LinkedHashMap<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this entire method, or at least the part from here on, could be moved into ConfigConditions.

Copy link
Contributor Author

@gregestren gregestren Jan 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I support this idea, and tried to make headway with it. But it's too complicated for this PR, in my view. The problem is that the method has various dependencies on ConfiguredTargetFunction that aren't trivial to extract. Trivially moving it would result in ConfiguredTargetFunction and ConfigConditions calling back and forth to each other.

I do support keeping ConfiguredTargetFunction (which is a beast) simple in any ways we can. So over a longer term I'd love to make progress on things like this.

@gregestren gregestren added the team-Configurability platforms, toolchains, cquery, select(), config transitions label Jan 26, 2021
@lberki
Copy link
Contributor

lberki commented Jan 27, 2021

Yay, this is great! I mean, great modulo the necessary depot cleanup required. Do you have a sense of how much work that is?

I think this is about the best approach you can take. I was somewhat surprised that you have to plumb through two maps in ConfigConditions (I would have guessed that the ConfiguredTarget is enough), but meh.

Do we have many other places that are exempt from visibility checking? I was hoping that centralizing it into RuleContext makes it catch every case, but I was apparently mistaken in at least one case.

@gregestren
Copy link
Contributor Author

I think this is about the best approach you can take. I was somewhat surprised that you have to plumb through two maps in ConfigConditions (I would have guessed that the ConfiguredTarget is enough), but meh.

Yeah, I wasn't thrilled about that. But it's really necessary, without doing deeper Bazel refactoring.

About that refactoring... One possible alternative is to include config_settings in RuleContext.prerequisiteMap. I avoided that approach because it technically changes the semantics and I can't say with confidence that wouldn't break some other invariant. But I am intrigued. I'd like to submit this PR to get the functionality in, then try to whip up a version around that and share with you all to see if it ultimately looks viable.

Do we have many other places that are exempt from visibility checking? I was hoping that centralizing it into RuleContext makes it catch every case, but I was apparently mistaken in at least one case.

I believe the answer is near universally no. It's really only dependencies that get evaluated directly in ConfiguredTargetFunction through their own code paths that have this issue. That should only be this and some toolchain deps as described at #12877 (comment).

@bazel-io bazel-io closed this in cac82cf Jan 28, 2021
gregestren added a commit to gregestren/bazel that referenced this pull request Jan 28, 2021
Make select() keys normal attribute -> configured target prerequisite
dependencies. This automatically opts them into RuleContext.Builder's standard
visibility checking.

The main historic argument against this is interference with "manual
trimming". But that's an on-ice feature that needs fundamental reevaluation and
shouldn't block other code in the meantime.

This is a simplified alternative to
bazelbuild#12877, for bazelbuild#12669.

PiperOrigin-RevId: 354326088
Change-Id: Ifaafc563f22d401599540ead70e49db6a86a1995
bazel-io pushed a commit that referenced this pull request Jan 29, 2021
*** Reason for rollback ***

Too many existing config_settings already set visibility. That was never enforced before. But now they'll break if any deps don't honor that visibility. This needs better depot cleanup.

I'll roll forward again behind a feature flag.

*** Original change description ***

Enforce visibility on select() keys

Example:

```
my_rule(
  name = "buildme",
  deps = select({
    "//other/package:some_config": [":mydeps"]
  }))
```

Today, `//other/package:some_config` is exempt from visibility checking, even though it's technically a target dep of
 `buildme`.

While this dep is "special" vs. other deps in various ways, there's no obvious reason why it needs to be special in this way. It adds an unclear corner case...

***

PiperOrigin-RevId: 354584882
bazel-io pushed a commit that referenced this pull request Feb 1, 2021
This was rolled back in 36d228b
 because of depot breakages.

This version adds incompatible flags to safely introduce enforcement.
See #12932 and
#12933 for flag settings.

*** Original change description ***

Roll back #12877.

***

Fixes #12669.

RELNOTES: enforce config_setting visibility. See #12932 for details.
PiperOrigin-RevId: 354930807
copybara-staging bot pushed a commit to google/copybara that referenced this pull request Feb 4, 2021
Included changes:

  - 32fc451600b6e94a015263eb1c8a63e974f6f4cc Write/QueryWriteStatus logging refinement/addition
  - 8fc77874b07a94d8fc4223bf7de20254838420b1 starlark: int: ignore base prefix unless matches explicit...
  - 8346d16648723347ff5234c1576fec277e9ea401 Skip a disk read if possible when considering whether the...
  - f6218bc030af285519e5279b587cf09afa6ea732 Optimize `InMemoryFileSystem#createDirectoryAndParents`.
  - 1b2481d855f6a4ca5a938356024ddede36399b2d When a test produces multiple actions, cache runfiles inp...
  - f5e54ed07021d5826462e64e952ba2a7dc35cde1 Delete Objective-C protobuf generation and linking code.
  - 9804ba5b88e241ac94e25aac6288b307789f0db5 Add --experimental_repository_disable_download to allow u...
  - 5bf5c30d2a35c99b4cdf0891477b88db5b441490 Avoid building validation outputs in Starlark analysis te...
  - 407204e23def40b779e63b77e9c5b580944800b4 Rename collectTransitive to collect
  - 71366b7ab6d78c2cd5cf7ee203af851d3d4f3500 Fix typo
  - ea615b0b23d71be5bdd40c837690f4f02e6e6b3e Reduce the number of ways to create a `SingleRunfilesSupp...
  - 02fddfe1749507dd1a5f42d94843f7b1175215e6 Rephrase Javadoc for `CommandEnvironment::getWorkspaceInf...
  - 33ae065ca3b0f0b99ffd5b7878007b3fe616909e Short-circuit select-list computation if we're just going...
  - 5b32c0620a5c0996a1b21f1628cb6251fc01a4d8 Create new self-transition to set --platforms based on --...
  - 1f6174ca01a076cfe65d22113ad3be57f61bf26b Define the new --android_platforms flag, which will event...
  - e4d5f5ddf744ea27a5f8131215b19822d0798c00 starlark: delete StarlarkFile.parseWithPrelude
  - 76c1f8ad4df7423c3f3d9369b7729c702aa619be Avoid computing possible attribute values when they won't...
  - 58bb42ad7ca263a75c6eeef51482f805726663a5 Revert "Switch to -fdebug-compilation-dir"
  - 28fc8a1f7f7524d1b730da2a41341ce4aa1fea35 Expand make variables in defines of cc_* rules
  - 20ef2eaf6b637e285a2f8d0be54c43b945919baa Update R8 to version 3.0.17-dev
  - a01e94a1e7b4251670547953e93ebf2736304cf7 Allow `DiffAwareness` to share precomputed information ab...
  - 042146f5177dd1c2916b75ebaa6f99bacfca87cb Improve diagnostic for PrepareDepsOfTargetsUnderDirectory...
  - f3c37db370aa4cba3a192d81bf8514a68206aef8 Remove jlpl_strict_deps feature.
  - 7d0899a5f213305a0ac078660c2f42e223a5a3df Fulfill a `TODO` to rename `RunfilesSupplierImpl` to `Sin...
  - 5dfffefef58da0c426cfa0b3d70132dde77950b0 blaze query: always show declared config_setting visibili...
  - 3bde4039b77632db0a0b785219e7c5474e8d4b37 Extend Bazel Java documentation.
  - 64e2a06de992b0097cc4ca8102fa6aeb30c778a3 Add a couple builtins injection tests
  - 015535a83cbdf491c7ce20c0c4774099ccb70ae8 Factor out Starlark predeclared env management into Bazel...
  - 6c63b8f708df72080d840b7ad8df292c00641102 Apply builtins injection to BUILD files
  - fa46d49c3ea237dd91f8bc826121944624197bec Further refactor CachedBzlLoadData management
  - 1e40cf75cd0c3074f50e6fb7a69042929409a147 Simplify Skyframe "inlining" code path in BzlLoadFunction
  - 54a7fcfdd1cc76a5bc3e8c3b75a671e41c87ef13 Refactor some test assertions
  - f9df9d7318f51c1998c76bc50a5d48deacac5963 Automated rollback of commit 18ee6bacdb079432d71bbcbefeb5...
  - 4f331eba49a44a2edb5059ebadf07dadea200148 Add convenience methods for calling Starlark code from na...
  - 96e223ad6f1fdf18c7aa0a175d7764b644605ba3 Enable working with StarlarkRuleContexts from native rules
  - f1cc4dd28d2725caec4c079b4b7d3ead5d76adfe Make RuleContext manage the StarlarkRuleContext
  - 79989f9becc2edefe8b35f7db687bf8de03e3580 Roll forward config_setting visibility enforcement behind...
  - 4fc48680653a71aacbfd555436ba8f9a0742d3d9 Remove support for the Java singlejar implementation.
  - 207283bbbcca9db8870082be51033bb7c8423b6e Use a space instead of a `/` in profile task title for Ge...
  - ba60c0b3f9bbd00975c984244839b155e84b4c5d ijar: fix manifest sections handling
  - 165c1a02625249582158ed77ee3abd428b9e5668 Switch Bazel over to proguard 6.2.2 in the tests
  - bb6af8b93beebcac884b1a03764a7acd49f1479b Fix platforms doc typos
  - d2582637866f28272addd9935a513aaa488c7ec7 Don't call Starlark implicit outputs functions twice
  - 1ab1a3ab344f7f07dd5920d89c1c60b9412b6448 buildEventF.get() may be null
  - dd8afa0fc79a7ff0fc0633eed6d592e0efd3bbfc Log count and size of output files and top-level files se...
  - 24d086446f74606819dc53c3a436caa056ff05b7 PlatformProviderUtils should ignore targets that don't ha...
  - 3e6e97585dd41e31b6ca3bfe3bed10abc3614fe4 Have `canonicalize-flags` command inherit from the build ...
  - 36d228bd792f4332c7486c4e5f9c78e4b55f4b06 Roll back bazelbuild/bazel#12877.
  - 9c5124fea6ba56665b697c9e6bca91180d5a6e7e Change up syntax to see if impossible `ArrayIndexOutOfBou...
  - 9a0bcbb0126f15a716eafcb0b6af61885dd9e2f2 Header compilation works with VanillaJavaBuilder now
  - 06f24b017ae415e74d648d6ce13998771457ccd6 Automated rollback of commit 4a46e9ebb340c17e8500ab9e294e...
  - 9cc17b52abc6e05212843a9c167553b410528982 Fix link to support page.
  - b93422169c6bd97c934701c41f6cbcacd65f15e5 Generalise DeniedImplicitOutputMarkerProvider
  - 2db9b611446b82b6657ac5990181e96df2f3272d Check in the proguard 6.2.2 binaries and sources
  - f8d49faaa886321ea26e6d18c741368c129a37dc Remote: Use parameters instead of thread-local storage to...
  - 37ee252f3744abc4511f55b5089cc52abd3ba09d Remote: Use parameters instead of thread-local storage to...
  - db69c9fb66ab0b9979205585044a3b7f516a7b39 Refactor tests to not assume the target configuration.
  - cef82b35d7a73d2a35ffde4dfcd9c67d950b7d99 AndroidInstrumentationTestTest checks artifacts by name, ...
  - a4cc7a21e924eca95a49810e46971ab1bcffe9f4 Change the MultiArchSplitTransitionProvider to be based o...
  - 3f08df54f9aa671c7721ee1e83180fb807e96b93 Remove redundant tests.
  - e23403312660d729bd356dd057058c307fc0d093 Expose getters in CcLauncherInfo API
  - cac82cf00649217e621e86825e9e99b3e56b0d34 Enforce visibility on select() keys
  - a2b7e40965416d869eff22b7c695f86a37d71044 Expose language in C++ compile API
  - e1c146d2e8997640d79cb972b95d8361c0b4da89 Fix the last prod code that uses BuildConfiguration#getBi...
  - 842122751bbba7832faa42d4a642d7d7b686adfd Add a flag to disable "strict_deps" attribute on java_lit...
  - cc9f2df4be30615ad491f83800f018e90b31d039 Add a new Skydoc test case to test external repositories ...
  - e42a740353744bd76793bfb358fb12371ea5edae Expose additional_outputs in C++ linking API
  - 625f53fca7b427b80ba393ebc7ec9661f44072b0 Move ArtifactFactory initialization to SkyframeExecutor.
  - f4763f9225a44aaaed5a853b0667a20fdffe9991 Use `actions:package_roots` where applicable in BUILD fil...
  - ecddf60fc636844a0ac45c83e51a886687967308 Avoid downloading x86_64 remote JDK on Apple Silicon
  - 4d0b21bbb568014e760daa0ddd74dca31281740d Double CloudBuild pipeline timeout.
  - e96b8ca0c244e1a6a747b98b8f01e2526c9db862 Revert default cpu value on x86 macOS to "darwin"
  - 75bd1ff8ab56d241916bde36291301fa026b2bab Remote: Use parameters instead of thread-local storage to...
  - 92955e617b5c41713a5163dc0437c2a024b31815 Remote: Use parameters instead of thread-local storage to...
  - f0b0c39516a70acc90ca7e74b2a7f7666d5c714f Simplify asDerivedRoot's signature by replacing boolean p...
  - fdde5afab72f1e98438ddc124cb72d6618d9f704 Support proguard 5.3.3 or 6.2.2 in the tests
  - 13aba68083fa0f7cfc21c1d994c4ae50014ab61c Sibling repository layout support for Android NDK builds.
  - e52b60dbac2ab4c43220507bd074e81a4bddb2b7 Change the unchecked `MissingDepException` to a subclass ...
  - ed15b4529219ca785b0d69ee6ef74fda545c723f Update the internal version of bazelbuild/platforms to 0....
  - 9051e80d81088b63bd5f98a87319ab5a98968e67 Clean up more vestiges of async include scanning.
  - dd96fa0083f89f764916d592c899f76717e5c8a5 Automatic code cleanup.
  - 037368017b5cde7bf99187271f3d139b9fca7d14 Remove the RepositoryName parameter from BuildInfoFactory...
  - bff197a1c4c6673a6b4aff14d2f56a0d36657634 Make J2ObjcAspect#getProtoOutputRoot compatible with --ex...
  - 3b3e6424c6fbd51d4c4ebb6aa25f1d1f4720221c Remove fallback strategy support for workers, add flag fo...
  - 50723bb9b606180d6a1bfda09ef1b8a0db467481 Update documentation for `AbortReason.OUT_OF_MEMORY` now ...
  - accad6fe89bd36998f14ae3df906c9d53dc066ba Do not use the unchecked `MissingDepException` to signify...
  - 952184f16c9e79219973e01a115f22dfbd77422f Refactor metrics logging to all flow through MetricsColle...
  - dfb70ea4cae2ffffb76e9741d86c96505a6d05ad Enable toolchain resolution for filegroup targets.
  - 7df3716a12c15e4b55e96f65e24d957d8ef57139 Update @bazel/bazel to bazelisk
  - 8c7e11a81c35563d951062fe6f00e4e85b3009fb Add native support for Apple Silicon
  - d1e9f602e34aa63cd5edab3ff45413810946ef67 Clean up some code in register module map action

BAZEL_VERSION_REV_ID: 32fc451600b6e94a015263eb1c8a63e974f6f4cc
Change-Id: I34c4c1d773fc7f629509b3dbca1a8a790f23b123
gregestren added a commit to gregestren/bazel that referenced this pull request Jul 16, 2021
This was rolled back in bazelbuild@36d228b
 because of depot breakages.

This version adds incompatible flags to safely introduce enforcement.
See bazelbuild#12932 and
bazelbuild#12933 for flag settings.

*** Original change description ***

Roll back bazelbuild#12877.

***

Fixes bazelbuild#12669.

RELNOTES: enforce config_setting visibility. See bazelbuild#12932 for details.
PiperOrigin-RevId: 354930807
katre pushed a commit that referenced this pull request Jul 19, 2021
This was rolled back in 36d228b
 because of depot breakages.

This version adds incompatible flags to safely introduce enforcement.
See #12932 and
#12933 for flag settings.

*** Original change description ***

Roll back #12877.

***

Fixes #12669.

RELNOTES: enforce config_setting visibility. See #12932 for details.
PiperOrigin-RevId: 354930807
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes team-Configurability platforms, toolchains, cquery, select(), config transitions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

config_setting visibility not enforced
3 participants