aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/objc
diff options
context:
space:
mode:
authorGravatar Matthew DeVore <matvore@google.com>2015-02-06 18:26:23 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-02-06 18:26:23 +0000
commit25bdc33f14a7781f5ffeca018f8dc0f5575f0979 (patch)
treeb30c9ffd3a38f3602ed9913bd3c3d558ba8cb8dd /src/main/java/com/google/devtools/build/lib/rules/objc
parent50a1194557959501ef36a44eaf782be6acb531f1 (diff)
Implement ios_extension_binary rule, which is similar to objc_binary, but only links and does not bundle, and creates a binary for an iOS app extension.
ios_extension_binary is minimialistic, not allow infoplist, entitlements, and other attributes, and generate different artifacts, which how objc_binary will also work for iOS applications in the new world when we have ios_application. -- MOS_MIGRATED_REVID=85728076
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/objc')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java181
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinary.java28
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryRule.java56
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBinary.java129
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcXcodeprojRule.java1
5 files changed, 274 insertions, 121 deletions
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
new file mode 100644
index 0000000000..2c0d336f56
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java
@@ -0,0 +1,181 @@
+// Copyright 2014 Google Inc. 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.IMPORTED_LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.rules.objc.ApplicationSupport.LinkedBinary;
+import com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraLinkArgs;
+import com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraLinkInputs;
+import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes;
+import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes;
+
+/**
+ * Implementation for rules that link binaries.
+ */
+abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory {
+ /**
+ * Indicates whether this binary generates an application bundle. If so, it causes the
+ * {@code infoplist} attribute to be read and a bundle to be added to the files-to-build.
+ */
+ enum HasApplicationSupport {
+ YES, NO;
+ }
+
+ private final HasApplicationSupport hasApplicationSupport;
+ private final ExtraLinkArgs extraLinkArgs;
+ private final XcodeProductType productType;
+
+ protected BinaryLinkingTargetFactory(HasApplicationSupport hasApplicationSupport,
+ ExtraLinkArgs extraLinkArgs, XcodeProductType productType) {
+ this.hasApplicationSupport = hasApplicationSupport;
+ this.extraLinkArgs = extraLinkArgs;
+ this.productType = productType;
+ }
+
+ @VisibleForTesting
+ static final String REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE =
+ "At least one library dependency or source file is required.";
+
+ @Override
+ public final ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
+ ObjcCommon common = common(ruleContext);
+ OptionsProvider optionsProvider = optionsProvider(ruleContext);
+
+ ObjcProvider objcProvider = common.getObjcProvider();
+ if (!hasLibraryOrSources(objcProvider)) {
+ ruleContext.ruleError(REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE);
+ return null;
+ }
+
+ XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder();
+ NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder()
+ .add(ObjcRuleClasses.intermediateArtifacts(ruleContext).singleArchitectureBinary());
+
+ new CompilationSupport(ruleContext)
+ .registerJ2ObjcCompileAndArchiveActions(optionsProvider, common.getObjcProvider())
+ .registerCompileAndArchiveActions(common, optionsProvider)
+ .addXcodeSettings(xcodeProviderBuilder, common, optionsProvider)
+ .registerLinkActions(common.getObjcProvider(), extraLinkArgs, new ExtraLinkInputs())
+ .validateAttributes();
+
+ Optional<XcTestAppProvider> xcTestAppProvider;
+ switch (hasApplicationSupport) {
+ case YES:
+ // TODO(bazel-team): Remove once all bundle users are migrated to ios_application.
+ ApplicationSupport applicationSupport = new ApplicationSupport(
+ ruleContext, common.getObjcProvider(), optionsProvider,
+ LinkedBinary.LOCAL_AND_DEPENDENCIES);
+ applicationSupport
+ .registerActions()
+ .addXcodeSettings(xcodeProviderBuilder)
+ .addFilesToBuild(filesToBuild)
+ .validateAttributes();
+ xcTestAppProvider = Optional.of(applicationSupport.xcTestAppProvider());
+ break;
+ case NO:
+ xcTestAppProvider = Optional.absent();
+ break;
+ default:
+ throw new AssertionError();
+ }
+
+ new ResourceSupport(ruleContext)
+ .registerActions(common.getStoryboards())
+ .validateAttributes()
+ .addXcodeSettings(xcodeProviderBuilder);
+
+ XcodeSupport xcodeSupport = new XcodeSupport(ruleContext)
+ // TODO(bazel-team): Use LIBRARY_STATIC as parameter instead of APPLICATION once objc_binary
+ // no longer creates an application bundle
+ .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), productType)
+ .addDependencies(xcodeProviderBuilder)
+ .addFilesToBuild(filesToBuild);
+ XcodeProvider xcodeProvider = xcodeProviderBuilder.build();
+ xcodeSupport.registerActions(xcodeProvider);
+
+ // TODO(bazel-team): Stop exporting an XcTestAppProvider once objc_binary no longer creates an
+ // application bundle.
+ return common.configuredTarget(
+ filesToBuild.build(),
+ Optional.of(xcodeProvider),
+ Optional.<ObjcProvider>absent(),
+ xcTestAppProvider,
+ Optional.<J2ObjcSrcsProvider>absent());
+ }
+
+ private OptionsProvider optionsProvider(RuleContext ruleContext) {
+ OptionsProvider.Builder provider = new OptionsProvider.Builder()
+ .addCopts(ruleContext.getTokenizedStringListAttr("copts"))
+ .addTransitive(Optional.fromNullable(
+ ruleContext.getPrerequisite("options", Mode.TARGET, OptionsProvider.class)));
+ if (hasApplicationSupport == HasApplicationSupport.YES) {
+ provider
+ .addInfoplists(ruleContext.getPrerequisiteArtifacts("infoplist", Mode.TARGET).list());
+ }
+ return provider.build();
+ }
+
+ private boolean hasLibraryOrSources(ObjcProvider objcProvider) {
+ return !Iterables.isEmpty(objcProvider.get(LIBRARY)) // Includes sources from this target.
+ || !Iterables.isEmpty(objcProvider.get(IMPORTED_LIBRARY));
+ }
+
+ private ObjcCommon common(RuleContext ruleContext) {
+ IntermediateArtifacts intermediateArtifacts =
+ ObjcRuleClasses.intermediateArtifacts(ruleContext);
+ CompilationArtifacts compilationArtifacts =
+ CompilationSupport.compilationArtifacts(ruleContext);
+
+ return new ObjcCommon.Builder(ruleContext)
+ .setCompilationAttributes(new CompilationAttributes(ruleContext))
+ .setResourceAttributes(new ResourceAttributes(ruleContext))
+ .setCompilationArtifacts(compilationArtifacts)
+ .addDepObjcProviders(ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class))
+ .addDepObjcProviders(
+ ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class))
+ .addNonPropagatedDepObjcProviders(
+ ruleContext.getPrerequisites("non_propagated_deps", Mode.TARGET, ObjcProvider.class))
+ .setIntermediateArtifacts(intermediateArtifacts)
+ .setAlwayslink(false)
+ .addExtraImportLibraries(j2ObjcLibraries(ruleContext))
+ .setLinkedBinary(intermediateArtifacts.singleArchitectureBinary())
+ .build();
+ }
+
+ private Iterable<Artifact> j2ObjcLibraries(RuleContext ruleContext) {
+ J2ObjcSrcsProvider j2ObjcSrcsProvider = ObjcRuleClasses.j2ObjcSrcsProvider(ruleContext);
+ ImmutableList.Builder<Artifact> j2objcLibraries = ImmutableList.builder();
+
+ // TODO(bazel-team): Refactor the code to stop flattening the nested set here.
+ for (J2ObjcSource j2ObjcSource : j2ObjcSrcsProvider.getSrcs()) {
+ j2objcLibraries.add(
+ ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext, j2ObjcSource).archive());
+ }
+
+ return j2objcLibraries.build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinary.java
new file mode 100644
index 0000000000..c930a84005
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinary.java
@@ -0,0 +1,28 @@
+// Copyright 2015 Google Inc. 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 com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraLinkArgs;
+
+/**
+ * Implementation for the "ios_extension_binary" rule.
+ */
+public class IosExtensionBinary extends BinaryLinkingTargetFactory {
+ public IosExtensionBinary() {
+ super(HasApplicationSupport.NO,
+ new ExtraLinkArgs("-e", "_NSExtensionMain", "-fapplication-extension"),
+ XcodeProductType.LIBRARY_STATIC);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryRule.java
new file mode 100644
index 0000000000..716758bb05
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryRule.java
@@ -0,0 +1,56 @@
+// Copyright 2015 Google Inc. 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 com.google.devtools.build.lib.analysis.BlazeRule;
+import com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClass.Builder;
+
+/**
+ * Rule definition for ios_extension_binary.
+ */
+@BlazeRule(name = "ios_extension_binary",
+ factoryClass = IosExtensionBinary.class,
+ ancestors = { ObjcLibraryRule.class })
+public class IosExtensionBinaryRule implements RuleDefinition {
+ @Override
+ public RuleClass build(Builder builder, final RuleDefinitionEnvironment env) {
+ return builder
+ /*<!-- #BLAZE_RULE(ios_extension_binary).IMPLICIT_OUTPUTS -->
+ <ul>
+ <li><code><var>name</var>.xcodeproj/project.pbxproj</code>: An Xcode project file which
+ can be used to develop or build on a Mac.</li>
+ </ul>
+ <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS -->*/
+ .setImplicitOutputsFunction(XcodeSupport.PBXPROJ)
+ .removeAttribute("alwayslink")
+ .build();
+ }
+}
+
+/*<!-- #BLAZE_RULE (NAME = ios_extension_binary, TYPE = BINARY, FAMILY = Objective-C) -->
+
+${ATTRIBUTE_SIGNATURE}
+
+<p>This rule produces a binary for an iOS app extension by linking one or more
+Objective-C libraries.</p>
+
+${IMPLICIT_OUTPUTS}
+
+${ATTRIBUTE_DEFINITION}
+
+<!-- #END_BLAZE_RULE -->*/
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBinary.java
index 52c897fe23..23bd8ea515 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBinary.java
@@ -14,134 +14,21 @@
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.LIBRARY;
-import static com.google.devtools.build.lib.rules.objc.XcodeProductType.APPLICATION;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.analysis.ConfiguredTarget;
-import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
-import com.google.devtools.build.lib.analysis.RuleContext;
-import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
-import com.google.devtools.build.lib.rules.objc.ApplicationSupport.LinkedBinary;
import com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraLinkArgs;
-import com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraLinkInputs;
-import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes;
-import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes;
/**
* Implementation for the "objc_binary" rule.
*/
-public class ObjcBinary implements RuleConfiguredTargetFactory {
-
- @VisibleForTesting
- static final String REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE =
- "At least one library dependency or source file is required.";
-
- @Override
- public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
- ObjcCommon common = common(ruleContext);
- OptionsProvider optionsProvider = optionsProvider(ruleContext);
-
- ObjcProvider objcProvider = common.getObjcProvider();
- if (!hasLibraryOrSources(objcProvider)) {
- ruleContext.ruleError(REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE);
- return null;
- }
-
- XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder();
- NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder();
+public class ObjcBinary extends BinaryLinkingTargetFactory {
+ public ObjcBinary() {
+ super(
+ // TODO(bazel-team): Remove the enum and delete all code depending on YES case once all
+ // bundle users are migrated to ios_application.
+ HasApplicationSupport.YES,
+ new ExtraLinkArgs(),
- new CompilationSupport(ruleContext)
- .registerJ2ObjcCompileAndArchiveActions(optionsProvider, common.getObjcProvider())
- .registerCompileAndArchiveActions(common, optionsProvider)
- .addXcodeSettings(xcodeProviderBuilder, common, optionsProvider)
- .registerLinkActions(common.getObjcProvider(), new ExtraLinkArgs(), new ExtraLinkInputs())
- .validateAttributes();
-
- // TODO(bazel-team): Remove once all bundle users are migrated to ios_application.
- ApplicationSupport applicationSupport = new ApplicationSupport(
- ruleContext, common.getObjcProvider(), optionsProvider, LinkedBinary.LOCAL_AND_DEPENDENCIES)
- .registerActions()
- .addXcodeSettings(xcodeProviderBuilder)
- .addFilesToBuild(filesToBuild)
- .validateAttributes();
-
- new ResourceSupport(ruleContext)
- .registerActions(common.getStoryboards())
- .validateAttributes()
- .addXcodeSettings(xcodeProviderBuilder);
-
- XcodeSupport xcodeSupport = new XcodeSupport(ruleContext)
// TODO(bazel-team): Use LIBRARY_STATIC as parameter instead of APPLICATION once objc_binary
// no longer creates an application bundle
- .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), APPLICATION)
- .addDependencies(xcodeProviderBuilder)
- .addFilesToBuild(filesToBuild);
- XcodeProvider xcodeProvider = xcodeProviderBuilder.build();
- xcodeSupport.registerActions(xcodeProvider);
-
- // TODO(bazel-team): Stop exporting an XcTestAppProvider once objc_binary no longer creates an
- // application bundle.
- return common.configuredTarget(
- filesToBuild.build(),
- Optional.of(xcodeProvider),
- Optional.<ObjcProvider>absent(),
- Optional.of(applicationSupport.xcTestAppProvider()),
- Optional.<J2ObjcSrcsProvider>absent());
- }
-
- private OptionsProvider optionsProvider(RuleContext ruleContext) {
- return new OptionsProvider.Builder()
- .addCopts(ruleContext.getTokenizedStringListAttr("copts"))
- .addInfoplists(ruleContext.getPrerequisiteArtifacts("infoplist", Mode.TARGET).list())
- .addTransitive(Optional.fromNullable(
- ruleContext.getPrerequisite("options", Mode.TARGET, OptionsProvider.class)))
- .build();
- }
-
- private boolean hasLibraryOrSources(ObjcProvider objcProvider) {
- return !Iterables.isEmpty(objcProvider.get(LIBRARY)) // Includes sources from this target.
- || !Iterables.isEmpty(objcProvider.get(IMPORTED_LIBRARY));
- }
-
- private ObjcCommon common(RuleContext ruleContext) {
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
- CompilationArtifacts compilationArtifacts =
- CompilationSupport.compilationArtifacts(ruleContext);
-
- return new ObjcCommon.Builder(ruleContext)
- .setCompilationAttributes(new CompilationAttributes(ruleContext))
- .setResourceAttributes(new ResourceAttributes(ruleContext))
- .setCompilationArtifacts(compilationArtifacts)
- .addDepObjcProviders(ruleContext.getPrerequisites("deps", Mode.TARGET, ObjcProvider.class))
- .addDepObjcProviders(
- ruleContext.getPrerequisites("bundles", Mode.TARGET, ObjcProvider.class))
- .addNonPropagatedDepObjcProviders(
- ruleContext.getPrerequisites("non_propagated_deps", Mode.TARGET, ObjcProvider.class))
- .setIntermediateArtifacts(intermediateArtifacts)
- .setAlwayslink(false)
- .addExtraImportLibraries(j2ObjcLibraries(ruleContext))
- .setLinkedBinary(intermediateArtifacts.singleArchitectureBinary())
- .build();
- }
-
- private Iterable<Artifact> j2ObjcLibraries(RuleContext ruleContext) {
- J2ObjcSrcsProvider j2ObjcSrcsProvider = ObjcRuleClasses.j2ObjcSrcsProvider(ruleContext);
- ImmutableList.Builder<Artifact> j2objcLibraries = ImmutableList.builder();
-
- // TODO(bazel-team): Refactor the code to stop flattening the nested set here.
- for (J2ObjcSource j2ObjcSource : j2ObjcSrcsProvider.getSrcs()) {
- j2objcLibraries.add(
- ObjcRuleClasses.j2objcIntermediateArtifacts(ruleContext, j2ObjcSource).archive());
- }
-
- return j2objcLibraries.build();
+ XcodeProductType.APPLICATION);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcXcodeprojRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcXcodeprojRule.java
index 0a6c4baf97..ecfff3952c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcXcodeprojRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcXcodeprojRule.java
@@ -51,6 +51,7 @@ public class ObjcXcodeprojRule implements RuleDefinition {
.nonEmpty()
.allowedRuleClasses(
"objc_binary",
+ "ios_extension_binary",
"ios_test",
"objc_bundle_library",
"objc_import",