aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2015-11-06 17:49:58 +0000
committerGravatar Florian Weikert <fwe@google.com>2015-11-06 22:53:20 +0000
commit0c4e3bf1bfb77198a1ac03715fabb253844a4f8d (patch)
tree6be2f10fd3c4dc7895aa15a76d61dfd3c2ef7e1f /src
parentf1ed27d220281a066ecdea0334b079dc72a41e36 (diff)
bazel: support linking accumulated libraries into C++ binaries
This CL permits a cc_binary to have a set of dependencies that are all gathered together when the cc_binary is linked, producing a set of LibraryToLink objects to link into the cc_binary. Each such dependency will an instance of a class that extends BuildLibraryToLink to a CcLinkParams. All instances of the same class will be gathered together. At link time the BuildLibraryToLink method buildLibraries will be called to build the LibraryToLink objects. -- MOS_MIGRATED_REVID=107242331
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkParams.java50
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java102
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java63
4 files changed, 216 insertions, 5 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkParams.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkParams.java
index 1657c1debc..189d7e58e4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkParams.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkParams.java
@@ -34,8 +34,8 @@ import java.util.Objects;
/**
* Parameters to be passed to the linker.
*
- * <p>The parameters concerned are the link options (strings) passed to the linker, linkstamps and a
- * list of libraries to be linked in.
+ * <p>The parameters concerned are the link options (strings) passed to the linker, linkstamps, a
+ * list of libraries to be linked in, and a list of libraries to build at link time.
*
* <p>Items in the collections are stored in nested sets. Link options and libraries are stored in
* link order (preorder) and linkstamps are sorted.
@@ -44,13 +44,16 @@ public final class CcLinkParams {
private final NestedSet<ImmutableList<String>> linkOpts;
private final NestedSet<Linkstamp> linkstamps;
private final NestedSet<LibraryToLink> libraries;
+ private final ExtraLinkTimeLibraries extraLinkTimeLibraries;
private CcLinkParams(NestedSet<ImmutableList<String>> linkOpts,
NestedSet<Linkstamp> linkstamps,
- NestedSet<LibraryToLink> libraries) {
+ NestedSet<LibraryToLink> libraries,
+ ExtraLinkTimeLibraries extraLinkTimeLibraries) {
this.linkOpts = linkOpts;
this.linkstamps = linkstamps;
this.libraries = libraries;
+ this.extraLinkTimeLibraries = extraLinkTimeLibraries;
}
/**
@@ -78,6 +81,13 @@ public final class CcLinkParams {
return libraries;
}
+ /**
+ * The extra link time libraries; will be null if there are no such libraries.
+ */
+ public ExtraLinkTimeLibraries getExtraLinkTimeLibraries() {
+ return extraLinkTimeLibraries;
+ }
+
public static final Builder builder(boolean linkingStatically, boolean linkShared) {
return new Builder(linkingStatically, linkShared);
}
@@ -112,6 +122,13 @@ public final class CcLinkParams {
private final NestedSetBuilder<LibraryToLink> librariesBuilder =
NestedSetBuilder.linkOrder();
+ /**
+ * A builder for the list of link time libraries. Most builds
+ * won't have any such libraries, so save space by leaving the
+ * default as null.
+ */
+ private ExtraLinkTimeLibraries.Builder extraLinkTimeLibrariesBuilder = null;
+
private boolean built = false;
private Builder(boolean linkingStatically, boolean linkShared) {
@@ -130,8 +147,12 @@ public final class CcLinkParams {
if (!localLinkopts.isEmpty()) {
linkOptsBuilder.add(localLinkopts);
}
+ ExtraLinkTimeLibraries extraLinkTimeLibraries = null;
+ if (extraLinkTimeLibrariesBuilder != null) {
+ extraLinkTimeLibraries = extraLinkTimeLibrariesBuilder.build();
+ }
return new CcLinkParams(linkOptsBuilder.build(), linkstampsBuilder.build(),
- librariesBuilder.build());
+ librariesBuilder.build(), extraLinkTimeLibraries);
}
private boolean add(CcLinkParamsStore store) {
@@ -217,6 +238,12 @@ public final class CcLinkParams {
linkOptsBuilder.addTransitive(args.getLinkopts());
linkstampsBuilder.addTransitive(args.getLinkstamps());
librariesBuilder.addTransitive(args.getLibraries());
+ if (args.getExtraLinkTimeLibraries() != null) {
+ if (extraLinkTimeLibrariesBuilder == null) {
+ extraLinkTimeLibrariesBuilder = ExtraLinkTimeLibraries.builder();
+ }
+ extraLinkTimeLibrariesBuilder.addTransitive(args.getExtraLinkTimeLibraries());
+ }
return this;
}
@@ -257,6 +284,18 @@ public final class CcLinkParams {
}
/**
+ * Adds an extra link time library, a library that is actually
+ * built at link time.
+ */
+ public Builder addExtraLinkTimeLibrary(ExtraLinkTimeLibrary e) {
+ if (extraLinkTimeLibrariesBuilder == null) {
+ extraLinkTimeLibrariesBuilder = ExtraLinkTimeLibraries.builder();
+ }
+ extraLinkTimeLibrariesBuilder.add(e);
+ return this;
+ }
+
+ /**
* Processes typical dependencies a C/C++ library.
*
* <p>A helper method that processes getValues() and merges contents of
@@ -332,5 +371,6 @@ public final class CcLinkParams {
public static final CcLinkParams EMPTY = new CcLinkParams(
NestedSetBuilder.<ImmutableList<String>>emptySet(Order.LINK_ORDER),
NestedSetBuilder.<Linkstamp>emptySet(Order.COMPILE_ORDER),
- NestedSetBuilder.<LibraryToLink>emptySet(Order.LINK_ORDER));
+ NestedSetBuilder.<LibraryToLink>emptySet(Order.LINK_ORDER),
+ null);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
index ccfb2e1ad5..49a5a02cee 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
@@ -1159,6 +1159,12 @@ public final class CppLinkAction extends AbstractAction {
public Builder addLinkParams(CcLinkParams linkParams, RuleErrorConsumer errorListener) {
addLinkopts(linkParams.flattenedLinkopts());
addLibraries(linkParams.getLibraries());
+ ExtraLinkTimeLibraries extraLinkTimeLibraries = linkParams.getExtraLinkTimeLibraries();
+ if (extraLinkTimeLibraries != null) {
+ for (ExtraLinkTimeLibrary extraLibrary : extraLinkTimeLibraries.getExtraLibraries()) {
+ addLibraries(extraLibrary.buildLibraries(ruleContext));
+ }
+ }
addLinkstamps(CppHelper.resolveLinkstamps(errorListener, linkParams));
return this;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java
new file mode 100644
index 0000000000..d596ce0156
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibraries.java
@@ -0,0 +1,102 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.rules.cpp;
+
+import com.google.common.collect.Lists;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A list of extra libraries to include in a link. These are non-C++
+ * libraries that are built from inputs gathered from all the dependencies.
+ * The dependencies have no way to coordinate, so each one will add an
+ * ExtraLinkTimeLibrary to its CcLinkParams. ExtraLinkTimeLibrary is an
+ * interface, and all ExtraLinkTimeLibrary objects of the same class will
+ * be gathered together.
+ */
+public final class ExtraLinkTimeLibraries {
+ /**
+ * We can have multiple different kinds of lists of libraries to include
+ * at link time. We map from the class type to an actual instance.
+ */
+ private final Collection<ExtraLinkTimeLibrary> extraLibraries;
+
+ private ExtraLinkTimeLibraries(Collection<ExtraLinkTimeLibrary> extraLibraries) {
+ this.extraLibraries = extraLibraries;
+ }
+
+ /**
+ * Return the set of extra libraries.
+ */
+ public Collection<ExtraLinkTimeLibrary> getExtraLibraries() {
+ return extraLibraries;
+ }
+
+ public static final Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder for {@link ExtraLinkTimeLibraries}.
+ */
+ public static final class Builder {
+ private Map<Class<? extends ExtraLinkTimeLibrary>, ExtraLinkTimeLibrary.Builder> libraries =
+ new LinkedHashMap<>();
+
+ private Builder() {
+ // Nothing to do.
+ }
+
+ /**
+ * Build a {@link ExtraLinkTimeLibraries} object.
+ */
+ public ExtraLinkTimeLibraries build() {
+ List<ExtraLinkTimeLibrary> extraLibraries = Lists.newArrayList();
+ for (ExtraLinkTimeLibrary.Builder builder : libraries.values()) {
+ extraLibraries.add(builder.build());
+ }
+ return new ExtraLinkTimeLibraries(extraLibraries);
+ }
+
+ /**
+ * Add a transitive dependency.
+ */
+ public final Builder addTransitive(ExtraLinkTimeLibraries dep) {
+ for (ExtraLinkTimeLibrary depLibrary : dep.getExtraLibraries()) {
+ Class<? extends ExtraLinkTimeLibrary> c = depLibrary.getClass();
+ if (!libraries.containsKey(c)) {
+ libraries.put(c, depLibrary.getBuilder());
+ }
+ libraries.get(c).addTransitive(depLibrary);
+ }
+ return this;
+ }
+
+ /**
+ * Add a single library to build.
+ */
+ public final Builder add(ExtraLinkTimeLibrary b) {
+ Class<? extends ExtraLinkTimeLibrary> c = b.getClass();
+ if (!libraries.containsKey(c)) {
+ libraries.put(c, b.getBuilder());
+ }
+ libraries.get(c).addTransitive(b);
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java
new file mode 100644
index 0000000000..52b2a0822a
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/ExtraLinkTimeLibrary.java
@@ -0,0 +1,63 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.rules.cpp;
+
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
+
+/**
+ * An extra library to include in a link. The actual library is built
+ * at link time.
+ *
+ * <p>This can be used for non-C++ inputs to a C++ link. A class that
+ * implements this interface will support transitively gathering all
+ * inputs from link dependencies, and then combine them all together
+ * into a set of C++ libraries.
+ *
+ * <p>Any implementations must be immutable (and therefore thread-safe),
+ * because this is passed between rules and accessed in a multi-threaded
+ * context.
+ */
+public interface ExtraLinkTimeLibrary {
+ /**
+ * Build the LibraryToLink inputs to pass to the C++ linker.
+ */
+ NestedSet<LibraryToLink> buildLibraries(RuleContext context);
+
+ /**
+ * Get a new Builder for this ExtraLinkTimeLibrary class. This acts
+ * like a static method, in that the result does not depend on the
+ * current state of the object, and the new Builder starts out
+ * empty.
+ */
+ Builder getBuilder();
+
+ /**
+ * The Builder interface builds an ExtraLinkTimeLibrary.
+ */
+ public interface Builder {
+ /**
+ * Add the inputs associated with another instance of the same
+ * underlying ExtraLinkTimeLibrary type.
+ */
+ void addTransitive(ExtraLinkTimeLibrary dep);
+
+ /**
+ * Build the ExtraLinkTimeLibrary based on the inputs.
+ */
+ ExtraLinkTimeLibrary build();
+ }
+}