aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Peter Schmitt <schmitt@google.com>2015-03-13 17:01:45 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-03-16 17:34:00 +0000
commit01889715e70b55b9d197e546593878f16cdc0f26 (patch)
treeab7e3350552b5fead62d1abdf473d5882b537271
parent09cff8f0a83d340729a0e61ca482e56614141487 (diff)
Split ios_application configurations based on --ios_multi_cpus.
Using the new flag works only on ios_application and ios_extension targets, resulting in their output binaries being "universal" with all given architectures included. Internally this is achieved by splitting the "binary" dependency (and its transitive dependencies) of ios_{application,extension} to be built in one of the architectures using split transitions. The results are then combined. Since an ios_application may depend on ios_extension, we transition back to the top-level configuration when encoutering such a dependency using the newly introduced TOP_LEVEL transition and then split configurations again. RELNOTES: --ios_multi_cpus allows building fat ios_applications. -- MOS_MIGRATED_REVID=88555540
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/Attribute.java43
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosApplication.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosApplicationRule.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosExtension.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionRule.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/IosTest.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java31
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java36
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java8
16 files changed, 202 insertions, 35 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Attribute.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Attribute.java
new file mode 100644
index 0000000000..95e628d624
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/Attribute.java
@@ -0,0 +1,43 @@
+// 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.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+
+/**
+ * Container for an attribute name and access mode such as are commonly passed to
+ * {@link RuleContext#getPrerequisite(String, Mode)} and related methods.
+ */
+public class Attribute {
+ private final String name;
+ private final Mode accessMode;
+
+ /**
+ * Creates an attribute reference with the given name and access mode.
+ */
+ public Attribute(String name, Mode accessMode) {
+ this.name = name;
+ this.accessMode = accessMode;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Mode getAccessMode() {
+ return accessMode;
+ }
+}
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 4e166eaee8..1710c96149 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
@@ -124,9 +124,9 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory
// TODO(bazel-team): Use LIBRARY_STATIC as parameter instead of APPLICATION once objc_binary
// no longer creates an application bundle
.addXcodeSettings(xcodeProviderBuilder, objcProvider, productType)
- .addDependencies(xcodeProviderBuilder, "bundles")
- .addDependencies(xcodeProviderBuilder, "deps")
- .addDependencies(xcodeProviderBuilder, "non_propagated_deps")
+ .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET))
+ .addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET))
+ .addDependencies(xcodeProviderBuilder, new Attribute("non_propagated_deps", Mode.TARGET))
.addFilesToBuild(filesToBuild);
XcodeProvider xcodeProvider = xcodeProviderBuilder.build();
xcodeSupport.registerActions(xcodeProvider);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplication.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplication.java
index d35bfa0618..72a4046437 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplication.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplication.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.rules.objc;
import com.google.common.base.Optional;
+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.RuleConfiguredTargetBuilder;
@@ -26,9 +27,14 @@ import com.google.devtools.build.xcode.common.Platform;
*/
public class IosApplication extends ReleaseBundlingTargetFactory {
+ private static final ImmutableSet<Attribute> DEPENDENCY_ATTRIBUTES =
+ ImmutableSet.of(
+ new Attribute("binary", Mode.SPLIT),
+ new Attribute("extensions", Mode.TARGET));
+
public IosApplication() {
super(ReleaseBundlingSupport.APP_BUNDLE_DIR_FORMAT, XcodeProductType.APPLICATION,
- ExposeAsNestedBundle.NO);
+ ExposeAsNestedBundle.NO, DEPENDENCY_ATTRIBUTES);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplicationRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplicationRule.java
index 497955ea92..040a81f77f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplicationRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosApplicationRule.java
@@ -18,6 +18,7 @@ import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTran
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.LABEL;
+import static com.google.devtools.build.lib.packages.Type.LABEL_LIST;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.BlazeRule;
@@ -60,6 +61,15 @@ public class IosApplicationRule implements RuleDefinition {
.allowedRuleClasses("objc_binary")
.allowedFileTypes()
.mandatory()
+ .direct_compile_time_input()
+ .cfg(ReleaseBundlingSupport.SPLIT_ARCH_TRANSITION))
+ /* <!-- #BLAZE_RULE(ios_application).ATTRIBUTE(extensions) -->
+ Any extensions to include in the final application.
+ ${SYNOPSIS}
+ <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
+ .add(attr("extensions", LABEL_LIST)
+ .allowedRuleClasses("ios_extension")
+ .allowedFileTypes()
.direct_compile_time_input())
.add(attr("$runner_script_template", LABEL).cfg(HOST)
.value(env.getLabel("//tools/objc:ios_runner.sh.mac_template")))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtension.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtension.java
index 163d133189..fa2e8fbef6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtension.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtension.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.rules.objc;
+import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -24,7 +25,7 @@ public class IosExtension extends ReleaseBundlingTargetFactory {
public IosExtension() {
super(ReleaseBundlingSupport.EXTENSION_BUNDLE_DIR_FORMAT, XcodeProductType.EXTENSION,
- ExposeAsNestedBundle.YES);
+ ExposeAsNestedBundle.YES, ImmutableSet.of(new Attribute("binary", Mode.SPLIT)));
}
protected OptionsProvider optionsProvider(RuleContext ruleContext) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionRule.java
index a3491e0b9d..ca35f478ed 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/IosExtensionRule.java
@@ -56,7 +56,8 @@ public class IosExtensionRule implements RuleDefinition {
.allowedRuleClasses("ios_extension_binary")
.allowedFileTypes()
.mandatory()
- .direct_compile_time_input())
+ .direct_compile_time_input()
+ .cfg(ReleaseBundlingSupport.SPLIT_ARCH_TRANSITION))
.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 1c94e9e14f..b2b836ef60 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
@@ -50,6 +50,9 @@ public abstract class IosTest implements RuleConfiguredTargetFactory {
@VisibleForTesting
public static final String REQUIRES_SOURCE_ERROR =
"ios_test requires at least one source file in srcs or non_arc_srcs";
+ @VisibleForTesting
+ public static final String NO_MULTI_CPUS_ERROR =
+ "ios_test cannot be built for multiple CPUs at the same time";
/**
* Creates a target, including registering actions, just as {@link #create(RuleContext)} does.
@@ -70,6 +73,10 @@ public abstract class IosTest implements RuleConfiguredTargetFactory {
ruleContext.ruleError(REQUIRES_SOURCE_ERROR);
}
+ if (!ObjcRuleClasses.objcConfiguration(ruleContext).getIosMultiCpus().isEmpty()) {
+ ruleContext.ruleError(NO_MULTI_CPUS_ERROR);
+ }
+
XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder();
NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder()
.addTransitive(common.getStoryboards().getOutputZips())
@@ -132,9 +139,9 @@ public abstract class IosTest implements RuleConfiguredTargetFactory {
new XcodeSupport(ruleContext)
.addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), productType)
- .addDependencies(xcodeProviderBuilder, "bundles")
- .addDependencies(xcodeProviderBuilder, "deps")
- .addDependencies(xcodeProviderBuilder, "non_propagated_deps")
+ .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET))
+ .addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET))
+ .addDependencies(xcodeProviderBuilder, new Attribute("non_propagated_deps", Mode.TARGET))
.addFilesToBuild(filesToBuild)
.registerActions(xcodeProviderBuilder.build());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java
index 253fe32814..e25e274674 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java
@@ -58,7 +58,7 @@ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory {
new XcodeSupport(ruleContext)
.addFilesToBuild(filesToBuild)
.addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), BUNDLE)
- .addDependencies(xcodeProviderBuilder, "bundles")
+ .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET))
.registerActions(xcodeProviderBuilder.build());
ObjcProvider nestedBundleProvider = new ObjcProvider.Builder()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
index 2e42ff9bd4..8937340c7c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommandLineOptions.java
@@ -17,9 +17,13 @@ package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.xcode.common.BuildOptionsUtil.DEFAULT_OPTIONS_NAME;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
+import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
import com.google.devtools.common.options.Option;
import java.util.List;
@@ -92,8 +96,28 @@ public class
help = "Enable checking for memory leaks in ios_test targets.")
public boolean runMemleaks;
+ @Option(name = "ios_multi_cpus",
+ converter = CommaSeparatedOptionListConverter.class,
+ defaultValue = "",
+ category = "flags",
+ help = "Comma-separated list of architectures to build an ios_application with. The result "
+ + "is a universal binary containing all specified architectures.")
+ public List<String> iosMultiCpus;
+
+ @Option(name = "ios_split_cpu",
+ defaultValue = "",
+ category = "undocumented",
+ help =
+ "Don't set this value from the command line - it is derived from ios_multi_cpus only.")
+ public String iosSplitCpu;
+
@VisibleForTesting static final String DEFAULT_MINIMUM_IOS = "7.0";
@Override
public void addAllLabels(Multimap<String, Label> labelMap) {}
+
+ @Override
+ public List<SplitTransition<BuildOptions>> getPotentialSplitTransitions() {
+ return ImmutableList.of(ReleaseBundlingSupport.SPLIT_ARCH_TRANSITION);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
index 4f8b3f5f27..e452ddb38c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java
@@ -18,7 +18,10 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.xcode.common.Platform;
@@ -53,6 +56,8 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
private final boolean runMemleaks;
private final List<String> copts;
private final CompilationMode compilationMode;
+ private final List<String> iosMultiCpus;
+ private final String iosSplitCpu;
// We only load this label if coverage mode is enabled. That is know as part of the
// BuildConfiguration. This label needs to be part of a configuration because only configurations
@@ -79,6 +84,8 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
this.copts = ImmutableList.copyOf(objcOptions.copts);
this.compilationMode = Preconditions.checkNotNull(options.compilationMode, "compilationMode");
this.gcovLabel = gcovLabel;
+ this.iosMultiCpus = Preconditions.checkNotNull(objcOptions.iosMultiCpus, "iosMultiCpus");
+ this.iosSplitCpu = Preconditions.checkNotNull(objcOptions.iosSplitCpu, "iosSplitCpu");
}
public String getIosSdkVersion() {
@@ -106,7 +113,7 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
}
public String getIosCpu() {
- return iosCpu;
+ return iosSplitCpu.isEmpty() ? iosCpu : iosSplitCpu;
}
public Platform getPlatform() {
@@ -164,6 +171,14 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
return gcovLabel;
}
+ /**
+ * List of all CPUs that this invocation is being built for. Different from {@link #getIosCpu()}
+ * which is the specific CPU <b>this target</b> is being built for.
+ */
+ public List<String> getIosMultiCpus() {
+ return iosMultiCpus;
+ }
+
@Override
public String getName() {
return "Objective-C";
@@ -173,4 +188,18 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment {
public String cacheKey() {
return iosSdkVersion;
}
+
+ @Nullable
+ @Override
+ public String getOutputDirectoryName() {
+ return !iosSplitCpu.isEmpty() ? "ios-" + iosSplitCpu : null;
+ }
+
+ @Override
+ public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) {
+ if (generateDebugSymbols && !iosMultiCpus.isEmpty()) {
+ reporter.handle(Event.error(
+ "--objc_generate_debug_symbols is not supported when --ios_multi_cpus is set"));
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java
index 616bfc0b9a..631def29c4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcImport.java
@@ -58,7 +58,7 @@ public class ObjcImport implements RuleConfiguredTargetFactory {
new XcodeSupport(ruleContext)
.addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC)
- .addDependencies(xcodeProviderBuilder, "bundles")
+ .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET))
.registerActions(xcodeProviderBuilder.build())
.addFilesToBuild(filesToBuild);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java
index cf4bfcb3ec..2271f4931f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java
@@ -101,9 +101,9 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory {
new XcodeSupport(ruleContext)
.addFilesToBuild(filesToBuild)
.addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC)
- .addDependencies(xcodeProviderBuilder, "bundles")
- .addDependencies(xcodeProviderBuilder, "deps")
- .addDependencies(xcodeProviderBuilder, "non_propagated_deps")
+ .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET))
+ .addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET))
+ .addDependencies(xcodeProviderBuilder, new Attribute("non_propagated_deps", Mode.TARGET))
.registerActions(xcodeProviderBuilder.build());
return common.configuredTarget(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
index 5e28bfb414..d253cf693a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
@@ -384,7 +384,7 @@ public class ObjcRuleClasses {
<!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
.add(attr("bundles", LABEL_LIST)
.direct_compile_time_input()
- .allowedRuleClasses("objc_bundle", "objc_bundle_library", "ios_extension")
+ .allowedRuleClasses("objc_bundle", "objc_bundle_library")
.allowedFileTypes())
.add(attr("$momczip_deploy", LABEL).cfg(HOST)
.value(env.getLabel("//tools/objc:momczip_deploy.jar")))
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 6a6e74a830..67befa23d4 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
@@ -33,9 +33,11 @@ import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.objc.ObjcActionsBuilder.ExtraActoolArgs;
@@ -68,6 +70,35 @@ public final class ReleaseBundlingSupport {
*/
public static final SafeImplicitOutputsFunction IPA = fromTemplates("%{name}.ipa");
+ /**
+ * Transition that when applied to a target generates a configured target for each value in
+ * {@code --ios_multi_cpus}, such that {@code --ios_cpu} is set to a different one of those values
+ * in the configured targets.
+ */
+ public static final SplitTransition<BuildOptions> SPLIT_ARCH_TRANSITION =
+ new SplitTransition<BuildOptions>() {
+ @Override
+ public List<BuildOptions> split(BuildOptions buildOptions) {
+ List<String> iosMultiCpus = buildOptions.get(ObjcCommandLineOptions.class).iosMultiCpus;
+ if (iosMultiCpus.isEmpty()) {
+ return ImmutableList.of();
+ }
+
+ ImmutableList.Builder<BuildOptions> splitBuildOptions = ImmutableList.builder();
+ for (String iosCpu : iosMultiCpus) {
+ BuildOptions splitOptions = buildOptions.clone();
+ splitOptions.get(ObjcCommandLineOptions.class).iosSplitCpu = iosCpu;
+ splitBuildOptions.add(splitOptions);
+ }
+ return splitBuildOptions.build();
+ }
+
+ @Override
+ public boolean defaultsToSelf() {
+ return true;
+ }
+ };
+
@VisibleForTesting
static final String NO_ASSET_CATALOG_ERROR_FORMAT =
"a value was specified (%s), but this app does not have any asset catalogs";
@@ -620,8 +651,13 @@ public final class ReleaseBundlingSupport {
return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
- return ruleContext.getPrerequisite("binary", Mode.TARGET, ObjcProvider.class)
- .get(ObjcProvider.LINKED_BINARY);
+ NestedSetBuilder<Artifact> linkedBinaries = NestedSetBuilder.stableOrder();
+ for (ObjcProvider provider
+ : ruleContext.getPrerequisites("binary", Mode.DONT_CHECK, ObjcProvider.class)) {
+ linkedBinaries.addTransitive(provider.get(ObjcProvider.LINKED_BINARY));
+ }
+
+ return linkedBinaries.build();
}
FilesToRunProvider bundleMergeExecutable() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java
index 4bae44af82..88481393b9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java
@@ -17,9 +17,9 @@ package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MERGE_ZIP;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
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.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -40,19 +40,22 @@ public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTarg
private final String bundleDirFormat;
private final XcodeProductType xcodeProductType;
private final ExposeAsNestedBundle exposeAsNestedBundle;
+ private final ImmutableSet<Attribute> dependencyAttributes;
/**
* @param bundleDirFormat format string representing the bundle's directory with a single
* placeholder for the target name (e.g. {@code "Payload/%s.app"})
* @param exposeAsNestedBundle whether to export an {@link ObjcProvider} with this target as a
- * nested bundle
+ * @param dependencyAttributes all attributes that contain dependencies of this rule. Any
+ * dependency so listed must expose {@link XcodeProvider} and {@link ObjcProvider}.
*/
public ReleaseBundlingTargetFactory(String bundleDirFormat,
XcodeProductType xcodeProductType,
- ExposeAsNestedBundle exposeAsNestedBundle) {
+ ExposeAsNestedBundle exposeAsNestedBundle, ImmutableSet<Attribute> dependencyAttributes) {
this.bundleDirFormat = bundleDirFormat;
this.xcodeProductType = xcodeProductType;
this.exposeAsNestedBundle = exposeAsNestedBundle;
+ this.dependencyAttributes = dependencyAttributes;
}
@Override
@@ -71,14 +74,16 @@ public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTarg
.addFilesToBuild(filesToBuild)
.validateAttributes();
- new XcodeSupport(ruleContext)
+ XcodeSupport xcodeSupport = new XcodeSupport(ruleContext)
.addFilesToBuild(filesToBuild)
- .addXcodeSettings(
- xcodeProviderBuilder, common.getObjcProvider(), xcodeProductType)
- .addDummySource(xcodeProviderBuilder)
- .addDependencies(xcodeProviderBuilder, "binary")
- .registerActions(xcodeProviderBuilder.build());
+ .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), xcodeProductType)
+ .addDummySource(xcodeProviderBuilder);
+ for (Attribute attribute : dependencyAttributes) {
+ xcodeSupport.addDependencies(xcodeProviderBuilder, attribute);
+ }
+
+ xcodeSupport.registerActions(xcodeProviderBuilder.build());
Optional<ObjcProvider> exposedObjcProvider;
if (exposeAsNestedBundle == ExposeAsNestedBundle.YES) {
@@ -112,10 +117,13 @@ public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTarg
ReleaseBundlingSupport releaseBundlingSupport) {}
private ObjcCommon common(RuleContext ruleContext) {
- return new ObjcCommon.Builder(ruleContext)
- .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
- .addDepObjcProviders(
- ruleContext.getPrerequisites("binary", Mode.TARGET, ObjcProvider.class))
- .build();
+ ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext)
+ .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext));
+ for (Attribute attribute : dependencyAttributes) {
+ builder.addDepObjcProviders(
+ ruleContext.getPrerequisites(
+ attribute.getName(), attribute.getAccessMode(), ObjcProvider.class));
+ }
+ return builder.build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java
index ca2524a37b..16cc88bb1e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/XcodeSupport.java
@@ -21,6 +21,7 @@ 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.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
+import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder;
/**
* Support for Objc rule types that export an Xcode provider or generate xcode project files.
@@ -104,9 +105,10 @@ public final class XcodeSupport {
*
* @return this xcode support
*/
- XcodeSupport addDependencies(XcodeProvider.Builder xcodeProviderBuilder, String attribute) {
- xcodeProviderBuilder
- .addDependencies(ruleContext.getPrerequisites(attribute, Mode.TARGET, XcodeProvider.class));
+ XcodeSupport addDependencies(Builder xcodeProviderBuilder, Attribute attribute) {
+ xcodeProviderBuilder.addDependencies(
+ ruleContext.getPrerequisites(
+ attribute.getName(), attribute.getAccessMode(), XcodeProvider.class));
return this;
}
}