aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Michael Staib <mstaib@google.com>2016-07-22 20:34:18 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-07-25 11:40:01 +0000
commit33ac07ccfe4825aa078643c40b2bd230b380de48 (patch)
tree1fbb65c5b560ce1503fe30ac88d822e081a89cf1 /src/main
parent6054ff324f42dddc8e8e4b85076e7304a2958ab9 (diff)
Be less naive with CcLibraryHelper precompiled library collision detection.
The naive algorithm was O(n*m) where n = number of precompiled libraries and m = number of libraries linked during this rule. Ugly! This one provides hopefully much more reasonable performance. -- MOS_MIGRATED_REVID=128206057
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java54
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingOutputs.java29
-rw-r--r--src/main/java/com/google/devtools/build/lib/util/FileType.java9
3 files changed, 54 insertions, 38 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
index c43404e3b9..401fefd881 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java
@@ -19,7 +19,9 @@ import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.FileProvider;
@@ -43,6 +45,7 @@ import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingM
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
import com.google.devtools.build.lib.syntax.Type;
+import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.Preconditions;
@@ -920,33 +923,30 @@ public final class CcLibraryHelper {
// Add the linked outputs of this rule iff we had anything to put in them, but then
// make sure we're not colliding with some library added from the inputs.
newOutputsBuilder.merge(originalLinkingOutputs);
- Iterable<LibraryToLink> allLibraries =
- Iterables.concat(staticLibraries, picStaticLibraries, dynamicLibraries);
- for (LibraryToLink precompiledLibrary : allLibraries) {
- List<LibraryToLink> matchingLibs =
- originalLinkingOutputs.getLibrariesWithSameIdentifierAs(precompiledLibrary);
- if (!matchingLibs.isEmpty()) {
- Iterable<String> matchingLibArtifactNames =
- Iterables.transform(
- matchingLibs,
- new Function<LibraryToLink, String>() {
- @Override
- public String apply(LibraryToLink input) {
- return input.getOriginalLibraryArtifact().getFilename();
- }
- });
- ruleContext.ruleError(
- "Can't put "
- + precompiledLibrary.getArtifact().getFilename()
- + " into the srcs of a "
- + ruleContext.getRuleClassNameForLogging()
- + " with the same name ("
- + ruleContext.getRule().getName()
- + ") which also contains other code or objects to link; it shares a name with "
- + Joiner.on(", ").join(matchingLibArtifactNames)
- + " (output compiled and linked from the non-library sources of this rule), "
- + "which could cause confusion");
- }
+ ImmutableSetMultimap<String, LibraryToLink> precompiledLibraryMap =
+ CcLinkingOutputs.getLibrariesByIdentifier(
+ Iterables.concat(staticLibraries, picStaticLibraries, dynamicLibraries));
+ ImmutableSetMultimap<String, LibraryToLink> linkedLibraryMap =
+ originalLinkingOutputs.getLibrariesByIdentifier();
+ for (String matchingIdentifier :
+ Sets.intersection(precompiledLibraryMap.keySet(), linkedLibraryMap.keySet())) {
+ Iterable<Artifact> matchingInputLibs =
+ LinkerInputs.toNonSolibArtifacts(precompiledLibraryMap.get(matchingIdentifier));
+ Iterable<Artifact> matchingOutputLibs =
+ LinkerInputs.toNonSolibArtifacts(linkedLibraryMap.get(matchingIdentifier));
+ ruleContext.ruleError(
+ "Can't put "
+ + Joiner.on(", ")
+ .join(Iterables.transform(matchingInputLibs, FileType.TO_FILENAME))
+ + " into the srcs of a "
+ + ruleContext.getRuleClassNameForLogging()
+ + " with the same name ("
+ + ruleContext.getRule().getName()
+ + ") which also contains other code or objects to link; it shares a name with "
+ + Joiner.on(", ")
+ .join(Iterables.transform(matchingOutputLibs, FileType.TO_FILENAME))
+ + " (output compiled and linked from the non-library sources of this rule), "
+ + "which could cause confusion");
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingOutputs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingOutputs.java
index aab459989c..a763a924bb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingOutputs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingOutputs.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.rules.cpp;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.rules.cpp.Link.LinkStaticness;
@@ -69,19 +70,25 @@ public class CcLinkingOutputs {
}
/**
- * Returns all libraries in this CcLinkingOutputs with the same library identifier - i.e., those
- * which would be considered different forms of the same library by getPreferredLibrary.
+ * Returns a map from library identifiers to sets of LibraryToLink from this CcLinkingOutputs
+ * which share that library identifier.
*/
- public List<LibraryToLink> getLibrariesWithSameIdentifierAs(LibraryToLink input) {
- Iterable<LibraryToLink> allLibraries =
+ public ImmutableSetMultimap<String, LibraryToLink> getLibrariesByIdentifier() {
+ return getLibrariesByIdentifier(
Iterables.concat(
- staticLibraries, picStaticLibraries, dynamicLibraries, executionDynamicLibraries);
- ImmutableList.Builder<LibraryToLink> result = new ImmutableList.Builder<>();
- for (LibraryToLink library : allLibraries) {
- if (libraryIdentifierOf(library.getOriginalLibraryArtifact())
- .equals(libraryIdentifierOf(input.getOriginalLibraryArtifact()))) {
- result.add(library);
- }
+ staticLibraries, picStaticLibraries, dynamicLibraries, executionDynamicLibraries));
+ }
+
+ /**
+ * Gathers up a map from library identifiers to sets of LibraryToLink which share that library
+ * identifier.
+ */
+ public static ImmutableSetMultimap<String, LibraryToLink> getLibrariesByIdentifier(
+ Iterable<LibraryToLink> inputs) {
+ ImmutableSetMultimap.Builder<String, LibraryToLink> result =
+ new ImmutableSetMultimap.Builder<>();
+ for (LibraryToLink library : inputs) {
+ result.put(libraryIdentifierOf(library.getOriginalLibraryArtifact()), library);
}
return result.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/util/FileType.java b/src/main/java/com/google/devtools/build/lib/util/FileType.java
index b8b4fdc119..b984e98d70 100644
--- a/src/main/java/com/google/devtools/build/lib/util/FileType.java
+++ b/src/main/java/com/google/devtools/build/lib/util/FileType.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.util;
+import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
@@ -129,6 +130,14 @@ public abstract class FileType implements Predicate<String> {
String getFilename();
}
+ public static final Function<HasFilename, String> TO_FILENAME =
+ new Function<HasFilename, String>() {
+ @Override
+ public String apply(HasFilename input) {
+ return input.getFilename();
+ }
+ };
+
/**
* Checks whether an Iterable<? extends HasFileType> contains any of the specified file types.
*