Write a repo mapping manifest in the runfiles directory#16321
Write a repo mapping manifest in the runfiles directory#16321
Conversation
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
src/test/java/com/google/devtools/build/lib/analysis/RunfilesRepoMappingManifestTest.java
Outdated
Show resolved
Hide resolved
src/test/java/com/google/devtools/build/lib/analysis/RunfilesRepoMappingManifestTest.java
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
src/test/java/com/google/devtools/build/lib/analysis/RunfilesRepoMappingManifestTest.java
Outdated
Show resolved
Hide resolved
| * more). | ||
| */ | ||
| @Before | ||
| public void setupSimpleBinaryRule() throws Exception { |
There was a problem hiding this comment.
mind adding test cases for:
- dependencies caused by aspects
- host/exec dependencies
- dependencies caused by an late-bound attribute
Based on how the machinery that collects the set of transitive packages works, it looks like all these should work, but it's better to test it.
There was a problem hiding this comment.
I'll get to this next. re "host/exec dependencies" though -- why would we want those in runfiles at all?
There was a problem hiding this comment.
Files from host/exec dependencies should never be in the runfiles tree, but to the best of my knowledge, this is not enforced anywhere, which means that it's pretty certain that someone does it anyway.
Therefore, packages of host/exec dependencies must also be in the runfiles repo mapping (unless you convince me that the above property is enforced, but I'd be very surprised)
There was a problem hiding this comment.
ah I see. I just added a new filtering so that only repos contributing runfiles would appear in the runfiles manifest (#16321 (comment)), so I think we should have this case covered (unless someone is actively including stuff from host/exec deps into their runfiles, in which case they can simply... not).
| runfilesInputManifest = null; | ||
| runfilesManifest = null; | ||
| } | ||
| Artifact repoMappingManifest = createRepoMappingManifestAction(ruleContext, owningExecutable); |
There was a problem hiding this comment.
Do I understand correctly that the same correctness guarantees will apply to the repo manifest as for the runfiles output manifest (and the runfiles tree), which is "nothing"? (I'm not saying this is a bad thing, I don't think you should be solving the correctness problems of runfiles here, just trying to validate my mental model against reality)
There was a problem hiding this comment.
I don't quite understand what you mean by "correctness guarantees"; any examples?
There was a problem hiding this comment.
Erm, sorry for being terse. My understanding is that Bazel doesn't guarantee that if one does
bazel build //a:b
rm bazel-bin/a/b.runfiles/<some file>
bazel build //a:b
the runfiles tree is rebuilt except if <some file> is MANIFEST. Do I understand correctly that this would be the same with the repo mapping manifest, i.e. deleting it or changing it would not cause the symlink tree creation action to be re-run?
There was a problem hiding this comment.
I don't really know runfiles well enough to answer this question, but my guess is that yeah, the repo mapping manifest is just like the output manifest.
|
|
||
| boolean runfilesEnabled = ruleContext.getConfiguration().runfilesEnabled(); | ||
|
|
||
| return new RunfilesSupport( |
There was a problem hiding this comment.
How will repo mapping files work with sandboxes? I suppose they should appear there, but how would that work?
There was a problem hiding this comment.
I really don't know how to answer this question :( Does the existing runfiles manifest file work with sandboxes? If so, it doesn't look like the repo mapping manifest file should be any different.
There was a problem hiding this comment.
Both sandboxed and remote execution go through https://cs.opensource.google/bazel/bazel/+/59e51fe625f485dc664928ae0ad93035808779f3:src/main/java/com/google/devtools/build/lib/analysis/Runfiles.java;l=392;drc=901c75e459d737220cb8e29649c1b6ba24e2221d;bpv=1;bpt=1, so I think that this PR should just work with them. But of course a test will tell ;-)
There was a problem hiding this comment.
Yep, a test case would dispel all my fears :)
The reason why I'm asking is that because I don't know off the top of my head how the runfiles manifest is plumbed to sandboxes and remote execution workers and since they are very special, I can't say with any confidence that the repo mapping file will be there. Ideally, by the time this changes is merged, we both would understand how runfiles output manifests appear in sandboxes / on RBE and be convinced that the repo mapping file does, too (and there would be a test also, of course!)
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Show resolved
Hide resolved
0bcf791 to
95c4cc8
Compare
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
95c4cc8 to
1e1bc3e
Compare
| runfilesManifest = null; | ||
| } | ||
| Artifact repoMappingManifest = | ||
| createRepoMappingManifestAction(ruleContext, runfiles, owningExecutable); |
There was a problem hiding this comment.
Just noticed that we aren't adding the repo mapping manifest to the runfiles manifest, which makes it more difficult to find it at runtime on Windows. If we move this call further up, we could pass the Artifact into SourceManifestAction.
1e1bc3e to
3d2f4d6
Compare
3d2f4d6 to
d6de34e
Compare
|
So that took a while.
With luck, all the tests (both internal and external) should pass now. |
d6de34e to
05fb4f7
Compare
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RepoMappingManifestAction.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
| private static ImmutableList<Entry> collectRepoMappings( | ||
| NestedSet<Package> transitivePackages, Runfiles runfiles) { | ||
| ImmutableSet<RepositoryName> reposContributingRunfiles = | ||
| runfiles.getAllArtifacts().toList().stream() |
There was a problem hiding this comment.
This being a path not taken in Blaze and not taken in Bazel by default makes me a bit worried it may regress analysis phase performance outside Google. Were you able to get benchmark data on that or have other reasons to believe it's safe?
There was a problem hiding this comment.
I didn't get benchmark data. This change was made out of necessity rather than convenience, since things break internally if a Package is used as to compute an action key in any way.
Also, this is actually still run in Blaze, so its effects will be visible. It's just not run in certain other modes of builds in Google (where the transitive package tracking doesn't happen).
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
Outdated
Show resolved
Hide resolved
|
|
||
| # Finally we get to build stuff! | ||
| self.RunBazel(['build', '//:me', '@bar//:bar'], allow_failure=False) | ||
| with open(self.Path('bazel-bin/me.repo_mapping'), 'r') as f: |
There was a problem hiding this comment.
Could you build this check into a binary executed as part of an action? That would give use confidence that the file exists in the sandbox, not just in the output tree.
That said, we may want a test that covers remote execution.
There was a problem hiding this comment.
I made the bare_binary fail if it can't find the repo mapping manifest file, and changed bazel build to bazel run. The content assertion is still outside.
With the current way the repo mapping manifest file is generated, I don't think remote execution is a concern anymore -- it's just another normal artifact, and has no entanglement with the special handling around the symlink tree.
There was a problem hiding this comment.
and of course the shell script doesn't work on windows... give me a second to fix that
There was a problem hiding this comment.
Agreed on the remote execution part. By making the binary a test and running bazel test, you would get coverage for the sandbox case without more code.
To ensure we can use repo mappings in the runfiles library, this change writes an extra file "my_binary_target.repo_mapping", which contains a bunch of (base_repo_canonical_name, apparent_repo_name, canonical_repo_name) triples. See https://github.com/bazelbuild/proposals/blob/main/designs/2022-07-21-locating-runfiles-with-bzlmod.md for more information. The extra file is written using a new action "RepoMappingManifestAction", and it's only executed if we know for sure that Bzlmod is enabled. This avoid generating a lot of extra actions that are essentially useless for monorepo setups such as Google's. Work towards #16124 PiperOrigin-RevId: 475820334 Change-Id: I885b4df093bd2c783c57d19f995f420b9b29b53c
05fb4f7 to
8f2f6ea
Compare
|
Merged as 527308c |
To ensure we can use repo mappings in the runfiles library, this change writes an extra file "my_binary_target.runfiles/_repo_mapping", which contains a bunch of (base_repo_canonical_name, apparent_repo_name, canonical_repo_name) triples. See https://github.com/bazelbuild/proposals/blob/main/designs/2022-07-21-locating-runfiles-with-bzlmod.md for more information.
Work towards #16124