Skip to content

Commit

Permalink
Separate runfiles middlemen into two layers: one that is a middleman …
Browse files Browse the repository at this point in the history
…for the files itself, and one that contains this middleman and the runfiles output manifest.

This is in preparation for Windows symlink support in runfiles manifests: on Windows, we'll need the target files created before we can create the runfiles symlinks for them, but we can't do that by adding the current runfiles middleman to the inputs of SymlinkTreeAction because it would create a cycle (output manifest -> SymlinkTreeAction -> runfiles manifest -> MiddlemanAction -> output manifest)

The alternative is to just add the artifacts to the inputs of SymlinkTreeAction, but that would create a bunch of extra edges and, more importantly, reverse edges in the action graph which we don't want.

--
MOS_MIGRATED_REVID=113041344
  • Loading branch information
lberki committed Jan 26, 2016
1 parent b88ef8f commit e4974e4
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -633,9 +633,7 @@ private static <E> void expandMiddlemanArtifact(Artifact middleman,
Preconditions.checkArgument(middleman.isMiddlemanArtifact());
List<Artifact> artifacts = new ArrayList<>();
middlemanExpander.expand(middleman, artifacts);
for (Artifact artifact : artifacts) {
output.add(outputFormatter.apply(artifact));
}
addExpandedArtifacts(artifacts, output, outputFormatter, middlemanExpander);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ public Artifact createAggregatingMiddleman(
* @param middlemanDir the directory in which to place the middleman.
*/
public Artifact createRunfilesMiddleman(
ActionOwner owner, Artifact owningArtifact, Iterable<Artifact> inputs, Root middlemanDir) {
ActionOwner owner, Artifact owningArtifact, Iterable<Artifact> inputs, Root middlemanDir,
String tag) {
if (hasExactlyOneInput(inputs)) { // Optimization: No middleman for just one input.
return Iterables.getOnlyElement(inputs);
}
String middlemanPath = owningArtifact == null
? Label.print(owner.getLabel())
: owningArtifact.getRootRelativePath().getPathString();
return createMiddleman(owner, middlemanPath, "runfiles", inputs, middlemanDir,
return createMiddleman(owner, middlemanPath, tag, inputs, middlemanDir,
MiddlemanType.RUNFILES_MIDDLEMAN).getFirst();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.RunUnder;
import com.google.devtools.build.lib.collect.IterablesChain;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
Expand Down Expand Up @@ -112,9 +111,11 @@ private RunfilesSupport(RuleContext ruleContext, Artifact executable, Runfiles r
throw new IllegalStateException("main program " + executable + " not included in runfiles");
}

Artifact artifactsMiddleman = createArtifactsMiddleman(ruleContext, runfiles.getAllArtifacts());
runfilesInputManifest = createRunfilesInputManifestArtifact(ruleContext);
this.runfilesManifest = createRunfilesAction(ruleContext, runfiles);
this.runfilesMiddleman = createRunfilesMiddleman(ruleContext, runfiles.getAllArtifacts());
this.runfilesMiddleman = createRunfilesMiddleman(
ruleContext, artifactsMiddleman, runfilesManifest);
sourcesManifest = createSourceManifest(ruleContext, runfiles);

args = ImmutableList.<String>builder()
Expand Down Expand Up @@ -247,15 +248,19 @@ public Artifact getSourceManifest() {
return sourcesManifest;
}

private Artifact createRunfilesMiddleman(ActionConstructionContext context,
private Artifact createArtifactsMiddleman(ActionConstructionContext context,
Iterable<Artifact> allRunfilesArtifacts) {
Iterable<Artifact> inputs = IterablesChain.<Artifact>builder()
.add(allRunfilesArtifacts)
.addElement(runfilesManifest)
.build();
return context.getAnalysisEnvironment().getMiddlemanFactory().createRunfilesMiddleman(
context.getActionOwner(), owningExecutable, inputs,
context.getConfiguration().getMiddlemanDirectory());
context.getActionOwner(), owningExecutable, allRunfilesArtifacts,
context.getConfiguration().getMiddlemanDirectory(), "runfiles_artifacts");
}

private Artifact createRunfilesMiddleman(ActionConstructionContext context,
Artifact artifactsMiddleman, Artifact outputManifest) {
return context.getAnalysisEnvironment().getMiddlemanFactory().createRunfilesMiddleman(
context.getActionOwner(), owningExecutable,
ImmutableList.of(artifactsMiddleman, outputManifest),
context.getConfiguration().getMiddlemanDirectory(), "runfiles");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,11 @@ public void testDifferentExecutablesForRunfilesMiddleman() throws Exception {

analysisEnvironment.clear();
Artifact middlemanForC = middlemanFactory.createRunfilesMiddleman(
NULL_ACTION_OWNER, c, Arrays.asList(c, common), targetConfig.getMiddlemanDirectory());
NULL_ACTION_OWNER, c, Arrays.asList(c, common), targetConfig.getMiddlemanDirectory(),
"runfiles");
Artifact middlemanForD = middlemanFactory.createRunfilesMiddleman(
NULL_ACTION_OWNER, d, Arrays.asList(d, common), targetConfig.getMiddlemanDirectory());
NULL_ACTION_OWNER, d, Arrays.asList(d, common), targetConfig.getMiddlemanDirectory(),
"runfiles");
analysisEnvironment.registerWith(getMutableActionGraph());

MiddlemanAction middlemanActionForC = (MiddlemanAction) getGeneratingAction(middlemanForC);
Expand Down

0 comments on commit e4974e4

Please sign in to comment.