aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Cal Peyser <cpeyser@google.com>2016-11-15 20:21:38 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2016-11-16 15:56:43 +0000
commit5bb4ff6886450217f00765c7ed19055ff08e9568 (patch)
tree0e6c8a00d58e6f26283a9fb116b450c6f3a7f7f1
parent60751d02cf9e2d78ab5d4bf9fee0006b8adcf453 (diff)
Implement basic objc executable linking in the CROSSTOOL.
The following link features are *not* implemented yet: 1) Objc++ linking semantics 2) Dead stripping 3) --should_prioritize_static_libs 4) DSYM generation 5) Coverage support 6) Swift interop 7) Linkmap -- MOS_MIGRATED_REVID=139232434
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java41
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java58
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java230
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java125
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java176
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java189
10 files changed, 610 insertions, 253 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
index ca464d2a1b..bf9e7c5367 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainFeatures.java
@@ -1150,7 +1150,7 @@ public class CcToolchainFeatures implements Serializable {
* Add a variable that expands a flag group containing a reference to {@code name} for each
* entry in {@code values}.
*/
- public Builder addSequenceVariable(String name, Collection<String> values) {
+ public Builder addSequenceVariable(String name, Iterable<String> values) {
StringSequence.Builder sequenceBuilder = new StringSequence.Builder();
for (String value : values) {
sequenceBuilder.addValue(value);
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 44004745a0..04dc86895e 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
@@ -95,6 +95,7 @@ public final class CppLinkAction extends AbstractAction
private static final String LINK_GUID = "58ec78bd-1176-4e36-8143-439f656b181d";
private static final String FAKE_LINK_GUID = "da36f819-5a15-43a9-8a45-e01b60e10c8b";
+ @Nullable private final String mnemonic;
private final CppConfiguration cppConfiguration;
private final LibraryToLink outputLibrary;
private final Artifact linkOutput;
@@ -138,6 +139,7 @@ public final class CppLinkAction extends AbstractAction
*/
CppLinkAction(
ActionOwner owner,
+ String mnemonic,
Iterable<Artifact> inputs,
ImmutableList<Artifact> outputs,
CppConfiguration cppConfiguration,
@@ -151,6 +153,11 @@ public final class CppLinkAction extends AbstractAction
Map<String, String> toolchainEnv,
ImmutableSet<String> executionRequirements) {
super(owner, inputs, outputs);
+ if (mnemonic == null) {
+ this.mnemonic = (isLTOIndexing) ? "CppLTOIndexing" : "CppLink";
+ } else {
+ this.mnemonic = mnemonic;
+ }
this.mandatoryInputs = inputs;
this.cppConfiguration = cppConfiguration;
this.outputLibrary = outputLibrary;
@@ -457,7 +464,7 @@ public final class CppLinkAction extends AbstractAction
@Override
public String getMnemonic() {
- return (isLTOIndexing) ? "CppLTOIndexing" : "CppLink";
+ return mnemonic;
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index f2690c6062..9fe8673389 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -124,6 +124,7 @@ public class CppLinkActionBuilder {
@Nullable private final RuleContext ruleContext;
private final AnalysisEnvironment analysisEnvironment;
private final Artifact output;
+ @Nullable private String mnemonic;
// can be null for CppLinkAction.createTestBuilder()
@Nullable private final CcToolchainProvider toolchain;
@@ -162,7 +163,7 @@ public class CppLinkActionBuilder {
private Iterable<LTOBackendArtifacts> allLTOArtifacts = null;
private final List<VariablesExtension> variablesExtensions = new ArrayList<>();
- private final List<Artifact> linkActionInputs = new ArrayList<>();
+ private final NestedSetBuilder<Artifact> linkActionInputs = NestedSetBuilder.stableOrder();
/**
* Creates a builder that builds {@link CppLinkAction} instances.
@@ -442,8 +443,11 @@ public class CppLinkActionBuilder {
/** Builds the Action as configured and returns it. */
public CppLinkAction build() throws InterruptedException {
- Preconditions.checkState(
- (libraryIdentifier == null) == (linkType == LinkTargetType.EXECUTABLE));
+ // Executable links do not have library identifiers.
+ boolean hasIdentifier = (libraryIdentifier != null);
+ boolean isExecutable = linkType.isExecutable();
+ Preconditions.checkState(hasIdentifier != isExecutable);
+
if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) {
throw new RuntimeException(
"Interface output can only be used " + "with non-fake DYNAMIC_LIBRARY targets");
@@ -485,7 +489,7 @@ public class CppLinkActionBuilder {
}
}
- final LibraryToLink outputLibrary = linkType == LinkTargetType.EXECUTABLE
+ final LibraryToLink outputLibrary = linkType.isExecutable()
? null
: LinkerInputs.newInputLibrary(output,
linkType.getLinkerOutput(),
@@ -651,7 +655,7 @@ public class CppLinkActionBuilder {
NestedSetBuilder<Artifact> dependencyInputsBuilder = NestedSetBuilder.stableOrder();
dependencyInputsBuilder.addTransitive(crosstoolInputs);
dependencyInputsBuilder.add(toolchain.getLinkDynamicLibraryTool());
- dependencyInputsBuilder.addAll(linkActionInputs);
+ dependencyInputsBuilder.addTransitive(linkActionInputs.build());
if (runtimeMiddleman != null) {
dependencyInputsBuilder.add(runtimeMiddleman);
}
@@ -737,6 +741,7 @@ public class CppLinkActionBuilder {
return new CppLinkAction(
getOwner(),
+ mnemonic,
inputsBuilder.deduplicate().build(),
actionOutputs,
cppConfiguration,
@@ -840,6 +845,12 @@ public class CppLinkActionBuilder {
protected ActionOwner getOwner() {
return ruleContext.getActionOwner();
}
+
+ /** Sets the mnemonic for the link action. */
+ public CppLinkActionBuilder setMnemonic(String mnemonic) {
+ this.mnemonic = mnemonic;
+ return this;
+ }
/** Set the crosstool inputs required for the action. */
public CppLinkActionBuilder setCrosstoolInputs(NestedSet<Artifact> inputs) {
@@ -1143,12 +1154,28 @@ public class CppLinkActionBuilder {
}
/**
- * Sets extra input artifacts to the link action.
+ * Adds an extra input artifact to the link action.
+ */
+ public CppLinkActionBuilder addActionInput(Artifact input) {
+ this.linkActionInputs.add(input);
+ return this;
+ }
+
+ /**
+ * Adds extra input artifacts to the link action.
*/
- public CppLinkActionBuilder addActionInputs(Collection<Artifact> inputs) {
+ public CppLinkActionBuilder addActionInputs(Iterable<Artifact> inputs) {
this.linkActionInputs.addAll(inputs);
return this;
}
+
+ /**
+ * Adds extra input artifacts to the link actions.
+ */
+ public CppLinkActionBuilder addTransitiveActionInputs(NestedSet<Artifact> inputs) {
+ this.linkActionInputs.addTransitive(inputs);
+ return this;
+ }
private static class LinkArgCollector {
String rpathRoot;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
index ec51c8413f..74f33ab913 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
@@ -103,6 +103,14 @@ public abstract class Link {
STATIC,
DYNAMIC
}
+
+ /**
+ * Whether a particular link target is executable.
+ */
+ public enum Executable {
+ EXECUTABLE,
+ NOT_EXECUTABLE
+ }
/**
* Types of ELF files that can be created by the linker (.a, .so, .lo,
@@ -115,7 +123,8 @@ public abstract class Link {
Staticness.STATIC,
"c++-link-static-library",
Picness.NOPIC,
- ArtifactCategory.STATIC_LIBRARY),
+ ArtifactCategory.STATIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** An objc static archive. */
OBJC_ARCHIVE(
@@ -123,19 +132,35 @@ public abstract class Link {
Staticness.STATIC,
"objc-archive",
Picness.NOPIC,
- ArtifactCategory.STATIC_LIBRARY),
+ ArtifactCategory.STATIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** An objc fully linked static archive. */
OBJC_FULLY_LINKED_ARCHIVE(
- ".a", Staticness.STATIC, "objc-fully-link", Picness.NOPIC, ArtifactCategory.STATIC_LIBRARY),
+ ".a",
+ Staticness.STATIC,
+ "objc-fully-link",
+ Picness.NOPIC,
+ ArtifactCategory.STATIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
+ /** An objc executable. */
+ OBJC_EXECUTABLE(
+ "",
+ Staticness.STATIC,
+ "objc-executable",
+ Picness.NOPIC,
+ ArtifactCategory.EXECUTABLE,
+ Executable.EXECUTABLE),
+
/** A static archive with .pic.o object files (compiled with -fPIC). */
PIC_STATIC_LIBRARY(
".pic.a",
Staticness.STATIC,
"c++-link-pic-static-library",
Picness.PIC,
- ArtifactCategory.STATIC_LIBRARY),
+ ArtifactCategory.STATIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** An interface dynamic library. */
INTERFACE_DYNAMIC_LIBRARY(
@@ -143,7 +168,8 @@ public abstract class Link {
Staticness.DYNAMIC,
"c++-link-interface-dynamic-library",
Picness.NOPIC, // Actually PIC but it's not indicated in the file name
- ArtifactCategory.INTERFACE_LIBRARY),
+ ArtifactCategory.INTERFACE_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** A dynamic library. */
DYNAMIC_LIBRARY(
@@ -151,7 +177,8 @@ public abstract class Link {
Staticness.DYNAMIC,
"c++-link-dynamic-library",
Picness.NOPIC, // Actually PIC but it's not indicated in the file name
- ArtifactCategory.DYNAMIC_LIBRARY),
+ ArtifactCategory.DYNAMIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** A static archive without removal of unused object files. */
ALWAYS_LINK_STATIC_LIBRARY(
@@ -159,7 +186,8 @@ public abstract class Link {
Staticness.STATIC,
"c++-link-alwayslink-static-library",
Picness.NOPIC,
- ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY),
+ ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** A PIC static archive without removal of unused object files. */
ALWAYS_LINK_PIC_STATIC_LIBRARY(
@@ -167,7 +195,8 @@ public abstract class Link {
Staticness.STATIC,
"c++-link-alwayslink-pic-static-library",
Picness.PIC,
- ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY),
+ ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY,
+ Executable.NOT_EXECUTABLE),
/** An executable binary. */
EXECUTABLE(
@@ -175,25 +204,29 @@ public abstract class Link {
Staticness.DYNAMIC,
"c++-link-executable",
Picness.NOPIC, // Picness is not indicate in the file name
- ArtifactCategory.EXECUTABLE);
+ ArtifactCategory.EXECUTABLE,
+ Executable.EXECUTABLE);
private final String extension;
private final Staticness staticness;
private final String actionName;
private final ArtifactCategory linkerOutput;
private final Picness picness;
+ private final Executable executable;
LinkTargetType(
String extension,
Staticness staticness,
String actionName,
Picness picness,
- ArtifactCategory linkerOutput) {
+ ArtifactCategory linkerOutput,
+ Executable executable) {
this.extension = extension;
this.staticness = staticness;
this.actionName = actionName;
this.linkerOutput = linkerOutput;
this.picness = picness;
+ this.executable = executable;
}
/**
@@ -223,6 +256,11 @@ public abstract class Link {
public String getActionName() {
return actionName;
}
+
+ /** Returns true iff this link type is executable */
+ public boolean isExecutable() {
+ return (executable == Executable.EXECUTABLE);
+ }
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
index 27e3e4db99..6a95202423 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
@@ -408,6 +408,7 @@ public final class LinkCommandLine extends CommandLine {
// TODO(b/30109612): make this pattern the case for all link variants.
case OBJC_ARCHIVE:
case OBJC_FULLY_LINKED_ARCHIVE:
+ case OBJC_EXECUTABLE:
argv.add(toolPath);
argv.addAll(featureConfiguration.getCommandLine(actionName, variables));
break;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
index 59eddc2d90..ea26384486 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
@@ -115,34 +115,26 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory
ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcEntryClassProvider.class))
.build();
- CompilationSupport compilationSupport;
- LegacyCompilationSupport legacyCompilationSupport = new LegacyCompilationSupport(ruleContext);
+ CompilationSupport compilationSupport = (usesCrosstool != UsesCrosstool.EXPERIMENTAL
+ || !ruleContext.getFragment(ObjcConfiguration.class).useCrosstoolForBinary())
+ ? new LegacyCompilationSupport(ruleContext)
+ : new CrosstoolCompilationSupport(ruleContext);
- if (usesCrosstool != UsesCrosstool.EXPERIMENTAL
- || !ruleContext.getFragment(ObjcConfiguration.class).useCrosstoolForBinary()) {
- compilationSupport = legacyCompilationSupport;
- } else {
- compilationSupport = new CrosstoolCompilationSupport(ruleContext);
- }
-
compilationSupport
+ .validateAttributes()
.addXcodeSettings(xcodeProviderBuilder, common)
.registerCompileAndArchiveActions(common)
.registerFullyLinkAction(
common.getObjcProvider(),
ruleContext.getImplicitOutputArtifact(CompilationSupport.FULLY_LINKED_LIB))
- .validateAttributes();
+ .registerLinkActions(
+ objcProvider,
+ j2ObjcMappingFileProvider,
+ j2ObjcEntryClassProvider,
+ getExtraLinkArgs(ruleContext),
+ ImmutableList.<Artifact>of(),
+ DsymOutputType.APP);
- // TODO(b/29582284): Factor into the above if/else once CrosstoolCompilationSupport supports
- // executable linking.
- legacyCompilationSupport.registerLinkActions(
- objcProvider,
- j2ObjcMappingFileProvider,
- j2ObjcEntryClassProvider,
- getExtraLinkArgs(ruleContext),
- ImmutableList.<Artifact>of(),
- DsymOutputType.APP);
-
Optional<XcTestAppProvider> xcTestAppProvider;
Optional<RunfilesSupport> maybeRunfilesSupport = Optional.absent();
switch (hasReleaseBundlingSupport) {
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 8bf9121f19..aaa5d80f60 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
@@ -15,10 +15,15 @@
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.cpp.Link.LINK_LIBRARY_FILETYPES;
+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_SEARCH_PATH_ONLY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE_SYSTEM;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.COMPILABLE_SRCS_TYPE;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.HEADERS;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.NON_ARC_SRCS_TYPE;
@@ -28,7 +33,9 @@ import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SWIFT_SOU
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
@@ -67,8 +74,11 @@ import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.Local
import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
/**
* Support for rules that compile sources. Provides ways to determine files that should be output,
@@ -119,6 +129,17 @@ public abstract class CompilationSupport {
ImmutableList.of(
"-fexceptions", "-fasm-blocks", "-fobjc-abi-version=2", "-fobjc-legacy-dispatch");
+ private static final String FRAMEWORK_SUFFIX = ".framework";
+
+ /** Selects cc libraries that have alwayslink=1. */
+ protected static final Predicate<Artifact> ALWAYS_LINKED_CC_LIBRARY =
+ new Predicate<Artifact>() {
+ @Override
+ public boolean apply(Artifact input) {
+ return LINK_LIBRARY_FILETYPES.matches(input.getFilename());
+ }
+ };
+
/**
* Returns the location of the xcrunwrapper tool.
*/
@@ -427,7 +448,7 @@ public abstract class CompilationSupport {
// The COVERAGE_GCOV_PATH environment variable is added in TestSupport#getExtraProviders()
NestedSetBuilder.<Pair<String, String>>emptySet(Order.COMPILE_ORDER),
!TargetUtils.isTestRule(ruleContext.getTarget()));
- }
+ }
/**
* Registers an action that will generate a clang module map for this target, using the hdrs
@@ -450,7 +471,7 @@ public abstract class CompilationSupport {
return this;
}
- /**
+ /**
* Validates compilation-related attributes on this rule.
*
* @return this compilation support
@@ -578,7 +599,7 @@ public abstract class CompilationSupport {
J2ObjcEntryClassProvider j2ObjcEntryClassProvider,
ExtraLinkArgs extraLinkArgs,
Iterable<Artifact> extraLinkInputs,
- DsymOutputType dsymOutputType);
+ DsymOutputType dsymOutputType) throws InterruptedException;
/**
* Returns the copts for the compile action in the current rule context (using a combination of
@@ -611,7 +632,7 @@ public abstract class CompilationSupport {
}
return copts;
}
-
+
/**
* Registers an action that writes given set of object files to the given objList. This objList is
* suitable to signal symbols to archive in a libtool archiving invocation.
@@ -645,8 +666,8 @@ public abstract class CompilationSupport {
}
/**
- * Registers an action to create an archive artifact by fully (statically) linking all
- * transitive dependencies of this rule.
+ * Registers an action to create an archive artifact by fully (statically) linking all transitive
+ * dependencies of this rule.
*
* @param objcProvider provides all compiling and linking information to create this artifact
* @param inputArtifacts inputs for this action
@@ -657,7 +678,200 @@ public abstract class CompilationSupport {
ObjcProvider objcProvider, Iterable<Artifact> inputArtifacts, Artifact outputArchive)
throws InterruptedException;
-
+ /**
+ * Returns all framework names to pass to the linker using {@code -framework} flags. For a
+ * framework in the directory foo/bar.framework, the name is "bar". Each framework is found
+ * without using the full path by means of the framework search paths. Search paths are added by
+ * {@link#commonLinkAndCompileFlagsForClang(ObjcProvider, ObjcConfiguration, AppleConfiguration)})
+ *
+ * <p>It's awful that we can't pass the full path to the framework and avoid framework search
+ * paths, but this is imposed on us by clang. clang does not support passing the full path to the
+ * framework, so Bazel cannot do it either.
+ */
+ protected Set<String> frameworkNames(ObjcProvider provider) {
+ Set<String> names = new LinkedHashSet<>();
+ Iterables.addAll(names, SdkFramework.names(provider.get(SDK_FRAMEWORK)));
+ for (PathFragment frameworkDir : provider.get(FRAMEWORK_DIR)) {
+ String segment = frameworkDir.getBaseName();
+ Preconditions.checkState(
+ segment.endsWith(FRAMEWORK_SUFFIX),
+ "expect %s to end with %s, but it does not",
+ segment,
+ FRAMEWORK_SUFFIX);
+ names.add(segment.substring(0, segment.length() - FRAMEWORK_SUFFIX.length()));
+ }
+ return names;
+ }
+
+ /**
+ * Returns libraries that should be passed to the linker.
+ */
+ protected ImmutableList<String> libraryNames(ObjcProvider objcProvider) {
+ ImmutableList.Builder<String> args = new ImmutableList.Builder<>();
+ for (String dylib : objcProvider.get(SDK_DYLIB)) {
+ if (dylib.startsWith("lib")) {
+ // remove lib prefix if it exists which is standard
+ // for libraries (libxml.dylib -> -lxml).
+ dylib = dylib.substring(3);
+ }
+ args.add(dylib);
+ }
+ return args.build();
+ }
+
+ /**
+ * Returns libraries that should be passed into the linker with {@code -force_load}.
+ */
+ protected ImmutableSet<Artifact> getForceLoadArtifacts(ObjcProvider objcProvider) {
+ ImmutableList<Artifact> ccLibraries = objcProvider.getCcLibraries();
+ Iterable<Artifact> ccLibrariesToForceLoad =
+ Iterables.filter(ccLibraries, ALWAYS_LINKED_CC_LIBRARY);
+
+ return ImmutableSet.<Artifact>builder()
+ .addAll(objcProvider.get(FORCE_LOAD_LIBRARY))
+ .addAll(ccLibrariesToForceLoad)
+ .build();
+ }
+
+ /** Returns pruned J2Objc archives for this target. */
+ protected ImmutableList<Artifact> j2objcPrunedLibraries(ObjcProvider objcProvider) {
+ ImmutableList.Builder<Artifact> j2objcPrunedLibraryBuilder = ImmutableList.builder();
+ for (Artifact j2objcLibrary : objcProvider.get(ObjcProvider.J2OBJC_LIBRARY)) {
+ j2objcPrunedLibraryBuilder.add(intermediateArtifacts.j2objcPrunedArchive(j2objcLibrary));
+ }
+ return j2objcPrunedLibraryBuilder.build();
+ }
+
+ /**
+ * Returns true if this build should strip J2Objc dead code.
+ */
+ protected boolean stripJ2ObjcDeadCode(J2ObjcEntryClassProvider j2ObjcEntryClassProvider) {
+ J2ObjcConfiguration j2objcConfiguration =
+ buildConfiguration.getFragment(J2ObjcConfiguration.class);
+ // Only perform J2ObjC dead code stripping if flag --j2objc_dead_code_removal is specified and
+ // users have specified entry classes.
+ return j2objcConfiguration.removeDeadCode()
+ && !j2ObjcEntryClassProvider.getEntryClasses().isEmpty();
+ }
+
+ /**
+ * Registers actions to perform J2Objc dead code removal.
+ */
+ protected void registerJ2ObjcDeadCodeRemovalActions(
+ ObjcProvider objcProvider,
+ J2ObjcMappingFileProvider j2ObjcMappingFileProvider,
+ J2ObjcEntryClassProvider j2ObjcEntryClassProvider) {
+ NestedSet<String> entryClasses = j2ObjcEntryClassProvider.getEntryClasses();
+ Artifact pruner = ruleContext.getPrerequisiteArtifact("$j2objc_dead_code_pruner", Mode.HOST);
+ NestedSet<Artifact> j2ObjcDependencyMappingFiles =
+ j2ObjcMappingFileProvider.getDependencyMappingFiles();
+ NestedSet<Artifact> j2ObjcHeaderMappingFiles =
+ j2ObjcMappingFileProvider.getHeaderMappingFiles();
+ NestedSet<Artifact> j2ObjcArchiveSourceMappingFiles =
+ j2ObjcMappingFileProvider.getArchiveSourceMappingFiles();
+
+ for (Artifact j2objcArchive : objcProvider.get(ObjcProvider.J2OBJC_LIBRARY)) {
+ PathFragment paramFilePath =
+ FileSystemUtils.replaceExtension(
+ j2objcArchive.getOwner().toPathFragment(), ".param.j2objc");
+ Artifact paramFile =
+ ruleContext.getUniqueDirectoryArtifact(
+ "_j2objc_pruned", paramFilePath, ruleContext.getBinOrGenfilesDirectory());
+ Artifact prunedJ2ObjcArchive = intermediateArtifacts.j2objcPrunedArchive(j2objcArchive);
+ Artifact dummyArchive =
+ Iterables.getOnlyElement(
+ ruleContext
+ .getPrerequisite("$dummy_lib", Mode.TARGET, ObjcProvider.class)
+ .get(LIBRARY));
+
+ CustomCommandLine commandLine =
+ CustomCommandLine.builder()
+ .addExecPath("--input_archive", j2objcArchive)
+ .addExecPath("--output_archive", prunedJ2ObjcArchive)
+ .addExecPath("--dummy_archive", dummyArchive)
+ .addExecPath("--xcrunwrapper", xcrunwrapper(ruleContext).getExecutable())
+ .addJoinExecPaths("--dependency_mapping_files", ",", j2ObjcDependencyMappingFiles)
+ .addJoinExecPaths("--header_mapping_files", ",", j2ObjcHeaderMappingFiles)
+ .addJoinExecPaths(
+ "--archive_source_mapping_files", ",", j2ObjcArchiveSourceMappingFiles)
+ .add("--entry_classes")
+ .add(Joiner.on(",").join(entryClasses))
+ .build();
+
+ ruleContext.registerAction(
+ new ParameterFileWriteAction(
+ ruleContext.getActionOwner(),
+ paramFile,
+ commandLine,
+ ParameterFile.ParameterFileType.UNQUOTED,
+ ISO_8859_1));
+ ruleContext.registerAction(
+ ObjcRuleClasses.spawnAppleEnvActionBuilder(
+ appleConfiguration, appleConfiguration.getSingleArchPlatform())
+ .setMnemonic("DummyPruner")
+ .setExecutable(pruner)
+ .addInput(dummyArchive)
+ .addInput(pruner)
+ .addInput(paramFile)
+ .addInput(j2objcArchive)
+ .addInput(xcrunwrapper(ruleContext).getExecutable())
+ .addTransitiveInputs(j2ObjcDependencyMappingFiles)
+ .addTransitiveInputs(j2ObjcHeaderMappingFiles)
+ .addTransitiveInputs(j2ObjcArchiveSourceMappingFiles)
+ .setCommandLine(
+ CustomCommandLine.builder().addPaths("@%s", paramFile.getExecPath()).build())
+ .addOutput(prunedJ2ObjcArchive)
+ .build(ruleContext));
+ }
+ }
+
+ /** Returns archives arising from j2objc transpilation after dead code removal. */
+ protected Iterable<Artifact> computeAndStripPrunedJ2ObjcArchives(
+ J2ObjcEntryClassProvider j2ObjcEntryClassProvider,
+ J2ObjcMappingFileProvider j2ObjcMappingFileProvider,
+ ObjcProvider objcProvider) {
+ Iterable<Artifact> prunedJ2ObjcArchives = ImmutableList.<Artifact>of();
+ if (stripJ2ObjcDeadCode(j2ObjcEntryClassProvider)) {
+ registerJ2ObjcDeadCodeRemovalActions(
+ objcProvider, j2ObjcMappingFileProvider, j2ObjcEntryClassProvider);
+ prunedJ2ObjcArchives = j2objcPrunedLibraries(objcProvider);
+ }
+ return prunedJ2ObjcArchives;
+ }
+
+ /**
+ * Returns a nested set of Bazel-built ObjC libraries with all unpruned J2ObjC libraries
+ * substituted with pruned ones.
+ */
+ protected ImmutableList<Artifact> substituteJ2ObjcPrunedLibraries(ObjcProvider objcProvider) {
+ ImmutableList.Builder<Artifact> libraries = new ImmutableList.Builder<>();
+
+ Set<Artifact> unprunedJ2ObjcLibs = objcProvider.get(ObjcProvider.J2OBJC_LIBRARY).toSet();
+ for (Artifact library : objcProvider.getObjcLibraries()) {
+ // If we match an unpruned J2ObjC library, add the pruned version of the J2ObjC static library
+ // instead.
+ if (unprunedJ2ObjcLibs.contains(library)) {
+ libraries.add(intermediateArtifacts.j2objcPrunedArchive(library));
+ } else {
+ libraries.add(library);
+ }
+ }
+ return libraries.build();
+ }
+
+ /** Returns the artifact that should be the outcome of this build's link action */
+ protected Artifact getBinaryToLink() {
+
+ // When compilation_mode=opt and objc_enable_binary_stripping are specified, the unstripped
+ // binary containing debug symbols is generated by the linker, which also needs the debug
+ // symbols for dead-code removal. The binary is also used to generate dSYM bundle if
+ // --apple_generate_dsym is specified. A symbol strip action is later registered to strip
+ // the symbol table from the unstripped binary.
+ return objcConfiguration.shouldStripBinary()
+ ? intermediateArtifacts.unstrippedSingleArchitectureBinary()
+ : intermediateArtifacts.strippedSingleArchitectureBinary();
+ }
+
private NestedSet<Artifact> getGcovForObjectiveCIfNeeded() {
if (ruleContext.getConfiguration().isCodeCoverageEnabled()
&& ruleContext.attributes().has(IosTest.OBJC_GCOV_ATTR, BuildType.LABEL)) {
@@ -719,4 +933,4 @@ public abstract class CompilationSupport {
}
return parents.build();
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java
index bf50ddff16..cd6789d3d1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CrosstoolCompilationSupport.java
@@ -15,12 +15,17 @@
package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE_SYSTEM;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE;
+import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+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.RuleConfiguredTarget.Mode;
@@ -38,15 +43,16 @@ import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.cpp.Link.LinkStaticness;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.PrecompiledFiles;
+import com.google.devtools.build.lib.rules.objc.ObjcVariablesExtension.VariableCategory;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
/**
- * Constructs command lines for objc compilation, archiving, and linking. Uses the crosstool
- * infrastructure to register {@link CppCompileAction} and {@link CppLinkAction} instances,
- * making use of a provided toolchain.
- *
- * TODO(b/28403953): Deprecate LegacyCompilationSupport in favor of this implementation for all
+ * Constructs command lines for objc compilation, archiving, and linking. Uses the crosstool
+ * infrastructure to register {@link CppCompileAction} and {@link CppLinkAction} instances, making
+ * use of a provided toolchain.
+ *
+ * <p>TODO(b/28403953): Deprecate LegacyCompilationSupport in favor of this implementation for all
* objc rules.
*/
public class CrosstoolCompilationSupport extends CompilationSupport {
@@ -59,6 +65,7 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
"objc++-compile",
"objc-archive",
"objc-fully-link",
+ "objc-executable",
"assemble",
"preprocess-assemble",
"c-compile",
@@ -79,25 +86,37 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
CompilationAttributes.Builder.fromRuleContext(ruleContext).build());
this.compilationArtifacts = compilationArtifacts(ruleContext);
}
-
+
@Override
CompilationSupport registerCompileAndArchiveActions(
ObjcCommon common, ExtraCompileArgs extraCompileArgs, Iterable<PathFragment> priorityHeaders)
throws RuleErrorException, InterruptedException {
- CcLibraryHelper helper = createCcLibraryHelper(common);
-
+ ObjcVariablesExtension.Builder extension = new ObjcVariablesExtension.Builder()
+ .setRuleContext(ruleContext)
+ .setObjcProvider(common.getObjcProvider())
+ .setCompilationArtifacts(compilationArtifacts)
+ .setIntermediateArtifacts(intermediateArtifacts)
+ .setConfiguration(ruleContext.getConfiguration());
+ CcLibraryHelper helper;
+
if (compilationArtifacts.getArchive().isPresent()) {
Artifact objList = intermediateArtifacts.archiveObjList();
// TODO(b/30783125): Signal the need for this action in the CROSSTOOL.
registerObjFilelistAction(getObjFiles(compilationArtifacts, intermediateArtifacts), objList);
- helper.setLinkType(LinkTargetType.OBJC_ARCHIVE).addLinkActionInput(objList);
+ extension.addVariableCategory(VariableCategory.ARCHIVE_VARIABLES);
+
+ helper = createCcLibraryHelper(common, extension.build())
+ .setLinkType(LinkTargetType.OBJC_ARCHIVE)
+ .addLinkActionInput(objList);
+ } else {
+ helper = createCcLibraryHelper(common, extension.build());
}
-
- helper.build();
+ helper.build();
+
return this;
}
@@ -113,6 +132,16 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
.getPackageDirectory()
.getRelative(labelName.replaceName("lib" + labelName.getBaseName()))
.getPathString();
+ ObjcVariablesExtension extension = new ObjcVariablesExtension.Builder()
+ .setRuleContext(ruleContext)
+ .setObjcProvider(objcProvider)
+ .setConfiguration(ruleContext.getConfiguration())
+ .setIntermediateArtifacts(intermediateArtifacts)
+ .setFullyLinkArchive(
+ ruleContext.getImplicitOutputArtifact(CompilationSupport.FULLY_LINKED_LIB))
+ .addVariableCategory(VariableCategory.FULLY_LINK_VARIABLES)
+ .build();
+
CppLinkAction fullyLinkAction =
new CppLinkActionBuilder(ruleContext, fullyLinkedArchive)
.addActionInputs(objcProvider.getObjcLibraries())
@@ -121,7 +150,7 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
.setLinkType(LinkTargetType.OBJC_FULLY_LINKED_ARCHIVE)
.setLinkStaticness(LinkStaticness.FULLY_STATIC)
.setLibraryIdentifier(libraryIdentifier)
- .addVariablesExtension(getVariablesExtension(objcProvider))
+ .addVariablesExtension(extension)
.setFeatureConfiguration(getFeatureConfiguration(ruleContext))
.build();
ruleContext.registerAction(fullyLinkAction);
@@ -136,12 +165,61 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
J2ObjcEntryClassProvider j2ObjcEntryClassProvider,
ExtraLinkArgs extraLinkArgs,
Iterable<Artifact> extraLinkInputs,
- DsymOutputType dsymOutputType) {
- // TODO(b/29582284): Implement the link action in the objc crosstool.
- throw new UnsupportedOperationException();
+ DsymOutputType dsymOutputType) throws InterruptedException {
+ Iterable<Artifact> prunedJ2ObjcArchives =
+ computeAndStripPrunedJ2ObjcArchives(
+ j2ObjcEntryClassProvider, j2ObjcMappingFileProvider, objcProvider);
+ ImmutableList<Artifact> bazelBuiltLibraries =
+ Iterables.isEmpty(prunedJ2ObjcArchives)
+ ? objcProvider.getObjcLibraries()
+ : substituteJ2ObjcPrunedLibraries(objcProvider);
+
+ Artifact inputFileList = intermediateArtifacts.linkerObjList();
+ ImmutableSet<Artifact> forceLinkArtifacts = getForceLoadArtifacts(objcProvider);
+
+ Iterable<Artifact> objFiles =
+ Iterables.concat(
+ bazelBuiltLibraries, objcProvider.get(IMPORTED_LIBRARY), objcProvider.getCcLibraries());
+ // Clang loads archives specified in filelists and also specified as -force_load twice,
+ // resulting in duplicate symbol errors unless they are deduped.
+ objFiles = Iterables.filter(objFiles, Predicates.not(Predicates.in(forceLinkArtifacts)));
+
+ registerObjFilelistAction(objFiles, inputFileList);
+
+ ObjcVariablesExtension extension = new ObjcVariablesExtension.Builder()
+ .setRuleContext(ruleContext)
+ .setObjcProvider(objcProvider)
+ .setConfiguration(ruleContext.getConfiguration())
+ .setIntermediateArtifacts(intermediateArtifacts)
+ .setFrameworkNames(frameworkNames(objcProvider))
+ .setLibraryNames(libraryNames(objcProvider))
+ .setForceLoadArtifacts(getForceLoadArtifacts(objcProvider))
+ .setAttributeLinkopts(attributes.linkopts())
+ .addVariableCategory(VariableCategory.EXECUTABLE_LINKING_VARIABLES)
+ .build();
+
+ Artifact binaryToLink = getBinaryToLink();
+ CppLinkAction executableLinkAction =
+ new CppLinkActionBuilder(ruleContext, binaryToLink)
+ .setMnemonic("ObjcLink")
+ .addActionInputs(bazelBuiltLibraries)
+ .addActionInputs(objcProvider.getCcLibraries())
+ .addTransitiveActionInputs(objcProvider.get(IMPORTED_LIBRARY))
+ .addTransitiveActionInputs(objcProvider.get(STATIC_FRAMEWORK_FILE))
+ .addTransitiveActionInputs(objcProvider.get(DYNAMIC_FRAMEWORK_FILE))
+ .addActionInputs(prunedJ2ObjcArchives)
+ .addActionInput(inputFileList)
+ .setLinkType(LinkTargetType.OBJC_EXECUTABLE)
+ .setLinkStaticness(LinkStaticness.FULLY_STATIC)
+ .addVariablesExtension(extension)
+ .setFeatureConfiguration(getFeatureConfiguration(ruleContext))
+ .build();
+ ruleContext.registerAction(executableLinkAction);
+
+ return this;
}
- private CcLibraryHelper createCcLibraryHelper(ObjcCommon common) throws InterruptedException {
+ private CcLibraryHelper createCcLibraryHelper(ObjcCommon common, VariablesExtension extension) {
PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);
Collection<Artifact> arcSources = Sets.newHashSet(compilationArtifacts.getSrcs());
Collection<Artifact> nonArcSources = Sets.newHashSet(compilationArtifacts.getNonArcSrcs());
@@ -170,7 +248,7 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
.addCopts(ruleContext.getFragment(ObjcConfiguration.class).getCoptsForCompilationMode())
.addSystemIncludeDirs(common.getObjcProvider().get(INCLUDE_SYSTEM))
.setCppModuleMap(intermediateArtifacts.moduleMap())
- .addVariableExtension(getVariablesExtension(common.getObjcProvider()));
+ .addVariableExtension(extension);
}
private static FeatureConfiguration getFeatureConfiguration(RuleContext ruleContext) {
@@ -192,7 +270,7 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
.add(CppRuleClasses.COMPILE_ACTION_FLAGS_IN_FLAG_SET)
.add(CppRuleClasses.DEPENDENCY_FILE)
.add(CppRuleClasses.INCLUDE_PATHS);
-
+
if (ruleContext.getConfiguration().getFragment(ObjcConfiguration.class).moduleMapsEnabled()) {
activatedCrosstoolSelectables.add(OBJC_MODULE_FEATURE_NAME);
}
@@ -207,17 +285,6 @@ public class CrosstoolCompilationSupport extends CompilationSupport {
return toolchain.getFeatures().getFeatureConfiguration(activatedCrosstoolSelectables.build());
}
- private VariablesExtension getVariablesExtension(ObjcProvider objcProvider)
- throws InterruptedException {
- return new ObjcVariablesExtension(
- ruleContext,
- objcProvider,
- compilationArtifacts,
- ruleContext.getImplicitOutputArtifact(CompilationSupport.FULLY_LINKED_LIB),
- intermediateArtifacts,
- ruleContext.getConfiguration());
- }
-
private static ImmutableList<Artifact> getObjFiles(
CompilationArtifacts compilationArtifacts, IntermediateArtifacts intermediateArtifacts) {
ImmutableList.Builder<Artifact> result = new ImmutableList.Builder<>();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java
index f7fdcdfb62..4658c5bd15 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/LegacyCompilationSupport.java
@@ -14,22 +14,17 @@
package com.google.devtools.build.lib.rules.objc;
-import static com.google.devtools.build.lib.rules.cpp.Link.LINK_LIBRARY_FILETYPES;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DEFINE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.DYNAMIC_FRAMEWORK_FILE;
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.Flag.USES_CPP;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE_SYSTEM;
-import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINK_INPUTS;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MODULE_MAP;
-import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB;
-import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_FILE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.CLANG;
@@ -42,24 +37,20 @@ import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PRECOMPIL
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SRCS_TYPE;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.STRIP;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SWIFT;
-import static java.nio.charset.StandardCharsets.ISO_8859_1;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
-import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.CommandLine;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
-import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate.OutputPathMapper;
@@ -77,9 +68,7 @@ import com.google.devtools.build.lib.rules.cpp.CppModuleMap;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
/**
* Constructs command lines for objc compilation, archiving, and linking. Uses hard-coded
@@ -89,17 +78,6 @@ import java.util.Set;
*/
public class LegacyCompilationSupport extends CompilationSupport {
- private static final String FRAMEWORK_SUFFIX = ".framework";
-
- /** Selects cc libraries that have alwayslink=1. */
- private static final Predicate<Artifact> ALWAYS_LINKED_CC_LIBRARY =
- new Predicate<Artifact>() {
- @Override
- public boolean apply(Artifact input) {
- return LINK_LIBRARY_FILETYPES.matches(input.getFilename());
- }
- };
-
/**
* A mapper that maps input ObjC source {@link Artifact.TreeFileArtifact}s to output object file
* {@link Artifact.TreeFileArtifact}s.
@@ -798,12 +776,9 @@ public class LegacyCompilationSupport extends CompilationSupport {
dsymBundleZip = Optional.absent();
}
- Iterable<Artifact> prunedJ2ObjcArchives = ImmutableList.<Artifact>of();
- if (stripJ2ObjcDeadCode(j2ObjcEntryClassProvider)) {
- registerJ2ObjcDeadCodeRemovalActions(objcProvider, j2ObjcMappingFileProvider,
- j2ObjcEntryClassProvider);
- prunedJ2ObjcArchives = j2objcPrunedLibraries(objcProvider);
- }
+ Iterable<Artifact> prunedJ2ObjcArchives =
+ computeAndStripPrunedJ2ObjcArchives(
+ j2ObjcEntryClassProvider, j2ObjcMappingFileProvider, objcProvider);
if (objcConfiguration.generateLinkmap()) {
linkmap = Optional.of(intermediateArtifacts.linkmap());
@@ -821,15 +796,6 @@ public class LegacyCompilationSupport extends CompilationSupport {
return this;
}
- private boolean stripJ2ObjcDeadCode(J2ObjcEntryClassProvider j2ObjcEntryClassProvider) {
- J2ObjcConfiguration j2objcConfiguration =
- buildConfiguration.getFragment(J2ObjcConfiguration.class);
- // Only perform J2ObjC dead code stripping if flag --j2objc_dead_code_removal is specified and
- // users have specified entry classes.
- return j2objcConfiguration.removeDeadCode()
- && !j2ObjcEntryClassProvider.getEntryClasses().isEmpty();
- }
-
private boolean isDynamicLib(CommandLine commandLine) {
return Iterables.contains(commandLine.arguments(), "-dynamiclib");
}
@@ -841,15 +807,7 @@ public class LegacyCompilationSupport extends CompilationSupport {
Optional<Artifact> dsymBundleZip,
Iterable<Artifact> prunedJ2ObjcArchives,
Optional<Artifact> linkmap) {
- // When compilation_mode=opt and objc_enable_binary_stripping are specified, the unstripped
- // binary containing debug symbols is generated by the linker, which also needs the debug
- // symbols for dead-code removal. The binary is also used to generate dSYM bundle if
- // --apple_generate_dsym is specified. A symbol strip action is later registered to strip
- // the symbol table from the unstripped binary.
- Artifact binaryToLink =
- objcConfiguration.shouldStripBinary()
- ? intermediateArtifacts.unstrippedSingleArchitectureBinary()
- : intermediateArtifacts.strippedSingleArchitectureBinary();
+ Artifact binaryToLink = getBinaryToLink();
ImmutableList<Artifact> objcLibraries = objcProvider.getObjcLibraries();
ImmutableList<Artifact> ccLibraries = objcProvider.getCcLibraries();
@@ -912,14 +870,6 @@ public class LegacyCompilationSupport extends CompilationSupport {
}
}
- private ImmutableList<Artifact> j2objcPrunedLibraries(ObjcProvider objcProvider) {
- ImmutableList.Builder<Artifact> j2objcPrunedLibraryBuilder = ImmutableList.builder();
- for (Artifact j2objcLibrary : objcProvider.get(ObjcProvider.J2OBJC_LIBRARY)) {
- j2objcPrunedLibraryBuilder.add(intermediateArtifacts.j2objcPrunedArchive(j2objcLibrary));
- }
- return j2objcPrunedLibraryBuilder.build();
- }
-
private static CommandLine symbolStripCommandLine(
Iterable<String> extraFlags, Artifact unstrippedArtifact, Artifact strippedArtifact) {
return CustomCommandLine.builder()
@@ -930,26 +880,6 @@ public class LegacyCompilationSupport extends CompilationSupport {
.build();
}
- /**
- * Returns a nested set of Bazel-built ObjC libraries with all unpruned J2ObjC libraries
- * substituted with pruned ones.
- */
- private ImmutableList<Artifact> substituteJ2ObjcPrunedLibraries(ObjcProvider objcProvider) {
- ImmutableList.Builder<Artifact> libraries = new ImmutableList.Builder<>();
-
- Set<Artifact> unprunedJ2ObjcLibs = objcProvider.get(ObjcProvider.J2OBJC_LIBRARY).toSet();
- for (Artifact library : objcProvider.getObjcLibraries()) {
- // If we match an unpruned J2ObjC library, add the pruned version of the J2ObjC static library
- // instead.
- if (unprunedJ2ObjcLibs.contains(library)) {
- libraries.add(intermediateArtifacts.j2objcPrunedArchive(library));
- } else {
- libraries.add(library);
- }
- }
- return libraries.build();
- }
-
private CommandLine linkCommandLine(
ExtraLinkArgs extraLinkArgs,
ObjcProvider objcProvider,
@@ -1103,104 +1033,6 @@ public class LegacyCompilationSupport extends CompilationSupport {
}
}
- private Iterable<String> libraryNames(ObjcProvider objcProvider) {
- ImmutableList.Builder<String> args = new ImmutableList.Builder<>();
- for (String dylib : objcProvider.get(SDK_DYLIB)) {
- if (dylib.startsWith("lib")) {
- // remove lib prefix if it exists which is standard
- // for libraries (libxml.dylib -> -lxml).
- dylib = dylib.substring(3);
- }
- args.add(dylib);
- }
- return args.build();
- }
-
- /**
- * All framework names to pass to the linker using {@code -framework} flags. For a framework in
- * the directory foo/bar.framework, the name is "bar". Each framework is found without using the
- * full path by means of the framework search paths. The search paths are added by
- * {@link #commonLinkAndCompileFlagsForClang(ObjcProvider, ObjcConfiguration,
- * AppleConfiguration)}).
- *
- * <p>It's awful that we can't pass the full path to the framework and avoid framework search
- * paths, but this is imposed on us by clang. clang does not support passing the full path to the
- * framework, so Bazel cannot do it either.
- */
- private Iterable<String> frameworkNames(ObjcProvider provider) {
- List<String> names = new ArrayList<>();
- Iterables.addAll(names, SdkFramework.names(provider.get(SDK_FRAMEWORK)));
- for (PathFragment frameworkDir : provider.get(FRAMEWORK_DIR)) {
- String segment = frameworkDir.getBaseName();
- Preconditions.checkState(segment.endsWith(FRAMEWORK_SUFFIX),
- "expect %s to end with %s, but it does not", segment, FRAMEWORK_SUFFIX);
- names.add(segment.substring(0, segment.length() - FRAMEWORK_SUFFIX.length()));
- }
- return names;
- }
-
- private void registerJ2ObjcDeadCodeRemovalActions(ObjcProvider objcProvider,
- J2ObjcMappingFileProvider j2ObjcMappingFileProvider,
- J2ObjcEntryClassProvider j2ObjcEntryClassProvider) {
- NestedSet<String> entryClasses = j2ObjcEntryClassProvider.getEntryClasses();
- Artifact pruner = ruleContext.getPrerequisiteArtifact("$j2objc_dead_code_pruner", Mode.HOST);
- NestedSet<Artifact> j2ObjcDependencyMappingFiles =
- j2ObjcMappingFileProvider.getDependencyMappingFiles();
- NestedSet<Artifact> j2ObjcHeaderMappingFiles =
- j2ObjcMappingFileProvider.getHeaderMappingFiles();
- NestedSet<Artifact> j2ObjcArchiveSourceMappingFiles =
- j2ObjcMappingFileProvider.getArchiveSourceMappingFiles();
-
- for (Artifact j2objcArchive : objcProvider.get(ObjcProvider.J2OBJC_LIBRARY)) {
- PathFragment paramFilePath = FileSystemUtils.replaceExtension(
- j2objcArchive.getOwner().toPathFragment(), ".param.j2objc");
- Artifact paramFile = ruleContext.getUniqueDirectoryArtifact(
- "_j2objc_pruned",
- paramFilePath,
- ruleContext.getBinOrGenfilesDirectory());
- Artifact prunedJ2ObjcArchive = intermediateArtifacts.j2objcPrunedArchive(j2objcArchive);
- Artifact dummyArchive = Iterables.getOnlyElement(
- ruleContext.getPrerequisite("$dummy_lib", Mode.TARGET, ObjcProvider.class)
- .get(LIBRARY));
-
- CustomCommandLine commandLine = CustomCommandLine.builder()
- .addExecPath("--input_archive", j2objcArchive)
- .addExecPath("--output_archive", prunedJ2ObjcArchive)
- .addExecPath("--dummy_archive", dummyArchive)
- .addExecPath("--xcrunwrapper", xcrunwrapper(ruleContext).getExecutable())
- .addJoinExecPaths("--dependency_mapping_files", ",", j2ObjcDependencyMappingFiles)
- .addJoinExecPaths("--header_mapping_files", ",", j2ObjcHeaderMappingFiles)
- .addJoinExecPaths(
- "--archive_source_mapping_files", ",", j2ObjcArchiveSourceMappingFiles)
- .add("--entry_classes").add(Joiner.on(",").join(entryClasses))
- .build();
-
- ruleContext.registerAction(
- new ParameterFileWriteAction(
- ruleContext.getActionOwner(),
- paramFile,
- commandLine,
- ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1));
- ruleContext.registerAction(ObjcRuleClasses.spawnAppleEnvActionBuilder(
- appleConfiguration, appleConfiguration.getSingleArchPlatform())
- .setMnemonic("DummyPruner")
- .setExecutable(pruner)
- .addInput(dummyArchive)
- .addInput(pruner)
- .addInput(paramFile)
- .addInput(j2objcArchive)
- .addInput(xcrunwrapper(ruleContext).getExecutable())
- .addTransitiveInputs(j2ObjcDependencyMappingFiles)
- .addTransitiveInputs(j2ObjcHeaderMappingFiles)
- .addTransitiveInputs(j2ObjcArchiveSourceMappingFiles)
- .setCommandLine(CustomCommandLine.builder()
- .addPaths("@%s", paramFile.getExecPath())
- .build())
- .addOutput(prunedJ2ObjcArchive)
- .build(ruleContext));
- }
- }
-
private CompilationSupport registerDsymActions(DsymOutputType dsymOutputType) {
Artifact tempDsymBundleZip = intermediateArtifacts.tempDsymBundleZip(dsymOutputType);
Artifact linkedBinary =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
index e14be86eba..851af8d32e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcVariablesExtension.java
@@ -15,17 +15,22 @@
package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKOPT;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
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;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.Platform;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StringSequence;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension;
+import java.util.Set;
/** Build variable extensions for templating a toolchain for objc builds. */
class ObjcVariablesExtension implements VariablesExtension {
@@ -43,22 +48,41 @@ class ObjcVariablesExtension implements VariablesExtension {
static final String CC_LIBRARY_EXEC_PATHS_VARIABLE_NAME = "cc_library_exec_paths";
static final String IMPORTED_LIBRARY_EXEC_PATHS_VARIABLE_NAME = "imported_library_exec_paths";
+ // executable linking variables
+ static final String FRAMEWORK_NAMES_VARIABLE_NAME = "framework_names";
+ static final String WEAK_FRAMEWORK_NAMES_VARIABLE_NAME = "weak_framework_names";
+ static final String LIBRARY_NAMES_VARIABLE_NAME = "library_names";
+ static final String FILELIST_VARIABLE_NAME = "filelist";
+ static final String LINKED_BINARY_VARIABLE_NAME = "linked_binary";
+ static final String FORCE_LOAD_EXEC_PATHS_VARIABLE_NAME = "force_load_exec_paths";
+ static final String DEP_LINKOPTS_VARIABLE_NAME = "dep_linkopts";
+ static final String ATTR_LINKOPTS_VARIABLE_NAME = "attr_linkopts";
+
private final RuleContext ruleContext;
private final ObjcProvider objcProvider;
private final CompilationArtifacts compilationArtifacts;
private final Artifact fullyLinkArchive;
private final IntermediateArtifacts intermediateArtifacts;
-
private final BuildConfiguration buildConfiguration;
private final AppleConfiguration appleConfiguration;
+ private final Set<String> frameworkNames;
+ private final ImmutableList<String> libraryNames;
+ private final ImmutableSet<Artifact> forceLoadArtifacts;
+ private final NestedSet<String> attributeLinkopts;
+ private final ImmutableSet<VariableCategory> activeVariableCategories;
- public ObjcVariablesExtension(
+ private ObjcVariablesExtension(
RuleContext ruleContext,
ObjcProvider objcProvider,
CompilationArtifacts compilationArtifacts,
Artifact fullyLinkArchive,
IntermediateArtifacts intermediateArtifacts,
- BuildConfiguration buildConfiguration) {
+ BuildConfiguration buildConfiguration,
+ Set<String> frameworkNames,
+ ImmutableList<String> libraryNames,
+ ImmutableSet<Artifact> forceLoadArtifacts,
+ NestedSet<String> attributeLinkopts,
+ ImmutableSet<VariableCategory> activeVariableCategories) {
this.ruleContext = ruleContext;
this.objcProvider = objcProvider;
this.compilationArtifacts = compilationArtifacts;
@@ -66,6 +90,16 @@ class ObjcVariablesExtension implements VariablesExtension {
this.intermediateArtifacts = intermediateArtifacts;
this.buildConfiguration = buildConfiguration;
this.appleConfiguration = buildConfiguration.getFragment(AppleConfiguration.class);
+ this.frameworkNames = frameworkNames;
+ this.libraryNames = libraryNames;
+ this.forceLoadArtifacts = forceLoadArtifacts;
+ this.attributeLinkopts = attributeLinkopts;
+ this.activeVariableCategories = activeVariableCategories;
+ }
+
+ /** Type of build variable that can optionally exported by this extension. */
+ public enum VariableCategory {
+ ARCHIVE_VARIABLES, FULLY_LINK_VARIABLES, EXECUTABLE_LINKING_VARIABLES;
}
@Override
@@ -74,10 +108,15 @@ class ObjcVariablesExtension implements VariablesExtension {
addFrameworkVariables(builder);
addArchVariables(builder);
addModuleMapVariables(builder);
- if (compilationArtifacts.getArchive().isPresent()) {
+ if (activeVariableCategories.contains(VariableCategory.ARCHIVE_VARIABLES)) {
addArchiveVariables(builder);
}
- addFullyLinkArchiveVariables(builder);
+ if (activeVariableCategories.contains(VariableCategory.FULLY_LINK_VARIABLES)) {
+ addFullyLinkArchiveVariables(builder);
+ }
+ if (activeVariableCategories.contains(VariableCategory.EXECUTABLE_LINKING_VARIABLES)) {
+ addExecutableLinkVariables(builder);
+ }
}
private void addPchVariables(CcToolchainFeatures.Variables.Builder builder) {
@@ -138,4 +177,144 @@ class ObjcVariablesExtension implements VariablesExtension {
IMPORTED_LIBRARY_EXEC_PATHS_VARIABLE_NAME,
ImmutableList.copyOf(Artifact.toExecPaths(objcProvider.get(IMPORTED_LIBRARY))));
}
+
+ private void addExecutableLinkVariables(CcToolchainFeatures.Variables.Builder builder) {
+ builder.addSequenceVariable(FRAMEWORK_NAMES_VARIABLE_NAME, frameworkNames);
+ builder.addSequenceVariable(
+ WEAK_FRAMEWORK_NAMES_VARIABLE_NAME,
+ SdkFramework.names(objcProvider.get(ObjcProvider.WEAK_SDK_FRAMEWORK)));
+ builder.addSequenceVariable(LIBRARY_NAMES_VARIABLE_NAME, libraryNames);
+ builder.addVariable(
+ FILELIST_VARIABLE_NAME, intermediateArtifacts.linkerObjList().getExecPathString());
+ builder.addVariable(
+ LINKED_BINARY_VARIABLE_NAME,
+ ruleContext.getFragment(ObjcConfiguration.class).shouldStripBinary()
+ ? intermediateArtifacts.unstrippedSingleArchitectureBinary().getExecPathString()
+ : intermediateArtifacts.strippedSingleArchitectureBinary().getExecPathString());
+
+ builder.addSequenceVariable(
+ FORCE_LOAD_EXEC_PATHS_VARIABLE_NAME,
+ Artifact.toExecPaths(forceLoadArtifacts));
+ builder.addSequenceVariable(DEP_LINKOPTS_VARIABLE_NAME, objcProvider.get(LINKOPT));
+ builder.addSequenceVariable(ATTR_LINKOPTS_VARIABLE_NAME, attributeLinkopts);
+ }
+
+ /** A Builder for {@link ObjcVariablesExtension}. */
+ static class Builder {
+ private RuleContext ruleContext;
+ private ObjcProvider objcProvider;
+ private CompilationArtifacts compilationArtifacts;
+ private Artifact fullyLinkArchive;
+ private IntermediateArtifacts intermediateArtifacts;
+ private BuildConfiguration buildConfiguration;
+ private Set<String> frameworkNames;
+ private ImmutableSet<Artifact> forceLoadArtifacts;
+ private ImmutableList<String> libraryNames;
+ private NestedSet<String> attributeLinkopts;
+
+ private final ImmutableSet.Builder<VariableCategory> activeVariableCategoriesBuilder =
+ ImmutableSet.builder();
+
+ /** Sets the {@link RuleContext} for this extension. */
+ public Builder setRuleContext(RuleContext ruleContext) {
+ this.ruleContext = Preconditions.checkNotNull(ruleContext);
+ return this;
+ }
+
+ /** Sets the {@link ObjcProvider} for this extension. */
+ public Builder setObjcProvider(ObjcProvider objcProvider) {
+ this.objcProvider = Preconditions.checkNotNull(objcProvider);
+ return this;
+ }
+
+ /** Sets the {@link CompilationArtifacts} for this extension. */
+ public Builder setCompilationArtifacts(CompilationArtifacts compilationArtifacts) {
+ this.compilationArtifacts = Preconditions.checkNotNull(compilationArtifacts);
+ return this;
+ }
+
+ /** Sets the output of the fully link action. */
+ public Builder setFullyLinkArchive(Artifact fullyLinkArchive) {
+ this.fullyLinkArchive = Preconditions.checkNotNull(fullyLinkArchive);
+ return this;
+ }
+
+ /** Sets the {@link IntermediateArtifacts} for this extension. */
+ public Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
+ this.intermediateArtifacts = Preconditions.checkNotNull(intermediateArtifacts);
+ return this;
+ }
+
+ /** Sets the configuration for this extension. */
+ public Builder setConfiguration(BuildConfiguration buildConfiguration) {
+ this.buildConfiguration = Preconditions.checkNotNull(buildConfiguration);
+ return this;
+ }
+
+ /** Sets the framework names to be passed to the linker using {@code -framework}. */
+ public Builder setFrameworkNames(Set<String> frameworkNames) {
+ this.frameworkNames = Preconditions.checkNotNull(frameworkNames);
+ return this;
+ }
+
+ /** Sets binary input files to be passed to the linker with "-l" flags. */
+ public Builder setLibraryNames(ImmutableList<String> libraryNames) {
+ this.libraryNames = Preconditions.checkNotNull(libraryNames);
+ return this;
+ }
+
+ /** Sets artifacts to be passed to the linker with {@code -force_load}. */
+ public Builder setForceLoadArtifacts(ImmutableSet<Artifact> forceLoadArtifacts) {
+ this.forceLoadArtifacts = Preconditions.checkNotNull(forceLoadArtifacts);
+ return this;
+ }
+
+ /** Sets linkopts arising from rule attributes. */
+ public Builder setAttributeLinkopts(NestedSet<String> attributeLinkopts) {
+ this.attributeLinkopts = Preconditions.checkNotNull(attributeLinkopts);
+ return this;
+ }
+
+ /** Sets the given {@link VariableCategory} as active for this extension. */
+ public Builder addVariableCategory(VariableCategory variableCategory) {
+ this.activeVariableCategoriesBuilder.add(Preconditions.checkNotNull(variableCategory));
+ return this;
+ }
+
+ public ObjcVariablesExtension build() {
+
+ ImmutableSet<VariableCategory> activeVariableCategories =
+ activeVariableCategoriesBuilder.build();
+
+ Preconditions.checkNotNull(ruleContext, "missing RuleContext");
+ Preconditions.checkNotNull(objcProvider, "missing ObjcProvider");
+ Preconditions.checkNotNull(buildConfiguration, "missing BuildConfiguration");
+ Preconditions.checkNotNull(intermediateArtifacts, "missing IntermediateArtifacts");
+ if (activeVariableCategories.contains(VariableCategory.ARCHIVE_VARIABLES)) {
+ Preconditions.checkNotNull(compilationArtifacts, "missing CompilationArtifacts");
+ }
+ if (activeVariableCategories.contains(VariableCategory.FULLY_LINK_VARIABLES)) {
+ Preconditions.checkNotNull(fullyLinkArchive, "missing fully-link archive");
+ }
+ if (activeVariableCategories.contains(VariableCategory.EXECUTABLE_LINKING_VARIABLES)) {
+ Preconditions.checkNotNull(frameworkNames, "missing framework names");
+ Preconditions.checkNotNull(libraryNames, "missing library names");
+ Preconditions.checkNotNull(forceLoadArtifacts, "missing force-load artifacts");
+ Preconditions.checkNotNull(attributeLinkopts, "missing attribute linkopts");
+ }
+
+ return new ObjcVariablesExtension(
+ ruleContext,
+ objcProvider,
+ compilationArtifacts,
+ fullyLinkArchive,
+ intermediateArtifacts,
+ buildConfiguration,
+ frameworkNames,
+ libraryNames,
+ forceLoadArtifacts,
+ attributeLinkopts,
+ activeVariableCategories);
+ }
+ }
}