diff options
author | Kristina Chodorow <kchodorow@google.com> | 2016-04-25 17:45:55 +0000 |
---|---|---|
committer | Yun Peng <pcloudy@google.com> | 2016-04-26 08:29:08 +0000 |
commit | d9121976fa7b39372027c70edddf9eb3c0bba7a6 (patch) | |
tree | 3975f0d7133450a47e4fb4faf033c31c8b23cfa3 /src/main/java/com | |
parent | a2841d3d9f87199a34e09fe6bd58ece9b84f2c58 (diff) |
Create runfiles at both .runfiles/ws/external/repo and .runfiles/repo
The major piece of #848.
RELNOTES[INC]: All repositories are now directly under the x.runfiles directory in the runfiles tree (previously, external repositories were at x.runfiles/main-repo/external/other-repo. This simplifies handling remote repository runfiles considerably, but will break existing references to external repository runfiles.
--
MOS_MIGRATED_REVID=120722312
Diffstat (limited to 'src/main/java/com')
3 files changed, 88 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/Runfiles.java b/src/main/java/com/google/devtools/build/lib/analysis/Runfiles.java index c18bf60997..d1f1434a39 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/Runfiles.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/Runfiles.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; @@ -458,23 +459,99 @@ public final class Runfiles { // Copy manifest map to another manifest map, prepending the workspace name to every path. // E.g. for workspace "myworkspace", the runfile entry "mylib.so"->"/path/to/mylib.so" becomes // "myworkspace/mylib.so"->"/path/to/mylib.so". - Map<PathFragment, Artifact> rootManifest = new HashMap<>(); - for (Map.Entry<PathFragment, Artifact> entry : manifest.entrySet()) { - checker.put(rootManifest, suffix.getRelative(entry.getKey()), entry.getValue()); - } + ManifestBuilder builder = new ManifestBuilder(suffix, legacyExternalRunfiles); + builder.addUnderWorkspace(manifest, checker); // Finally add symlinks relative to the root of the runfiles tree, on top of everything else. // This operation is always checked for conflicts, to match historical behavior. if (conflictPolicy == ConflictPolicy.IGNORE) { checker = new ConflictChecker(ConflictPolicy.WARN, eventHandler, location); } - for (Map.Entry<PathFragment, Artifact> entry : getRootSymlinksAsMap(checker).entrySet()) { - PathFragment mappedPath = entry.getKey(); - Artifact mappedArtifact = entry.getValue(); - checker.put(rootManifest, mappedPath, mappedArtifact); + builder.add(getRootSymlinksAsMap(checker), checker); + return builder.build(); + } + + /** + * Helper class to handle munging the paths of external artifacts. + */ + @VisibleForTesting + static final class ManifestBuilder { + // Manifest of paths to artifacts. Path fragments are relative to the .runfiles directory. + private final Map<PathFragment, Artifact> manifest; + private final PathFragment workspaceName; + private final boolean legacyExternalRunfiles; + // Whether we saw the local workspace name in the runfiles. If legacyExternalRunfiles is true, + // then this is true, as anything under external/ will also have a runfile under the local + // workspace. + private boolean sawWorkspaceName; + + public ManifestBuilder( + PathFragment workspaceName, boolean legacyExternalRunfiles) { + this.manifest = new HashMap<>(); + this.workspaceName = workspaceName; + this.legacyExternalRunfiles = legacyExternalRunfiles; + this.sawWorkspaceName = legacyExternalRunfiles; } - return rootManifest; + /** + * Adds a map under the workspaceName. + */ + public void addUnderWorkspace( + Map<PathFragment, Artifact> inputManifest, ConflictChecker checker) { + for (Map.Entry<PathFragment, Artifact> entry : inputManifest.entrySet()) { + PathFragment path = entry.getKey(); + if (isUnderWorkspace(path)) { + sawWorkspaceName = true; + checker.put(manifest, workspaceName.getRelative(path), entry.getValue()); + } else { + if (legacyExternalRunfiles) { + checker.put(manifest, workspaceName.getRelative(path), entry.getValue()); + } + // Always add the non-legacy .runfiles/repo/whatever path. + checker.put(manifest, getExternalPath(path), entry.getValue()); + } + } + } + + /** + * Adds a map to the root directory. + */ + public void add(Map<PathFragment, Artifact> inputManifest, ConflictChecker checker) { + for (Map.Entry<PathFragment, Artifact> entry : inputManifest.entrySet()) { + checker.put(manifest, checkForWorkspace(entry.getKey()), entry.getValue()); + } + } + + /** + * Returns the manifest, adding the workspaceName directory if it is not already present. + */ + public Map<PathFragment, Artifact> build() { + if (!sawWorkspaceName) { + // If we haven't seen it and we have seen other files, add the workspace name directory. + // It might not be there if all of the runfiles are from other repos (and then running from + // x.runfiles/ws will fail, because ws won't exist). We can't tell Runfiles to create a + // directory, so instead this creates a hidden file inside the desired directory. + manifest.put(workspaceName.getRelative(".runfile"), null); + } + return manifest; + } + + private PathFragment getExternalPath(PathFragment path) { + return checkForWorkspace(path.relativeTo(Label.EXTERNAL_PACKAGE_NAME)); + } + + private PathFragment checkForWorkspace(PathFragment path) { + sawWorkspaceName = sawWorkspaceName || path.getSegment(0).equals(workspaceName); + return path; + } + + private static boolean isUnderWorkspace(PathFragment path) { + return !path.startsWith(Label.EXTERNAL_PACKAGE_NAME); + } + } + + boolean getLegacyExternalRunfiles() { + return legacyExternalRunfiles; } /** diff --git a/src/main/java/com/google/devtools/build/lib/analysis/SourceManifestAction.java b/src/main/java/com/google/devtools/build/lib/analysis/SourceManifestAction.java index 6d726e760d..73e8c40b7f 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/SourceManifestAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/SourceManifestAction.java @@ -192,6 +192,7 @@ public final class SourceManifestAction extends AbstractFileWriteAction { protected String computeKey() { Fingerprint f = new Fingerprint(); f.addString(GUID); + f.addBoolean(runfiles.getLegacyExternalRunfiles()); Map<PathFragment, Artifact> symlinks = runfiles.getSymlinksAsMap(null); f.addInt(symlinks.size()); for (Map.Entry<PathFragment, Artifact> symlink : symlinks.entrySet()) { diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java index b62824708c..3f8c6be31f 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java @@ -710,7 +710,7 @@ public final class BuildConfiguration { @Option(name = "legacy_external_runfiles", defaultValue = "true", - category = "undocumented", + category = "strategy", help = "If true, build runfiles symlink forests for external repositories under " + ".runfiles/wsname/external/repo (in addition to .runfiles/repo).") public boolean legacyExternalRunfiles; |