From a0512fea5e86352f7c18613ef656851654dbe764 Mon Sep 17 00:00:00 2001 From: Greg Estren Date: Wed, 11 Nov 2015 18:14:53 +0000 Subject: Provide a looser concept of BuildConfiguration "equality" to account for dynamic configurations. In short, as a configuration gets passed down its dependency tree it's likely to lose fragments. For example, when a java_library depends on a cc_library, the former has both JavaConfiguration and CppConfiguration while the latter only has CppConfiguration. It's still the "same" configuration in both cases, it's just that it got trimmed. This cl provides a looser concept of BuildConfiguration equality that accounts for this. -- MOS_MIGRATED_REVID=107598262 --- .../lib/analysis/config/BuildConfiguration.java | 40 ++++++++++++++++++++++ .../build/lib/analysis/config/BuildOptions.java | 3 +- .../build/lib/rules/java/JavaLibraryHelper.java | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) (limited to 'src/main/java/com') 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 49f71b605b..1ec1858d77 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 @@ -87,6 +87,7 @@ import java.util.LinkedHashSet; 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; @@ -946,6 +947,29 @@ public final class BuildConfiguration { outputDir.getRelative(BlazeDirectories.RELATIVE_INCLUDE_DIR)); this.middlemanDirectory = Root.middlemanRoot(execRoot, outputDir); } + + @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; @@ -1060,6 +1084,22 @@ public final class BuildConfiguration { */ private final Map transitiveOptionsMap; + /** + * Returns true if this configuration is semantically equal to the other, with + * the possible exception that the other has fewer fragments. + * + *

This is useful for dynamic configurations - as the same configuration gets "trimmed" while + * going down a dependency chain, it's still the same configuration but loses some of its + * fragments. So we need a more nuanced concept of "equality" than simple reference equality. + */ + public boolean equalsOrIsSupersetOf(BuildConfiguration other) { + return this.equals(other) + || (outputRoots.equals(other.outputRoots) + && actionsEnabled == other.actionsEnabled + && fragments.values().containsAll(other.fragments.values()) + && buildOptions.getOptions().containsAll(other.buildOptions.getOptions())); + } + /** * Returns map of all the fragments for this configuration. */ diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java index f94b3eab46..c79d8b1612 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java @@ -32,6 +32,7 @@ import com.google.devtools.common.options.OptionsParsingException; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -219,7 +220,7 @@ public final class BuildOptions implements Cloneable, Serializable { /** * Returns the options contained in this collection. */ - public Iterable getOptions() { + public Collection getOptions() { return fragmentOptionsMap.values(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java index 9f6a639745..275a2d722d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java @@ -189,7 +189,7 @@ public final class JavaLibraryHelper { public JavaLibraryHelper addDeps(Iterable deps) { for (TransitiveInfoCollection dep : deps) { Preconditions.checkArgument(dep.getConfiguration() == null - || dep.getConfiguration().equals(configuration)); + || configuration.equalsOrIsSupersetOf(dep.getConfiguration())); this.deps.add(dep); } return this; -- cgit v1.2.3