Skip to content

Commit

Permalink
Make BuildConfiguration output directories understand repositories
Browse files Browse the repository at this point in the history
This doesn't change the behavior at all, just prep for rolling
forward the execroot change.

--
PiperOrigin-RevId: 141059303
MOS_MIGRATED_REVID=141059303
  • Loading branch information
kchodorow authored and damienmg committed Dec 5, 2016
1 parent a701988 commit 3fd5d39
Showing 1 changed file with 63 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

package com.google.devtools.build.lib.analysis.config;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Verify;
Expand All @@ -25,6 +24,8 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
Expand Down Expand Up @@ -84,7 +85,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.TreeMap;
Expand Down Expand Up @@ -960,62 +960,6 @@ public Map<String, Set<Label>> getDefaultsLabels(BuildConfiguration.Options comm
}
}

/**
* All the output directories pertinent to a configuration.
*/
private static final class OutputRoots implements Serializable {
private final Root outputDirectory; // the configuration-specific output directory.
private final Root binDirectory;
private final Root genfilesDirectory;
private final Root coverageMetadataDirectory; // for coverage-related metadata, artifacts, etc.
private final Root testLogsDirectory;
private final Root includeDirectory;
private final Root middlemanDirectory;

private OutputRoots(BlazeDirectories directories, String outputDirName) {
Path execRoot = directories.getExecRoot();
// configuration-specific output tree
Path outputDir = directories.getOutputPath().getRelative(outputDirName);
this.outputDirectory = Root.asDerivedRoot(execRoot, outputDir, true);

// specific subdirs under outputDirectory
this.binDirectory = Root
.asDerivedRoot(execRoot, outputDir.getRelative("bin"), true);
this.genfilesDirectory = Root.asDerivedRoot(
execRoot, outputDir.getRelative("genfiles"), true);
this.coverageMetadataDirectory = Root.asDerivedRoot(execRoot,
outputDir.getRelative("coverage-metadata"), true);
this.testLogsDirectory = Root.asDerivedRoot(
execRoot, outputDir.getRelative("testlogs"), true);
this.includeDirectory = Root.asDerivedRoot(
execRoot, outputDir.getRelative(BlazeDirectories.RELATIVE_INCLUDE_DIR), true);
this.middlemanDirectory = Root.middlemanRoot(execRoot, outputDir, true);
}

@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof OutputRoots)) {
return false;
}
OutputRoots other = (OutputRoots) o;
return outputDirectory.equals(other.outputDirectory)
&& binDirectory.equals(other.binDirectory)
&& genfilesDirectory.equals(other.genfilesDirectory)
&& coverageMetadataDirectory.equals(other.coverageMetadataDirectory)
&& testLogsDirectory.equals(other.testLogsDirectory)
&& includeDirectory.equals(other.includeDirectory);
}

@Override
public int hashCode() {
return Objects.hash(outputDirectory, binDirectory, genfilesDirectory,
coverageMetadataDirectory, testLogsDirectory, includeDirectory);
}
}

private final String checksum;

private Transitions transitions;
Expand Down Expand Up @@ -1064,7 +1008,54 @@ public int hashCode() {
* this so that the build works even if the two configurations are too close (which is common)
* and so that the path of artifacts in the host configuration is a bit more readable.
*/
private final OutputRoots outputRoots;
private enum OutputDirectory {
BIN("bin"),
GENFILES("genfiles"),
MIDDLEMAN(true),
TESTLOGS("testlogs"),
COVERAGE("coverage-metadata"),
INCLUDE(BlazeDirectories.RELATIVE_INCLUDE_DIR),
OUTPUT(false);

private final String name;
private final boolean middleman;

/**
* This constructor is for roots without suffixes, e.g.,
* [[execroot/repo]/bazel-out/local-fastbuild].
* @param isMiddleman whether the root should be a middleman root or a "normal" derived root.
*/
OutputDirectory(boolean isMiddleman) {
this.name = "";
this.middleman = isMiddleman;
}

OutputDirectory(String name) {
this.name = name;
this.middleman = false;
}

Root getRoot(
RepositoryName repositoryName, String outputDirName, BlazeDirectories directories) {
// e.g., execroot/repo1
Path execRoot = directories.getExecRoot();
// e.g., execroot/repo1/bazel-out/config/bin
Path outputDir = execRoot.getRelative(directories.getRelativeOutputPath())
.getRelative(outputDirName);
if (middleman) {
return INTERNER.intern(Root.middlemanRoot(execRoot, outputDir, repositoryName.isMain()));
}
// e.g., [[execroot/repo1]/bazel-out/config/bin]
return INTERNER.intern(
Root.asDerivedRoot(execRoot, outputDir.getRelative(name), repositoryName.isMain()));
}
}

// "Cache" of roots, so we don't keep around thousands of copies of the same root.
private static Interner<Root> INTERNER = Interners.newWeakInterner();

private final BlazeDirectories directories;
private final String outputDirName;

/** If false, AnalysisEnviroment doesn't register any actions created by the ConfiguredTarget. */
private final boolean actionsEnabled;
Expand Down Expand Up @@ -1246,19 +1237,7 @@ public BuildConfiguration(BlazeDirectories directories,
Map<Class<? extends Fragment>, Fragment> fragmentsMap,
BuildOptions buildOptions,
boolean actionsDisabled) {
this(null, directories, fragmentsMap, buildOptions, actionsDisabled);
}

/**
* Constructor variation that uses the passed in output roots if non-null, else computes them
* from the directories.
*/
public BuildConfiguration(@Nullable OutputRoots outputRoots,
@Nullable BlazeDirectories directories,
Map<Class<? extends Fragment>, Fragment> fragmentsMap,
BuildOptions buildOptions,
boolean actionsDisabled) {
Preconditions.checkState(outputRoots == null ^ directories == null);
this.directories = directories;
this.actionsEnabled = !actionsDisabled;
this.fragments = ImmutableSortedMap.copyOf(fragmentsMap, lexicalFragmentSorter);

Expand Down Expand Up @@ -1286,16 +1265,12 @@ public BuildConfiguration(@Nullable OutputRoots outputRoots,
commandLineBuildVariables = ImmutableMap.copyOf(commandLineDefinesBuilder);

this.mnemonic = buildMnemonic();
String outputDirName = (options.outputDirectoryName != null)
this.outputDirName = (options.outputDirectoryName != null)
? options.outputDirectoryName : mnemonic;
this.platformName = buildPlatformName();

this.shellExecutable = computeShellExecutable();

this.outputRoots = outputRoots != null
? outputRoots
: new OutputRoots(directories, outputDirName);

Pair<ImmutableMap<String, String>, ImmutableSet<String>> shellEnvironment =
setupShellEnvironment();
this.localShellEnvironment = shellEnvironment.getFirst();
Expand Down Expand Up @@ -1339,7 +1314,7 @@ public BuildConfiguration clone(
BuildOptions options = buildOptions.trim(
getOptionsClasses(fragmentsMap.keySet(), ruleClassProvider));
BuildConfiguration newConfig =
new BuildConfiguration(outputRoots, null, fragmentsMap, options, !actionsEnabled);
new BuildConfiguration(directories, fragmentsMap, options, !actionsEnabled);
newConfig.setConfigurationTransitions(this.transitions);
return newConfig;
}
Expand Down Expand Up @@ -1860,23 +1835,6 @@ public void evaluateTransition(final Rule fromRule, final Attribute attribute,
transitionApplier.applyConfigurationHook(fromRule, attribute, toTarget);
}

/**
* For an given environment, returns a subset containing all
* variables in the given list if they are defined in the given
* environment.
*/
@VisibleForTesting
static Map<String, String> getMapping(List<String> variables,
Map<String, String> environment) {
Map<String, String> result = new HashMap<>();
for (String var : variables) {
if (environment.containsKey(var)) {
result.put(var, environment.get(var));
}
}
return result;
}

/**
* Returns the {@link Option} class the defines the given option, null if the
* option isn't recognized.
Expand Down Expand Up @@ -1926,7 +1884,7 @@ public String getPlatformName() {
* Returns the output directory for this build configuration.
*/
public Root getOutputDirectory(RepositoryName repositoryName) {
return outputRoots.outputDirectory;
return OutputDirectory.OUTPUT.getRoot(repositoryName, outputDirName, directories);
}

/**
Expand All @@ -1935,19 +1893,17 @@ public Root getOutputDirectory(RepositoryName repositoryName) {
@SkylarkCallable(name = "bin_dir", structField = true, documented = false)
@Deprecated
public Root getBinDirectory() {
return outputRoots.binDirectory;
return getBinDirectory(RepositoryName.MAIN);
}

/**
* TODO(kchodorow): This (and the other get*Directory functions) won't work with external
* repositories without changes to how ArtifactFactory resolves derived roots. This is not an
* issue right now because it only effects Blaze's include scanning (internal) and Bazel's
* repositories (external) but will need to be fixed.
* TODO(kchodorow): Use the repository name to derive the bin directory.
*/
@SuppressWarnings("unused")
public Root getBinDirectory(RepositoryName repositoryName) {
return getBinDirectory();
return OutputDirectory.BIN.getRoot(repositoryName, outputDirName, directories);
}

/**
Expand All @@ -1959,11 +1915,9 @@ public PathFragment getBinFragment() {

/**
* Returns the include directory for this build configuration.
* TODO(kchodorow): Use the repository name to derive the include directory.
*/
@SuppressWarnings("unused")
public Root getIncludeDirectory(RepositoryName repositoryName) {
return outputRoots.includeDirectory;
return OutputDirectory.INCLUDE.getRoot(repositoryName, outputDirName, directories);
}

/**
Expand All @@ -1972,33 +1926,27 @@ public Root getIncludeDirectory(RepositoryName repositoryName) {
@SkylarkCallable(name = "genfiles_dir", structField = true, documented = false)
@Deprecated
public Root getGenfilesDirectory() {
return outputRoots.genfilesDirectory;
return getGenfilesDirectory(RepositoryName.MAIN);
}

// TODO(kchodorow): Use the repository name to derive the genfiles directory.
@SuppressWarnings("unused")
public Root getGenfilesDirectory(RepositoryName repositoryName) {
return getGenfilesDirectory();
return OutputDirectory.GENFILES.getRoot(repositoryName, outputDirName, directories);
}

/**
* Returns the directory where coverage-related artifacts and metadata files
* should be stored. This includes for example uninstrumented class files
* needed for Jacoco's coverage reporting tools.
* TODO(kchodorow): Use the repository name to derive the coverage directory.
*/
@SuppressWarnings("unused")
public Root getCoverageMetadataDirectory(RepositoryName repositoryName) {
return outputRoots.coverageMetadataDirectory;
return OutputDirectory.COVERAGE.getRoot(repositoryName, outputDirName, directories);
}

/**
* Returns the testlogs directory for this build configuration.
* TODO(kchodorow): Use the repository name to derive the test directory.
*/
@SuppressWarnings("unused")
public Root getTestLogsDirectory(RepositoryName repositoryName) {
return outputRoots.testLogsDirectory;
return OutputDirectory.TESTLOGS.getRoot(repositoryName, outputDirName, directories);
}

/**
Expand All @@ -2023,11 +1971,9 @@ public String getHostPathSeparator() {

/**
* Returns the internal directory (used for middlemen) for this build configuration.
* TODO(kchodorow): Use the repository name to derive the middleman directory.
*/
@SuppressWarnings("unused")
public Root getMiddlemanDirectory(RepositoryName repositoryName) {
return outputRoots.middlemanDirectory;
return OutputDirectory.MIDDLEMAN.getRoot(repositoryName, outputDirName, directories);
}

public boolean getAllowRuntimeDepsOnNeverLink() {
Expand All @@ -2041,11 +1987,7 @@ public boolean isStrictFilesets() {
public List<Label> getPlugins() {
return options.pluginList;
}

public List<Map.Entry<String, String>> getPluginCopts() {
return options.pluginCoptList;
}


/**
* Returns the configuration-dependent string for this configuration. This is also the name of the
* configuration's base output directory unless {@link Options#outputDirectoryName} overrides it.
Expand Down

0 comments on commit 3fd5d39

Please sign in to comment.