aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java
diff options
context:
space:
mode:
authorGravatar Cal Peyser <cpeyser@google.com>2016-02-11 15:45:46 +0000
committerGravatar David Chen <dzc@google.com>2016-02-11 22:22:14 +0000
commit60434dae746ed61f025fdfd0464993fa6a0ff1d2 (patch)
treea17a05ad70edffad7bc3c7f0ee508fb66e8576c2 /src/main/java
parent63396eadb4614211a1ffb4c65bb676ee8511c61b (diff)
--
MOS_MIGRATED_REVID=114436999
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java86
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java38
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/LibrariesToLink.java111
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java52
5 files changed, 267 insertions, 34 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
index 7f129f9e5c..eb7c1bf0ca 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java
@@ -16,7 +16,6 @@ package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE;
-import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DIR;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_CPP;
@@ -702,6 +701,43 @@ public final class CompilationSupport {
*/
CompilationSupport registerLinkActions(ObjcProvider objcProvider, ExtraLinkArgs extraLinkArgs,
Iterable<Artifact> extraLinkInputs) {
+ LibrariesToLink defaultLibrariesToLink = LibrariesToLink.defaultLibraries(objcProvider);
+ return registerLinkActions(
+ objcProvider, extraLinkArgs, extraLinkInputs, defaultLibrariesToLink);
+ }
+
+ /**
+ * Registers any actions necessary to link a test rule and its dependencies, without redundantly
+ * linking libraries already linked into the test application.
+ *
+ * <p>Dsym bundle and breakpad files are generated if
+ * {@link ObjcConfiguration#generateDebugSymbols()} is set.
+ *
+ * <p>When Bazel flags {@code --compilation_mode=opt} and {@code --objc_enable_binary_stripping}
+ * are specified, additional optimizations will be performed on the linked binary: all-symbol
+ * stripping (using {@code /usr/bin/strip}) and dead-code stripping (using linker flags:
+ * {@code -dead_strip} and {@code -no_dead_strip_inits_and_terms}).
+ *
+ * @param objcProvider common information about this rule's attributes and its dependencies
+ * @param extraLinkArgs any additional arguments to pass to the linker
+ * @param extraLinkInputs any additional input artifacts to pass to the link action
+ * @param librariesToLink libraries that were not already linked into the test application
+ *
+ * @return this compilation support
+ */
+ CompilationSupport registerLinkActionsForXcTest(
+ ObjcProvider objcProvider,
+ ExtraLinkArgs extraLinkArgs,
+ Iterable<Artifact> extraLinkInputs,
+ LibrariesToLink librariesToLink) {
+ return registerLinkActions(objcProvider, extraLinkArgs, extraLinkInputs, librariesToLink);
+ }
+
+ private CompilationSupport registerLinkActions(
+ ObjcProvider objcProvider,
+ ExtraLinkArgs extraLinkArgs,
+ Iterable<Artifact> extraLinkInputs,
+ LibrariesToLink librariesToLink) {
IntermediateArtifacts intermediateArtifacts =
ObjcRuleClasses.intermediateArtifacts(ruleContext);
Optional<Artifact> dsymBundle;
@@ -724,6 +760,7 @@ public final class CompilationSupport {
extraLinkArgs,
extraLinkInputs,
dsymBundle,
+ librariesToLink,
prunedJ2ObjcArchives);
return this;
}
@@ -786,8 +823,12 @@ public final class CompilationSupport {
/*externDependencies=*/ true));
}
- private void registerLinkAction(ObjcProvider objcProvider, ExtraLinkArgs extraLinkArgs,
- Iterable<Artifact> extraLinkInputs, Optional<Artifact> dsymBundle,
+ private void registerLinkAction(
+ ObjcProvider objcProvider,
+ ExtraLinkArgs extraLinkArgs,
+ Iterable<Artifact> extraLinkInputs,
+ Optional<Artifact> dsymBundle,
+ LibrariesToLink librariesToLink,
Iterable<Artifact> prunedJ2ObjcArchives) {
ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
IntermediateArtifacts intermediateArtifacts =
@@ -804,18 +845,26 @@ public final class CompilationSupport {
: intermediateArtifacts.strippedSingleArchitectureBinary();
ImmutableList<Artifact> ccLibraries = ccLibraries(objcProvider);
- NestedSet<Artifact> bazelBuiltLibraries = Iterables.isEmpty(prunedJ2ObjcArchives)
- ? objcProvider.get(LIBRARY) : substituteJ2ObjcPrunedLibraries(objcProvider);
+ Iterable<Artifact> bazelBuiltLibraries =
+ Iterables.isEmpty(prunedJ2ObjcArchives)
+ ? librariesToLink.getLibrariesToLink()
+ : substituteJ2ObjcPrunedLibraries(objcProvider, librariesToLink);
ruleContext.registerAction(
ObjcRuleClasses.spawnXcrunActionBuilder(ruleContext)
.setMnemonic("ObjcLink")
.setShellCommand(ImmutableList.of("/bin/bash", "-c"))
.setCommandLine(
- linkCommandLine(extraLinkArgs, objcProvider, binaryToLink, dsymBundle, ccLibraries,
+ linkCommandLine(
+ extraLinkArgs,
+ objcProvider,
+ binaryToLink,
+ dsymBundle,
+ ccLibraries,
+ librariesToLink,
bazelBuiltLibraries))
.addOutput(binaryToLink)
.addOutputs(dsymBundle.asSet())
- .addTransitiveInputs(bazelBuiltLibraries)
+ .addInputs(bazelBuiltLibraries)
.addTransitiveInputs(objcProvider.get(IMPORTED_LIBRARY))
.addTransitiveInputs(objcProvider.get(FRAMEWORK_FILE))
.addInputs(ccLibraries)
@@ -875,13 +924,14 @@ public final class CompilationSupport {
* Returns a nested set of Bazel-built ObjC libraries with all unpruned J2ObjC libraries
* substituted with pruned ones.
*/
- private NestedSet<Artifact> substituteJ2ObjcPrunedLibraries(ObjcProvider objcProvider) {
+ private NestedSet<Artifact> substituteJ2ObjcPrunedLibraries(
+ ObjcProvider objcProvider, LibrariesToLink librariesToLink) {
ImmutableList.Builder<Artifact> libraries = new ImmutableList.Builder<>();
IntermediateArtifacts intermediateArtifacts =
ObjcRuleClasses.intermediateArtifacts(ruleContext);
Set<Artifact> unprunedJ2ObjcLibs = objcProvider.get(ObjcProvider.J2OBJC_LIBRARY).toSet();
- for (Artifact library : objcProvider.get(LIBRARY)) {
+ for (Artifact library : librariesToLink.getLibrariesToLink()) {
// If we match an unpruned J2ObjC library, add the pruned version of the J2ObjC static library
// instead.
if (unprunedJ2ObjcLibs.contains(library)) {
@@ -893,9 +943,14 @@ public final class CompilationSupport {
return NestedSetBuilder.wrap(Order.NAIVE_LINK_ORDER, libraries.build());
}
- private CommandLine linkCommandLine(ExtraLinkArgs extraLinkArgs,
- ObjcProvider objcProvider, Artifact linkedBinary, Optional<Artifact> dsymBundle,
- Iterable<Artifact> ccLibraries, Iterable<Artifact> bazelBuiltLibraries) {
+ private CommandLine linkCommandLine(
+ ExtraLinkArgs extraLinkArgs,
+ ObjcProvider objcProvider,
+ Artifact linkedBinary,
+ Optional<Artifact> dsymBundle,
+ Iterable<Artifact> ccLibraries,
+ LibrariesToLink librariesToLink,
+ Iterable<Artifact> bazelBuiltLibraries) {
ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
Iterable<String> libraryNames = libraryNames(objcProvider);
@@ -920,7 +975,7 @@ public final class CompilationSupport {
if (objcConfiguration.shouldPrioritizeStaticLibs()) {
commandLine
.addExecPaths(bazelBuiltLibraries)
- .addExecPaths(objcProvider.get(IMPORTED_LIBRARY))
+ .addExecPaths(librariesToLink.getImportedLibrariesToLink())
.addExecPaths(ccLibraries);
}
@@ -939,13 +994,14 @@ public final class CompilationSupport {
if (!objcConfiguration.shouldPrioritizeStaticLibs()) {
commandLine
.addExecPaths(bazelBuiltLibraries)
- .addExecPaths(objcProvider.get(IMPORTED_LIBRARY))
+ .addExecPaths(librariesToLink.getImportedLibrariesToLink())
.addExecPaths(ccLibraries);
}
commandLine
.addExecPath("-o", linkedBinary)
- .addBeforeEach("-force_load", Artifact.toExecPaths(objcProvider.get(FORCE_LOAD_LIBRARY)))
+ .addBeforeEach(
+ "-force_load", Artifact.toExecPaths(librariesToLink.getForceLoadLibrariesToLink()))
.add(extraLinkArgs)
.add(objcProvider.get(ObjcProvider.LINKOPT))
.build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java
index cfb68733ba..891e80c1ba 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java
@@ -88,13 +88,15 @@ public final class IosTest implements RuleConfiguredTargetFactory {
addResourceFilesToBuild(ruleContext, common.getObjcProvider(), filesToBuild);
XcodeProductType productType = getProductType(ruleContext);
- ExtraLinkArgs extraLinkArgs;
- Iterable<Artifact> extraLinkInputs;
String bundleFormat;
if (!isXcTest(ruleContext)) {
- extraLinkArgs = new ExtraLinkArgs();
- extraLinkInputs = ImmutableList.of();
bundleFormat = ReleaseBundlingSupport.APP_BUNDLE_DIR_FORMAT;
+ new CompilationSupport(ruleContext)
+ .registerLinkActions(
+ common.getObjcProvider(), new ExtraLinkArgs(), ImmutableList.<Artifact>of())
+ .registerCompileAndArchiveActions(common)
+ .addXcodeSettings(xcodeProviderBuilder, common)
+ .validateAttributes();
} else {
XcodeProvider appIpaXcodeProvider =
ruleContext.getPrerequisite(XCTEST_APP, Mode.TARGET, XcodeProvider.class);
@@ -104,28 +106,32 @@ public final class IosTest implements RuleConfiguredTargetFactory {
XcTestAppProvider testApp = xcTestAppProvider(ruleContext);
Artifact bundleLoader = testApp.getBundleLoader();
-
+ LibrariesToLink librariesToLink =
+ LibrariesToLink.xcTestLibraries(ruleContext, common.getObjcProvider());
+
// -bundle causes this binary to be linked as a bundle and not require an entry point
// (i.e. main())
// -bundle_loader causes the code in this test to have access to the symbols in the test rig,
// or more specifically, the flag causes ld to consider the given binary when checking for
// missing symbols.
- extraLinkArgs = new ExtraLinkArgs(
- "-bundle",
- "-bundle_loader", bundleLoader.getExecPathString());
+ ExtraLinkArgs extraLinkArgs =
+ new ExtraLinkArgs("-bundle", "-bundle_loader", bundleLoader.getExecPathString());
- extraLinkInputs = ImmutableList.of(bundleLoader);
bundleFormat = ReleaseBundlingSupport.XCTEST_BUNDLE_DIR_FORMAT;
-
+
filesToBuild.add(testApp.getIpa());
+
+ new CompilationSupport(ruleContext)
+ .registerLinkActionsForXcTest(
+ common.getObjcProvider(),
+ extraLinkArgs,
+ ImmutableList.of(bundleLoader),
+ librariesToLink)
+ .registerCompileAndArchiveActions(common)
+ .addXcodeSettings(xcodeProviderBuilder, common)
+ .validateAttributes();
}
- new CompilationSupport(ruleContext)
- .registerLinkActions(common.getObjcProvider(), extraLinkArgs, extraLinkInputs)
- .registerCompileAndArchiveActions(common)
- .addXcodeSettings(xcodeProviderBuilder, common)
- .validateAttributes();
-
ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
new ReleaseBundlingSupport(
ruleContext,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/LibrariesToLink.java b/src/main/java/com/google/devtools/build/lib/rules/objc/LibrariesToLink.java
new file mode 100644
index 0000000000..8c41c155ec
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/LibrariesToLink.java
@@ -0,0 +1,111 @@
+// Copyright 2016 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.objc;
+
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+
+/**
+ * Determines libraries that should be linked into an objc library.
+ */
+public class LibrariesToLink {
+
+ private Iterable<Artifact> librariesToLink;
+ private Iterable<Artifact> importedLibrariesToLink;
+ private Iterable<Artifact> forceLoadLibrariesToLink;
+
+ private LibrariesToLink(
+ Iterable<Artifact> librariesToLink,
+ Iterable<Artifact> importedLibrariesToLink,
+ Iterable<Artifact> forceLoadLibrariesToLink) {
+ this.librariesToLink = librariesToLink;
+ this.importedLibrariesToLink = importedLibrariesToLink;
+ this.forceLoadLibrariesToLink = forceLoadLibrariesToLink;
+ }
+
+ /**
+ * Returns libraries not already linked in the test binary.
+ */
+ public Iterable<Artifact> getLibrariesToLink() {
+ return librariesToLink;
+ }
+
+ /**
+ * Returns imported libraries not already linked in the test binary.
+ */
+ public Iterable<Artifact> getImportedLibrariesToLink() {
+ return importedLibrariesToLink;
+ }
+
+ /**
+ * Returns libraries not already linked into the test binary with the --force_load option.
+ */
+ public Iterable<Artifact> getForceLoadLibrariesToLink() {
+ return forceLoadLibrariesToLink;
+ }
+
+ /**
+ * Creates an instance of LibrariesToLink for an XcTest application by removing libraries
+ * already linked into the test binary. Should only be used if the xctest_app attribute
+ * is set.
+ *
+ * @param ruleContext the RuleContext of the test rule
+ * @param objcProvider the ObjcProvider of the test rule
+ */
+ public static LibrariesToLink xcTestLibraries(
+ RuleContext ruleContext, ObjcProvider objcProvider) {
+
+ Iterable<Artifact> librariesToLink = objcProvider.get(LIBRARY);
+ Iterable<Artifact> importedLibrariesToLink = objcProvider.get(IMPORTED_LIBRARY);
+ Iterable<Artifact> forceLoadLibrariesToLink = objcProvider.get(FORCE_LOAD_LIBRARY);
+
+ XcTestAppProvider xcTestAppProvider =
+ ruleContext.getPrerequisite(IosTest.XCTEST_APP, Mode.TARGET, XcTestAppProvider.class);
+ librariesToLink =
+ Sets.difference(
+ objcProvider.get(LIBRARY).toSet(),
+ ImmutableSet.copyOf(xcTestAppProvider.getLinkedLibraries()));
+ importedLibrariesToLink =
+ Sets.difference(
+ objcProvider.get(IMPORTED_LIBRARY).toSet(),
+ ImmutableSet.copyOf(xcTestAppProvider.getLinkedImportedLibraries()));
+ forceLoadLibrariesToLink =
+ Sets.difference(
+ objcProvider.get(FORCE_LOAD_LIBRARY).toSet(),
+ ImmutableSet.copyOf(xcTestAppProvider.getForceLoadLibraries()));
+
+ return new LibrariesToLink(librariesToLink, importedLibrariesToLink, forceLoadLibrariesToLink);
+ }
+
+ /**
+ * Creates an instance of LibrariesToLink without subtractions. For use when not linking an
+ * xctest app.
+ *
+ * @param objcProvider the provider for the rule
+ */
+ public static LibrariesToLink defaultLibraries(ObjcProvider objcProvider) {
+ return new LibrariesToLink(
+ objcProvider.get(LIBRARY),
+ objcProvider.get(IMPORTED_LIBRARY),
+ objcProvider.get(FORCE_LOAD_LIBRARY));
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java
index 1bfed353b3..7481f5a58d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java
@@ -521,8 +521,18 @@ public final class ReleaseBundlingSupport {
.build();
// TODO(bazel-team): Handle the FRAMEWORK_DIR key properly. We probably want to add it to
// framework search paths, but not actually link it with the -framework flag.
- return new XcTestAppProvider(intermediateArtifacts.combinedArchitectureBinary(),
- ruleContext.getImplicitOutputArtifact(IPA), partialObjcProvider);
+
+ Iterable<Artifact> linkedArtifacts = objcProvider.get(ObjcProvider.LIBRARY);
+ Iterable<Artifact> linkedImportedLibraries = objcProvider.get(ObjcProvider.IMPORTED_LIBRARY);
+ Iterable<Artifact> forceLoadLibraries = objcProvider.get(ObjcProvider.FORCE_LOAD_LIBRARY);
+
+ return new XcTestAppProvider(
+ intermediateArtifacts.combinedArchitectureBinary(),
+ ruleContext.getImplicitOutputArtifact(IPA),
+ partialObjcProvider,
+ linkedArtifacts,
+ linkedImportedLibraries,
+ forceLoadLibraries);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java
index 3d47454e2e..899ab0b3c3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/XcTestAppProvider.java
@@ -27,11 +27,36 @@ public final class XcTestAppProvider implements TransitiveInfoProvider {
private final Artifact bundleLoader;
private final Artifact ipa;
private final ObjcProvider objcProvider;
+ private final Iterable<Artifact> linkedLibraries;
+ private final Iterable<Artifact> linkedImportedLibraries;
+ private final Iterable<Artifact> forceLoadLibraries;
- XcTestAppProvider(Artifact bundleLoader, Artifact ipa, ObjcProvider objcProvider) {
+ /**
+ * Constructs XcTestAppProvider.
+ *
+ * @param bundleLoader the bundle loader to be passed into the linker of the test binary
+ * @param ipa the bundled test application
+ * @param objcProvider an objcProvider to be passed to the depending IosTest target
+ * @param linkedLibraries libraries already linked into the test application, that should not be
+ * linked into the IosTest binary
+ * @param linkedImportedLibraries imported Libraries already linked into the test application,
+ * that should not be linked into the IosTest binary
+ * @param forceLoadLibraries libraries already linked into the test application with --force_load
+ * that should not be linked into the IosTest binary
+ */
+ XcTestAppProvider(
+ Artifact bundleLoader,
+ Artifact ipa,
+ ObjcProvider objcProvider,
+ Iterable<Artifact> linkedLibraries,
+ Iterable<Artifact> linkedImportedLibraries,
+ Iterable<Artifact> forceLoadLibraries) {
this.bundleLoader = Preconditions.checkNotNull(bundleLoader);
this.ipa = Preconditions.checkNotNull(ipa);
this.objcProvider = Preconditions.checkNotNull(objcProvider);
+ this.linkedLibraries = linkedLibraries;
+ this.linkedImportedLibraries = linkedImportedLibraries;
+ this.forceLoadLibraries = forceLoadLibraries;
}
/**
@@ -54,4 +79,29 @@ public final class XcTestAppProvider implements TransitiveInfoProvider {
public ObjcProvider getObjcProvider() {
return objcProvider;
}
+
+ /**
+ * Returns the list of libraries that were linked into the host application. These libraries
+ * should not also be linked into the test binary, so as to prevent ambiguous references.
+ */
+ public Iterable<Artifact> getLinkedLibraries() {
+ return linkedLibraries;
+ }
+
+ /**
+ * Returns the list of imported libraries that were linked into the host application. These
+ * libraries should not also be linked into the test binary, so as to
+ * prevent ambiguous references.
+ */
+ public Iterable<Artifact> getLinkedImportedLibraries() {
+ return linkedImportedLibraries;
+ }
+
+ /**
+ * Returns the list of libraries that were linked into the host application with the --force_load
+ * flag.
+ */
+ public Iterable<Artifact> getForceLoadLibraries() {
+ return forceLoadLibraries;
+ }
}