aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-03-22 18:23:03 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-03-23 12:19:51 +0000
commit73f2a45d3a601b43e72c866e44f4ba3eaa782aeb (patch)
tree7a5ab2d1524f02526d22e6de0f2d3f7bd8f15779 /src
parenta65d0ee1f9376820f87309a3b81502ad14614583 (diff)
Introduce ReleaseBundling class to contain all application specific information required for creating a release bundle.
-- MOS_MIGRATED_REVID=117843546
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java78
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java71
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibrary.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java361
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java224
5 files changed, 587 insertions, 167 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java
index 3900c701a0..3123ded3d0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BundleSupport.java
@@ -35,15 +35,11 @@ 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.AppleToolchain;
import com.google.devtools.build.lib.rules.apple.Platform;
-import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.InvalidFamilyNameException;
-import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.RepeatedFamilyNameException;
import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder;
-import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@@ -216,20 +212,18 @@ final class BundleSupport {
}
/**
- * Returns a set containing the {@link TargetDeviceFamily} values
- * which this bundle is targeting. Returns an empty set for any
- * invalid value of the target device families attribute.
+ * Returns a set containing the {@link TargetDeviceFamily} values which this bundle is targeting.
+ * Returns an empty set for any invalid value of the target device families attribute.
*/
ImmutableSet<TargetDeviceFamily> targetDeviceFamilies() {
- return attributes.families();
+ return bundling.getTargetDeviceFamilies();
}
private void registerInterfaceBuilderActions(ObjcProvider objcProvider) {
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
for (Artifact storyboardInput : objcProvider.get(ObjcProvider.STORYBOARD)) {
String archiveRoot = BundleableFile.flatBundlePath(storyboardInput.getExecPath()) + "c";
- Artifact zipOutput = intermediateArtifacts.compiledStoryboardZip(storyboardInput);
+ Artifact zipOutput = bundling.getIntermediateArtifacts()
+ .compiledStoryboardZip(storyboardInput);
ruleContext.registerAction(
ObjcRuleClasses.spawnXcrunActionBuilder(ruleContext)
@@ -254,7 +248,7 @@ final class BundleSupport {
.add("--module")
.add(ruleContext.getLabel().getName());
- for (TargetDeviceFamily targetDeviceFamily : attributes.families()) {
+ for (TargetDeviceFamily targetDeviceFamily : targetDeviceFamilies()) {
commandLine.add("--target-device").add(targetDeviceFamily.name().toLowerCase(Locale.US));
}
@@ -265,10 +259,8 @@ final class BundleSupport {
private void registerMomczipActions(ObjcProvider objcProvider) {
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
Iterable<Xcdatamodel> xcdatamodels = Xcdatamodels.xcdatamodels(
- intermediateArtifacts, objcProvider.get(ObjcProvider.XCDATAMODEL));
+ bundling.getIntermediateArtifacts(), objcProvider.get(ObjcProvider.XCDATAMODEL));
for (Xcdatamodel datamodel : xcdatamodels) {
Artifact outputZip = datamodel.getOutputZip();
ruleContext.registerAction(
@@ -292,10 +284,8 @@ final class BundleSupport {
}
private void registerConvertXibsActions(ObjcProvider objcProvider) {
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
for (Artifact original : objcProvider.get(ObjcProvider.XIB)) {
- Artifact zipOutput = intermediateArtifacts.compiledXibFileZip(original);
+ Artifact zipOutput = bundling.getIntermediateArtifacts().compiledXibFileZip(original);
String archiveRoot = BundleableFile.flatBundlePath(
FileSystemUtils.replaceExtension(original.getExecPath(), ".nib"));
@@ -311,10 +301,8 @@ final class BundleSupport {
}
private void registerConvertStringsActions(ObjcProvider objcProvider) {
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
for (Artifact strings : objcProvider.get(ObjcProvider.STRINGS)) {
- Artifact bundled = intermediateArtifacts.convertedStringsFile(strings);
+ Artifact bundled = bundling.getIntermediateArtifacts().convertedStringsFile(strings);
ruleContext.registerAction(ObjcRuleClasses.spawnXcrunActionBuilder(ruleContext)
.setMnemonic("ConvertStringsPlist")
.setExecutable(new PathFragment("/usr/bin/plutil"))
@@ -341,9 +329,8 @@ final class BundleSupport {
if (!bundling.needsToMergeInfoplist()) {
return; // Nothing to do here.
}
-
- Artifact plMergeControlArtifact =
- ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".plmerge-control");
+
+ Artifact plMergeControlArtifact = baseNameArtifact(ruleContext, ".plmerge-control");
ruleContext.registerAction(
new BinaryFileWriteAction(
@@ -359,17 +346,32 @@ final class BundleSupport {
.addArgument("--control")
.addInputArgument(plMergeControlArtifact)
.addTransitiveInputs(mergingContentArtifacts)
- .addOutput(ObjcRuleClasses.intermediateArtifacts(ruleContext).mergedInfoplist())
+ .addOutput(bundling.getIntermediateArtifacts().mergedInfoplist())
.build(ruleContext));
}
+ /**
+ * Returns an {@link Artifact} with name prefixed with prefix given in {@link Bundling} if
+ * available. This helps in creating unique artifact name when multiple bundles are created
+ * with a different name than the target name.
+ */
+ private Artifact baseNameArtifact(RuleContext ruleContext, String artifactName) {
+ String prefixedArtifactName;
+ if (bundling.getArtifactPrefix() != null) {
+ prefixedArtifactName = String.format("-%s%s", bundling.getArtifactPrefix(), artifactName);
+ } else {
+ prefixedArtifactName = artifactName;
+ }
+ return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, prefixedArtifactName);
+ }
+
private void registerActoolActionIfNecessary(ObjcProvider objcProvider) {
Optional<Artifact> actoolzipOutput = bundling.getActoolzipOutput();
if (!actoolzipOutput.isPresent()) {
return;
}
- Artifact actoolPartialInfoplist = actoolPartialInfoplist(ruleContext, objcProvider).get();
+ Artifact actoolPartialInfoplist = actoolPartialInfoplist(objcProvider).get();
Artifact zipOutput = actoolzipOutput.get();
// TODO(bazel-team): Do not use the deploy jar explicitly here. There is currently a bug where
@@ -404,7 +406,7 @@ final class BundleSupport {
.add("--minimum-deployment-target")
.add(bundling.getMinimumOsVersion().toString());
- for (TargetDeviceFamily targetDeviceFamily : attributes.families()) {
+ for (TargetDeviceFamily targetDeviceFamily : targetDeviceFamilies()) {
commandLine.add("--target-device").add(targetDeviceFamily.name().toLowerCase(Locale.US));
}
@@ -424,12 +426,9 @@ final class BundleSupport {
* about the {@code app_icon} and {@code launch_image} if supplied. If neither an app icon or a
* launch image was supplied, the plist file generated is empty.
*/
- private static Optional<Artifact> actoolPartialInfoplist(
- RuleContext ruleContext, ObjcProvider objcProvider) {
+ private Optional<Artifact> actoolPartialInfoplist(ObjcProvider objcProvider) {
if (objcProvider.hasAssetCatalogs()) {
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
- return Optional.of(intermediateArtifacts.actoolPartialInfoplist());
+ return Optional.of(bundling.getIntermediateArtifacts().actoolPartialInfoplist());
} else {
return Optional.absent();
}
@@ -453,21 +452,6 @@ final class BundleSupport {
}
/**
- * Returns the value of the {@code families} attribute in a form
- * that is more useful than a list of strings. Returns an empty
- * set for any invalid {@code families} attribute value, including
- * an empty list.
- */
- ImmutableSet<TargetDeviceFamily> families() {
- List<String> rawFamilies = ruleContext.attributes().get("families", Type.STRING_LIST);
- try {
- return ImmutableSet.copyOf(TargetDeviceFamily.fromNamesInRule(rawFamilies));
- } catch (InvalidFamilyNameException | RepeatedFamilyNameException e) {
- return ImmutableSet.of();
- }
- }
-
- /**
* Returns the location of the ibtoolwrapper tool.
*/
FilesToRunProvider ibtoolWrapper() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java b/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java
index ec9da712c7..c9b83efdae 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/Bundling.java
@@ -30,6 +30,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingR
import com.google.common.base.Optional;
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.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
@@ -63,6 +64,8 @@ final class Bundling {
private String fallbackBundleId;
private String architecture;
private DottedVersion minimumOsVersion;
+ private ImmutableSet<TargetDeviceFamily> families;
+ private String artifactPrefix;
public Builder setName(String name) {
this.name = name;
@@ -104,6 +107,15 @@ final class Bundling {
}
/**
+ * Adds the given list of artifacts representing {@code Info.plist}s that are to be merged into
+ * this bundle's {@code Info.plist}.
+ */
+ public Builder addInfoplistInputs(Iterable<Artifact> infoplists) {
+ this.infoplistInputs.addAll(infoplists);
+ return this;
+ }
+
+ /**
* Adds an artifact representing an {@code Info.plist} that contains automatic entries
* generated by xcode.
*/
@@ -137,12 +149,12 @@ final class Bundling {
this.intermediateArtifacts = intermediateArtifacts;
return this;
}
-
+
public Builder setPrimaryBundleId(String primaryId) {
this.primaryBundleId = primaryId;
return this;
}
-
+
public Builder setFallbackBundleId(String fallbackId) {
this.fallbackBundleId = fallbackId;
return this;
@@ -157,6 +169,16 @@ final class Bundling {
return this;
}
+ public Builder setTargetDeviceFamilies(ImmutableSet<TargetDeviceFamily> families) {
+ this.families = families;
+ return this;
+ }
+
+ public Builder setArtifactPrefix(String artifactPrefix) {
+ this.artifactPrefix = artifactPrefix;
+ return this;
+ }
+
private static NestedSet<Artifact> nestedBundleContentArtifacts(Iterable<Bundling> bundles) {
NestedSetBuilder<Artifact> artifacts = NestedSetBuilder.stableOrder();
for (Bundling bundle : bundles) {
@@ -259,7 +281,7 @@ final class Bundling {
public Bundling build() {
Preconditions.checkNotNull(intermediateArtifacts, "intermediateArtifacts");
-
+ Preconditions.checkNotNull(families, "families");
NestedSet<Artifact> bundleInfoplistInputs = bundleInfoplistInputs();
Optional<Artifact> bundleInfoplist = bundleInfoplist(bundleInfoplistInputs);
Optional<Artifact> actoolzipOutput = actoolzipOutput();
@@ -295,7 +317,10 @@ final class Bundling {
minimumOsVersion,
bundleInfoplistInputs,
automaticEntriesInfoplistInput,
- objcProvider.get(NESTED_BUNDLE));
+ objcProvider.get(NESTED_BUNDLE),
+ families,
+ intermediateArtifacts,
+ artifactPrefix);
}
}
@@ -320,6 +345,9 @@ final class Bundling {
private final NestedSet<Artifact> infoplistInputs;
private final NestedSet<Bundling> nestedBundlings;
private Artifact automaticEntriesInfoplistInput;
+ private final ImmutableSet<TargetDeviceFamily> families;
+ private final IntermediateArtifacts intermediateArtifacts;
+ private final String artifactPrefix;
private Bundling(
String name,
@@ -336,7 +364,10 @@ final class Bundling {
DottedVersion minimumOsVersion,
NestedSet<Artifact> infoplistInputs,
Artifact automaticEntriesInfoplistInput,
- NestedSet<Bundling> nestedBundlings) {
+ NestedSet<Bundling> nestedBundlings,
+ ImmutableSet<TargetDeviceFamily> families,
+ IntermediateArtifacts intermediateArtifacts,
+ String artifactPrefix) {
this.nestedBundlings = Preconditions.checkNotNull(nestedBundlings);
this.name = Preconditions.checkNotNull(name);
this.bundleDirFormat = Preconditions.checkNotNull(bundleDirFormat);
@@ -352,6 +383,9 @@ final class Bundling {
this.minimumOsVersion = Preconditions.checkNotNull(minimumOsVersion);
this.infoplistInputs = Preconditions.checkNotNull(infoplistInputs);
this.automaticEntriesInfoplistInput = automaticEntriesInfoplistInput;
+ this.families = Preconditions.checkNotNull(families);
+ this.intermediateArtifacts = intermediateArtifacts;
+ this.artifactPrefix = artifactPrefix;
}
/**
@@ -401,7 +435,7 @@ final class Bundling {
public Optional<Artifact> getBundleInfoplist() {
return bundleInfoplist;
}
-
+
/**
* Returns all info plists that need to be merged into this bundle's {@link #getBundleInfoplist()
* info plist}, other than that plist that contains blaze-generated automatic entires.
@@ -428,7 +462,7 @@ final class Bundling {
}
return result.build();
}
-
+
/**
* Returns {@code true} if this bundle requires merging of its {@link #getBundleInfoplist() info
* plist}.
@@ -505,4 +539,27 @@ final class Bundling {
public DottedVersion getMinimumOsVersion() {
return minimumOsVersion;
}
+
+ /**
+ * Returns the list of {@link TargetDeviceFamily} values this bundle is targeting.
+ * If empty, the default values specified by "families" attribute will be used.
+ */
+ public ImmutableSet<TargetDeviceFamily> getTargetDeviceFamilies() {
+ return families;
+ }
+
+ /**
+ * Returns {@link IntermediateArtifacts} required to create this bundle.
+ */
+ public IntermediateArtifacts getIntermediateArtifacts() {
+ return intermediateArtifacts;
+ }
+
+ /**
+ * Returns the prefix to be added to all generated artifact names, can be null. This is useful
+ * to disambiguate artifacts for multiple bundles created with different names withing same rule.
+ */
+ public String getArtifactPrefix() {
+ return artifactPrefix;
+ }
}
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 1827df916e..6fa174900d 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
@@ -17,6 +17,7 @@ package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.NESTED_BUNDLE;
import static com.google.devtools.build.lib.rules.objc.XcodeProductType.BUNDLE;
+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;
@@ -25,6 +26,11 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes;
+import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.InvalidFamilyNameException;
+import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.RepeatedFamilyNameException;
+import com.google.devtools.build.lib.syntax.Type;
+
+import java.util.List;
/**
* Implementation for {@code objc_bundle_library}.
@@ -77,6 +83,19 @@ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory {
ObjcRuleClasses.intermediateArtifacts(ruleContext);
ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
+
+ ImmutableSet<TargetDeviceFamily> families = null;
+ List<String> rawFamilies = ruleContext.attributes().get("families", Type.STRING_LIST);
+ try {
+ families = ImmutableSet.copyOf(TargetDeviceFamily.fromNamesInRule(rawFamilies));
+ } catch (InvalidFamilyNameException | RepeatedFamilyNameException e) {
+ families = ImmutableSet.of();
+ }
+
+ if (families.isEmpty()) {
+ ruleContext.attributeError("families", ReleaseBundling.INVALID_FAMILIES_ERROR);
+ }
+
return new Bundling.Builder()
.setName(ruleContext.getLabel().getName())
.setArchitecture(appleConfiguration.getIosCpu())
@@ -85,6 +104,7 @@ public class ObjcBundleLibrary implements RuleConfiguredTargetFactory {
.addInfoplistInputFromRule(ruleContext)
.setIntermediateArtifacts(intermediateArtifacts)
.setMinimumOsVersion(objcConfiguration.getMinimumOs())
+ .setTargetDeviceFamilies(families)
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java
new file mode 100644
index 0000000000..a78f0077d1
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundling.java
@@ -0,0 +1,361 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+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.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.InvalidFamilyNameException;
+import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.RepeatedFamilyNameException;
+import com.google.devtools.build.lib.syntax.Type;
+import com.google.devtools.build.lib.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * Contains information regarding the creation of a released bundle such as an application
+ * or extension. The information which generally includes app icons, launch image, targeted devices
+ * and other data for potential signing is used to create a releasable bundle out of the bundle
+ * created using {@link Bundling} object.
+ */
+@Immutable
+final class ReleaseBundling {
+ static final class Builder {
+ private Artifact ipaArtifact;
+ private String bundleId;
+ private String primaryBundleId;
+ private String fallbackBundleId;
+ private String appIcon;
+ private String launchImage;
+ private Artifact launchStoryboard;
+ private Artifact provisioningProfile;
+ private String provisioningProfileAttributeName;
+ private final NestedSetBuilder<Artifact> infoplistInputs = NestedSetBuilder.stableOrder();
+ private Iterable<Artifact> infoPlistsFromRule;
+ private ImmutableSet<TargetDeviceFamily> families;
+ private IntermediateArtifacts intermediateArtifacts;
+ private String artifactPrefix;
+
+ public Builder setIpaArtifact(Artifact ipaArtifact) {
+ this.ipaArtifact = ipaArtifact;
+ return this;
+ }
+
+ public Builder setBundleId(String bundleId) {
+ this.bundleId = bundleId;
+ return this;
+ }
+
+ public Builder setPrimaryBundleId(String primaryId) {
+ this.primaryBundleId = primaryId;
+ return this;
+ }
+
+ public Builder setFallbackBundleId(String fallbackId) {
+ this.fallbackBundleId = fallbackId;
+ return this;
+ }
+
+ public Builder setAppIcon(String appIcon) {
+ this.appIcon = appIcon;
+ return this;
+ }
+
+ public Builder setLaunchImage(String launchImage) {
+ this.launchImage = launchImage;
+ return this;
+ }
+
+ public Builder setLaunchStoryboard(Artifact launchStoryboard) {
+ this.launchStoryboard = launchStoryboard;
+ return this;
+ }
+
+ public Builder setProvisioningProfile(Artifact provisioningProfile) {
+ this.provisioningProfile = provisioningProfile;
+ return this;
+ }
+
+ public Builder setProvisioningProfileAttributeName(String provisioningProfileAttributeName) {
+ this.provisioningProfileAttributeName = provisioningProfileAttributeName;
+ return this;
+ }
+
+ public Builder addInfoplistInput(Artifact infoPlist) {
+ this.infoplistInputs.add(infoPlist);
+ return this;
+ }
+
+ public Builder addInfoplistInputs(Iterable<Artifact> infoplists) {
+ this.infoplistInputs.addAll(infoplists);
+ return this;
+ }
+
+ public Builder setInfoPlistsFromRule(Iterable<Artifact> infoPlistsFromRule) {
+ this.infoPlistsFromRule = infoPlistsFromRule;
+ return this;
+ }
+
+ public Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
+ this.intermediateArtifacts = intermediateArtifacts;
+ return this;
+ }
+
+ public Builder setTargetDeviceFamilies(ImmutableSet<TargetDeviceFamily> families) {
+ this.families = families;
+ return this;
+ }
+
+ public Builder setArtifactPrefix(String artifactPrefix) {
+ this.artifactPrefix = artifactPrefix;
+ return this;
+ }
+
+ public ReleaseBundling build() {
+ Preconditions.checkNotNull(intermediateArtifacts, "intermediateArtifacts");
+ Preconditions.checkNotNull(families, "families");
+ return new ReleaseBundling(
+ ipaArtifact,
+ bundleId,
+ primaryBundleId,
+ fallbackBundleId,
+ appIcon,
+ launchImage,
+ launchStoryboard,
+ provisioningProfile,
+ provisioningProfileAttributeName,
+ infoplistInputs.build(),
+ infoPlistsFromRule,
+ families,
+ intermediateArtifacts,
+ artifactPrefix);
+ }
+ }
+
+ /**
+ * Returns a {@link ReleaseBundling} object constructed using the information available in given
+ * context.
+ */
+ public static ReleaseBundling releaseBundling(RuleContext ruleContext)
+ throws InterruptedException {
+ Preconditions.checkState(!Strings.isNullOrEmpty(
+ ruleContext.attributes().get("bundle_id", Type.STRING)),
+ "requires a bundle_id value");
+ String primaryBundleId = null;
+ String fallbackBundleId = null;
+ Artifact provisioningProfile;
+
+ if (ruleContext.attributes().isAttributeValueExplicitlySpecified("bundle_id")) {
+ primaryBundleId = ruleContext.attributes().get("bundle_id", Type.STRING);
+ } else {
+ fallbackBundleId = ruleContext.attributes().get("bundle_id", Type.STRING);
+ }
+
+ Artifact explicitProvisioningProfile =
+ ruleContext.getPrerequisiteArtifact("provisioning_profile", Mode.TARGET);
+ if (explicitProvisioningProfile != null) {
+ provisioningProfile = explicitProvisioningProfile;
+ } else {
+ provisioningProfile = ruleContext.getPrerequisiteArtifact(":default_provisioning_profile",
+ Mode.TARGET);
+ }
+
+ ImmutableSet<TargetDeviceFamily> families = null;
+ List<String> rawFamilies = ruleContext.attributes().get("families", Type.STRING_LIST);
+ try {
+ families = ImmutableSet.copyOf(TargetDeviceFamily.fromNamesInRule(rawFamilies));
+ } catch (InvalidFamilyNameException | RepeatedFamilyNameException e) {
+ families = ImmutableSet.of();
+ }
+
+ if (families.isEmpty()) {
+ ruleContext.attributeError("families", INVALID_FAMILIES_ERROR);
+ }
+
+ return new ReleaseBundling.Builder()
+ .setIpaArtifact(ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA))
+ .setBundleId(ruleContext.attributes().get("bundle_id", Type.STRING))
+ .setPrimaryBundleId(primaryBundleId)
+ .setFallbackBundleId(fallbackBundleId)
+ .setAppIcon(Strings.emptyToNull(ruleContext.attributes().get("app_icon", Type.STRING)))
+ .setLaunchImage(Strings.emptyToNull(
+ ruleContext.attributes().get("launch_image", Type.STRING)))
+ .setLaunchStoryboard(ruleContext.getPrerequisiteArtifact("launch_storyboard", Mode.TARGET))
+ .setProvisioningProfile(provisioningProfile)
+ .setProvisioningProfileAttributeName("provisioning_profile")
+ .setTargetDeviceFamilies(families)
+ .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
+ .build();
+ }
+
+ @VisibleForTesting
+ static final String INVALID_FAMILIES_ERROR =
+ "Expected one or two strings from the list 'iphone', 'ipad'";
+ private final Artifact ipaArtifact;
+ private final String bundleId;
+ private final String fallbackBundleId;
+ private final String primaryBundleId;
+ private final String appIcon;
+ private final String launchImage;
+ private final Artifact launchStoryboard;
+ private final Artifact provisioningProfile;
+ private final String provisioningProfileAttributeName;
+ private final NestedSet<Artifact> infoplistInputs;
+ private final ImmutableSet<TargetDeviceFamily> families;
+ private final IntermediateArtifacts intermediateArtifacts;
+ private final Iterable<Artifact> infoPlistsFromRule;
+ private final String artifactPrefix;
+
+ private ReleaseBundling(
+ Artifact ipaArtifact,
+ String bundleId,
+ String primaryBundleId,
+ String fallbackBundleId,
+ String appIcon,
+ String launchImage,
+ Artifact launchStoryboard,
+ Artifact provisioningProfile,
+ String provisioningProfileAttributeName,
+ NestedSet<Artifact> infoplistInputs,
+ Iterable<Artifact> infoPlistsFromRule,
+ ImmutableSet<TargetDeviceFamily> families,
+ IntermediateArtifacts intermediateArtifacts,
+ String artifactPrefix) {
+ this.ipaArtifact = Preconditions.checkNotNull(ipaArtifact);
+ this.bundleId = bundleId;
+ this.primaryBundleId = primaryBundleId;
+ this.fallbackBundleId = fallbackBundleId;
+ this.appIcon = appIcon;
+ this.launchImage = launchImage;
+ this.launchStoryboard = launchStoryboard;
+ this.provisioningProfile = provisioningProfile;
+ this.provisioningProfileAttributeName =
+ Preconditions.checkNotNull(provisioningProfileAttributeName);
+ this.infoplistInputs = Preconditions.checkNotNull(infoplistInputs);
+ this.infoPlistsFromRule = infoPlistsFromRule;
+ this.families = Preconditions.checkNotNull(families);
+ this.intermediateArtifacts = Preconditions.checkNotNull(intermediateArtifacts);
+ this.artifactPrefix = artifactPrefix;
+ }
+
+ /**
+ * Returns the {@link Artifact} containing the final ipa bundle.
+ */
+ public Artifact getIpaArtifact() {
+ return ipaArtifact;
+ }
+
+ /**
+ * Returns the identifier of this bundle.
+ */
+ public String getBundleId() {
+ return bundleId;
+ }
+
+ /**
+ * Returns primary bundle ID to use, can be null.
+ */
+ public String getPrimaryBundleId() {
+ return primaryBundleId;
+ }
+
+ /**
+ * Returns fallback bundle ID to use when primary isn't set.
+ */
+ public String getFallbackBundleId() {
+ return fallbackBundleId;
+ }
+
+ /**
+ * Returns the app icon name for this bundle, can be null.
+ */
+ public String getAppIcon() {
+ return appIcon;
+ }
+
+ /**
+ * Returns the launch image name for this bundle, can be null.
+ */
+ public String getLaunchImage() {
+ return launchImage;
+ }
+
+ /**
+ * Returns an {@link Artifact} containing launch storyboard for this bundle, can be null.
+ */
+ public Artifact getLaunchStoryboard() {
+ return launchStoryboard;
+ }
+
+ /**
+ * Returns an {@link Artifact} containing provisioning profile used to sign this bundle,
+ * can be null.
+ */
+ public Artifact getProvisioningProfile() {
+ return provisioningProfile;
+ }
+
+ /**
+ * Returns the list of plists to be merged to final bundle.
+ */
+ public NestedSet<Artifact> getInfoplistInputs() {
+ return infoplistInputs;
+ }
+
+ /**
+ * Returns the list of {@link TargetDeviceFamily} values this bundle is targeting.
+ * If empty, the default values specified by "families" attribute will be used.
+ */
+ public ImmutableSet<TargetDeviceFamily> getTargetDeviceFamilies() {
+ return families;
+ }
+
+ /**
+ * Returns {@link IntermediateArtifacts} used to create this bundle.
+ */
+ public IntermediateArtifacts getIntermediateArtifacts() {
+ return intermediateArtifacts;
+ }
+
+ /**
+ * Returns the name of the attribute which is used to specifiy the provisioning profile.
+ */
+ public String getProvisioningProfileAttrName() {
+ return provisioningProfileAttributeName;
+ }
+
+ /**
+ * Adds any info plists specified in the given rule's {@code infoplists} attribute as inputs to
+ * this bundle's {@code Info.plist} (which is merged from any such added plists plus some
+ * additional information).
+ */
+ public Iterable<Artifact> getInfoPlistsFromRule() {
+ return infoPlistsFromRule;
+ }
+
+ /**
+ * Returns the prefix to be added to all generated artifact names, can be null. This is useful
+ * to disambiguate artifacts for multiple bundles created with different names withing same rule.
+ */
+ public String getArtifactPrefix() {
+ return artifactPrefix;
+ }
+}
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 c6dc2740a8..40c52be628 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
@@ -56,7 +56,6 @@ import com.google.devtools.build.lib.rules.apple.Platform;
import com.google.devtools.build.lib.rules.objc.BundleSupport.ExtraActoolArgs;
import com.google.devtools.build.lib.rules.objc.Bundling.Builder;
import com.google.devtools.build.lib.shell.ShellUtils;
-import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.XcodeprojBuildSetting;
import com.dd.plist.NSArray;
@@ -88,9 +87,6 @@ public final class ReleaseBundlingSupport {
static final String NO_ASSET_CATALOG_ERROR_FORMAT =
"a value was specified (%s), but this app does not have any asset catalogs";
@VisibleForTesting
- static final String INVALID_FAMILIES_ERROR =
- "Expected one or two strings from the list 'iphone', 'ipad'";
- @VisibleForTesting
static final String DEVICE_NO_PROVISIONING_PROFILE =
"Provisioning profile must be set for device build";
@@ -124,6 +120,7 @@ public final class ReleaseBundlingSupport {
private final ObjcProvider objcProvider;
private final LinkedBinary linkedBinary;
private final IntermediateArtifacts intermediateArtifacts;
+ private final ReleaseBundling releaseBundling;
/**
* Indicator as to whether this rule generates a binary directly or whether only dependencies
@@ -156,6 +153,8 @@ public final class ReleaseBundlingSupport {
* @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated
* for (<b>not</b> the minimum OS version its binary is compiled with, that needs to be set
* through the configuration)
+ * @param releaseBundling the {@link ReleaseBundling} containing information for creating a
+ * releaseable bundle.
*/
ReleaseBundlingSupport(
RuleContext ruleContext,
@@ -163,13 +162,15 @@ public final class ReleaseBundlingSupport {
LinkedBinary linkedBinary,
String bundleDirFormat,
String bundleName,
- DottedVersion bundleMinimumOsVersion) {
+ DottedVersion bundleMinimumOsVersion,
+ ReleaseBundling releaseBundling) {
this.linkedBinary = linkedBinary;
this.attributes = new Attributes(ruleContext);
this.ruleContext = ruleContext;
this.objcProvider = objcProvider;
- this.intermediateArtifacts = ObjcRuleClasses.intermediateArtifacts(ruleContext);
- bundling = bundling(ruleContext, objcProvider, bundleDirFormat, bundleName,
+ this.releaseBundling = releaseBundling;
+ this.intermediateArtifacts = releaseBundling.getIntermediateArtifacts();
+ this.bundling = bundling(ruleContext, objcProvider, bundleDirFormat, bundleName,
bundleMinimumOsVersion);
bundleSupport = new BundleSupport(ruleContext, bundling, extraActoolArgs());
}
@@ -177,6 +178,29 @@ public final class ReleaseBundlingSupport {
/**
* Creates a new application support within the given rule context.
*
+ * @param ruleContext context for the application-generating rule
+ * @param objcProvider provider containing all dependencies' information as well as some of this
+ * rule's
+ * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just
+ * the latter
+ * @param bundleDirFormat format string representing the bundle's directory with a single
+ * placeholder for the target name (e.g. {@code "Payload/%s.app"})
+ * @param bundleName name of the bundle, used with bundleDirFormat
+ */
+ ReleaseBundlingSupport(
+ RuleContext ruleContext,
+ ObjcProvider objcProvider,
+ LinkedBinary linkedBinary,
+ String bundleDirFormat,
+ String bundleName,
+ DottedVersion bundleMinimumOsVersion) throws InterruptedException {
+ this(ruleContext, objcProvider, linkedBinary, bundleDirFormat, bundleName,
+ bundleMinimumOsVersion, ReleaseBundling.releaseBundling(ruleContext));
+ }
+
+ /**
+ * Creates a new application support within the given rule context.
+ *
* {@code bundleName} defaults to label name
*
* @param ruleContext context for the application-generating rule
@@ -189,13 +213,14 @@ public final class ReleaseBundlingSupport {
* @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated
* for (<b>not</b> the minimum OS version its binary is compiled with, that needs to be set
* through the configuration)
+ * @throws InterruptedException
*/
ReleaseBundlingSupport(
RuleContext ruleContext,
ObjcProvider objcProvider,
LinkedBinary linkedBinary,
String bundleDirFormat,
- DottedVersion bundleMinimumOsVersion) {
+ DottedVersion bundleMinimumOsVersion) throws InterruptedException {
this(ruleContext, objcProvider, linkedBinary, bundleDirFormat, ruleContext.getLabel().getName(),
bundleMinimumOsVersion);
}
@@ -212,30 +237,26 @@ public final class ReleaseBundlingSupport {
// run actool in this case, which means it does not do validity checks,
// and we MUST raise our own error somehow...
if (!objcProvider.hasAssetCatalogs()) {
- if (attributes.appIcon() != null) {
+ if (releaseBundling.getAppIcon() != null) {
ruleContext.attributeError("app_icon",
- String.format(NO_ASSET_CATALOG_ERROR_FORMAT, attributes.appIcon()));
+ String.format(NO_ASSET_CATALOG_ERROR_FORMAT, releaseBundling.getAppIcon()));
}
- if (attributes.launchImage() != null) {
+ if (releaseBundling.getLaunchImage() != null) {
ruleContext.attributeError("launch_image",
- String.format(NO_ASSET_CATALOG_ERROR_FORMAT, attributes.launchImage()));
+ String.format(NO_ASSET_CATALOG_ERROR_FORMAT, releaseBundling.getLaunchImage()));
}
}
- if (bundleSupport.targetDeviceFamilies().isEmpty()) {
- ruleContext.attributeError("families", INVALID_FAMILIES_ERROR);
- }
-
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
- if (attributes.provisioningProfile() == null
+ if (releaseBundling.getProvisioningProfile() == null
&& appleConfiguration.getBundlingPlatform() != Platform.IOS_SIMULATOR) {
- ruleContext.attributeError("provisioning_profile", DEVICE_NO_PROVISIONING_PROFILE);
+ ruleContext.attributeError(releaseBundling.getProvisioningProfileAttrName(),
+ DEVICE_NO_PROVISIONING_PROFILE);
}
return this;
}
-
/**
* Validates that resources defined in this rule and its dependencies and written to this bundle
* are legal.
@@ -266,7 +287,7 @@ public final class ReleaseBundlingSupport {
registerEnvironmentPlistAction();
registerAutomaticPlistAction();
- if (attributes.launchStoryboard() != null) {
+ if (releaseBundling.getLaunchStoryboard() != null) {
registerLaunchStoryboardPlistAction();
}
@@ -315,7 +336,7 @@ public final class ReleaseBundlingSupport {
}
private void registerLaunchStoryboardPlistAction() {
- String launchStoryboard = attributes.launchStoryboard().getFilename();
+ String launchStoryboard = releaseBundling.getLaunchStoryboard().getFilename();
String launchStoryboardName = launchStoryboard.substring(0, launchStoryboard.lastIndexOf('.'));
NSDictionary result = new NSDictionary();
result.put("UILaunchStoryboardName", launchStoryboardName);
@@ -345,7 +366,7 @@ public final class ReleaseBundlingSupport {
.addOutput(getGeneratedEnvironmentPlist())
.build(ruleContext));
}
-
+
private void registerAutomaticPlistAction() {
ruleContext.registerAction(
new FileWriteAction(
@@ -392,7 +413,7 @@ public final class ReleaseBundlingSupport {
* avoid excessive zipping/unzipping of IPA contents.
*/
private void registerPostProcessAndSigningActions() throws InterruptedException {
- Artifact processedIpa = ruleContext.getImplicitOutputArtifact(IPA);
+ Artifact processedIpa = releaseBundling.getIpaArtifact();
Artifact unprocessedIpa = intermediateArtifacts.unprocessedIpa();
boolean processingNeeded = false;
@@ -422,7 +443,8 @@ public final class ReleaseBundlingSupport {
processingNeeded = true;
registerEntitlementsActions();
actionCommandLine += signingCommandLine();
- inputs.add(attributes.provisioningProfile()).add(intermediateArtifacts.entitlements());
+ inputs.add(releaseBundling.getProvisioningProfile()).add(
+ intermediateArtifacts.entitlements());
}
actionCommandLine += "cd ${t} && /usr/bin/zip -q -r \"${signed_ipa}\" .";
@@ -515,8 +537,8 @@ public final class ReleaseBundlingSupport {
NestedSetBuilder.create(Order.STABLE_ORDER, substitutedEntitlements, extraEntitlements),
intermediateArtifacts.entitlements());
- Artifact plMergeControlArtifact =
- ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".merge-entitlements-control");
+ Artifact plMergeControlArtifact = ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext,
+ artifactName(".merge-entitlements-control"));
ruleContext.registerAction(
new BinaryFileWriteAction(
@@ -569,14 +591,12 @@ public final class ReleaseBundlingSupport {
if (linkedBinary == LinkedBinary.LOCAL_AND_DEPENDENCIES
&& ObjcRuleClasses.objcConfiguration(ruleContext).generateDebugSymbols()) {
- IntermediateArtifacts intermediateArtifacts =
- ObjcRuleClasses.intermediateArtifacts(ruleContext);
debugSymbolBuilder.add(intermediateArtifacts.dsymPlist())
.add(intermediateArtifacts.dsymSymbol())
.add(intermediateArtifacts.breakpadSym());
}
- filesToBuild.add(ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA))
+ filesToBuild.add(releaseBundling.getIpaArtifact())
// TODO(bazel-team): Fat binaries may require some merging of these file rather than just
// making them available.
.addTransitive(debugSymbolBuilder.build());
@@ -604,8 +624,8 @@ public final class ReleaseBundlingSupport {
.build();
// TODO(bazel-team): Handle the FRAMEWORK_DIR key properly. We probably want to add it to
// framework search paths, but not actually link it with the -framework flag.
- return new XcTestAppProvider(intermediateArtifacts.combinedArchitectureBinary(),
- ruleContext.getImplicitOutputArtifact(IPA), partialObjcProvider);
+ return new XcTestAppProvider(intermediateArtifacts
+ .combinedArchitectureBinary(), releaseBundling.getIpaArtifact(), partialObjcProvider);
}
/**
@@ -636,9 +656,8 @@ public final class ReleaseBundlingSupport {
* Returns a {@link RunfilesSupport} that uses the provided runner script as the executable.
*/
RunfilesSupport runfilesSupport(Artifact runnerScript) throws InterruptedException {
- Artifact ipaFile = ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA);
Runfiles runfiles = new Runfiles.Builder(ruleContext.getWorkspaceName())
- .addArtifact(ipaFile)
+ .addArtifact(releaseBundling.getIpaArtifact())
.addArtifact(runnerScript)
.addArtifact(attributes.iossim())
.build();
@@ -647,11 +666,11 @@ public final class ReleaseBundlingSupport {
private ExtraActoolArgs extraActoolArgs() {
ImmutableList.Builder<String> extraArgs = ImmutableList.builder();
- if (attributes.appIcon() != null) {
- extraArgs.add("--app-icon", attributes.appIcon());
+ if (releaseBundling.getAppIcon() != null) {
+ extraArgs.add("--app-icon", releaseBundling.getAppIcon());
}
- if (attributes.launchImage() != null) {
- extraArgs.add("--launch-image", attributes.launchImage());
+ if (releaseBundling.getLaunchImage() != null) {
+ extraArgs.add("--launch-image", releaseBundling.getLaunchImage());
}
return new ExtraActoolArgs(extraArgs.build());
}
@@ -666,21 +685,11 @@ public final class ReleaseBundlingSupport {
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
if (appleConfiguration.getBundlingPlatform() == Platform.IOS_DEVICE) {
extraBundleFiles = ImmutableList.of(new BundleableFile(
- new Attributes(ruleContext).provisioningProfile(),
- PROVISIONING_PROFILE_BUNDLE_FILE));
+ releaseBundling.getProvisioningProfile(), PROVISIONING_PROFILE_BUNDLE_FILE));
} else {
extraBundleFiles = ImmutableList.of();
}
- String primaryBundleId = null;
- String fallbackBundleId = null;
-
- if (ruleContext.attributes().isAttributeValueExplicitlySpecified("bundle_id")) {
- primaryBundleId = ruleContext.attributes().get("bundle_id", Type.STRING);
- } else {
- fallbackBundleId = ruleContext.attributes().get("bundle_id", Type.STRING);
- }
-
Bundling.Builder bundling =
new Builder()
.setName(bundleName)
@@ -689,16 +698,28 @@ public final class ReleaseBundlingSupport {
.setBundleDirFormat(bundleDirFormat)
.addExtraBundleFiles(extraBundleFiles)
.setObjcProvider(objcProvider)
- .addInfoplistInputFromRule(ruleContext)
- .addInfoplistInput(getGeneratedVersionPlist())
- .addInfoplistInput(getGeneratedEnvironmentPlist())
- .setAutomaticEntriesInfoplistInput(getGeneratedAutomaticPlist())
- .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
- .setPrimaryBundleId(primaryBundleId)
- .setFallbackBundleId(fallbackBundleId)
- .setMinimumOsVersion(minimumOsVersion);
-
- if (attributes.launchStoryboard() != null) {
+ .setIntermediateArtifacts(intermediateArtifacts)
+ .setPrimaryBundleId(releaseBundling.getPrimaryBundleId())
+ .setFallbackBundleId(releaseBundling.getFallbackBundleId())
+ .setMinimumOsVersion(minimumOsVersion)
+ .setArtifactPrefix(releaseBundling.getArtifactPrefix())
+ .setTargetDeviceFamilies(releaseBundling.getTargetDeviceFamilies());
+
+ // Add plists from rule first.
+ if (releaseBundling.getInfoPlistsFromRule() != null) {
+ bundling.addInfoplistInputs(releaseBundling.getInfoPlistsFromRule());
+ } else {
+ bundling.addInfoplistInputFromRule(ruleContext);
+ }
+
+ // Add generated plists next so that generated values can override the default values in the
+ // plists from rule.
+ bundling.setAutomaticEntriesInfoplistInput(getGeneratedAutomaticPlist())
+ .addInfoplistInput(getGeneratedVersionPlist())
+ .addInfoplistInput(getGeneratedEnvironmentPlist())
+ .addInfoplistInputs(releaseBundling.getInfoplistInputs());
+
+ if (releaseBundling.getLaunchStoryboard() != null) {
bundling.addInfoplistInput(getLaunchStoryboardPlist());
}
@@ -734,16 +755,16 @@ public final class ReleaseBundlingSupport {
/** Returns this target's Xcode build settings. */
private Iterable<XcodeprojBuildSetting> buildSettings() {
ImmutableList.Builder<XcodeprojBuildSetting> buildSettings = new ImmutableList.Builder<>();
- if (attributes.appIcon() != null) {
+ if (releaseBundling.getAppIcon() != null) {
buildSettings.add(XcodeprojBuildSetting.newBuilder()
.setName("ASSETCATALOG_COMPILER_APPICON_NAME")
- .setValue(attributes.appIcon())
+ .setValue(releaseBundling.getAppIcon())
.build());
}
- if (attributes.launchImage() != null) {
+ if (releaseBundling.getLaunchImage() != null) {
buildSettings.add(XcodeprojBuildSetting.newBuilder()
.setName("ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME")
- .setValue(attributes.launchImage())
+ .setValue(releaseBundling.getLaunchImage())
.build());
}
@@ -768,8 +789,8 @@ public final class ReleaseBundlingSupport {
}
private void registerBundleMergeActions() {
- Artifact bundleMergeControlArtifact =
- ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".ipa-control");
+ Artifact bundleMergeControlArtifact = ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext,
+ artifactName(".ipa-control"));
BundleMergeControlBytes controlBytes =
new BundleMergeControlBytes(
@@ -849,13 +870,13 @@ public final class ReleaseBundlingSupport {
private void registerExtractTeamPrefixAction(Artifact teamPrefixFile) {
String shellCommand = "set -e && "
+ "PLIST=$(mktemp -t teamprefix.plist) && trap \"rm ${PLIST}\" EXIT && "
- + extractPlistCommand(attributes.provisioningProfile()) + " > ${PLIST} && "
+ + extractPlistCommand(releaseBundling.getProvisioningProfile()) + " > ${PLIST} && "
+ "/usr/libexec/PlistBuddy -c 'Print ApplicationIdentifierPrefix:0' ${PLIST} > "
+ teamPrefixFile.getShellEscapedExecPathString();
ruleContext.registerAction(
ObjcRuleClasses.spawnBashOnDarwinActionBuilder(shellCommand)
.setMnemonic("ExtractIosTeamPrefix")
- .addInput(attributes.provisioningProfile())
+ .addInput(releaseBundling.getProvisioningProfile())
.addOutput(teamPrefixFile)
.build(ruleContext));
}
@@ -868,14 +889,14 @@ public final class ReleaseBundlingSupport {
// is the application name, and is specified as an attribute.
String shellCommand = "set -e && "
+ "PLIST=$(mktemp -t entitlements.plist) && trap \"rm ${PLIST}\" EXIT && "
- + extractPlistCommand(attributes.provisioningProfile()) + " > ${PLIST} && "
+ + extractPlistCommand(releaseBundling.getProvisioningProfile()) + " > ${PLIST} && "
+ "/usr/libexec/PlistBuddy -x -c 'Print Entitlements' ${PLIST} > "
+ entitlements.getShellEscapedExecPathString();
ruleContext.registerAction(
ObjcRuleClasses.spawnBashOnDarwinActionBuilder(shellCommand)
.setMnemonic("ExtractIosEntitlements")
.setProgressMessage("Extracting entitlements: " + ruleContext.getLabel())
- .addInput(attributes.provisioningProfile())
+ .addInput(releaseBundling.getProvisioningProfile())
.addOutput(entitlements)
.build(ruleContext));
@@ -884,7 +905,7 @@ public final class ReleaseBundlingSupport {
private void registerEntitlementsVariableSubstitutionAction(
Artifact inputEntitlements, Artifact prefix, Artifact substitutedEntitlements) {
- String escapedBundleId = ShellUtils.shellEscape(attributes.bundleId());
+ String escapedBundleId = ShellUtils.shellEscape(releaseBundling.getBundleId());
String shellCommand =
"set -e && "
+ "PREFIX=\"$(cat "
@@ -954,7 +975,7 @@ public final class ReleaseBundlingSupport {
// configured in it (DeveloperCertificates:0).
identity =
"$(PLIST=$(mktemp -t cert.plist) && trap \"rm ${PLIST}\" EXIT && "
- + extractPlistCommand(attributes.provisioningProfile())
+ + extractPlistCommand(releaseBundling.getProvisioningProfile())
+ " > ${PLIST} && "
+ "/usr/libexec/PlistBuddy -c 'Print DeveloperCertificates:0' ${PLIST} | "
+ "openssl x509 -inform DER -noout -fingerprint | "
@@ -970,28 +991,40 @@ public final class ReleaseBundlingSupport {
private Artifact getGeneratedVersionPlist() {
return ruleContext.getRelatedArtifact(
- ruleContext.getUniqueDirectory("plists"), "-version.plist");
+ ruleContext.getUniqueDirectory("plists"), artifactName("-version.plist"));
}
private Artifact getGeneratedEnvironmentPlist() {
return ruleContext.getRelatedArtifact(
- ruleContext.getUniqueDirectory("plists"), "-environment.plist");
+ ruleContext.getUniqueDirectory("plists"), artifactName("-environment.plist"));
}
-
+
private Artifact getGeneratedAutomaticPlist() {
return ruleContext.getRelatedArtifact(
- ruleContext.getUniqueDirectory("plists"), "-automatic.plist");
+ ruleContext.getUniqueDirectory("plists"), artifactName("-automatic.plist"));
}
private Artifact getLaunchStoryboardPlist() {
return ruleContext.getRelatedArtifact(
- ruleContext.getUniqueDirectory("plists"), "-launchstoryboard.plist");
+ ruleContext.getUniqueDirectory("plists"), artifactName("-launchstoryboard.plist"));
+ }
+
+ /**
+ * Returns artifact name prefixed with prefix given in {@link ReleaseBundling} if available.
+ * This helps in creating unique artifact name when multiple bundles are created with a different
+ * name than the target name.
+ */
+ private String artifactName(String artifactName) {
+ if (releaseBundling.getArtifactPrefix() != null) {
+ return String.format("-%s%s", releaseBundling.getArtifactPrefix(), artifactName);
+ }
+ return artifactName;
}
/**
- * Logic to access attributes required by application support. Attributes are required and
- * guaranteed to return a value or throw unless they are annotated with {@link Nullable} in which
- * case they can return {@code null} if no value is defined.
+ * Logic to access attributes to access tools required by application support.
+ * Attributes are required and guaranteed to return a value or throw unless they are annotated
+ * with {@link Nullable} in which case they can return {@code null} if no value is defined.
*/
private static class Attributes {
private final RuleContext ruleContext;
@@ -1000,31 +1033,6 @@ public final class ReleaseBundlingSupport {
this.ruleContext = ruleContext;
}
- @Nullable
- String appIcon() {
- return stringAttribute("app_icon");
- }
-
- @Nullable
- String launchImage() {
- return stringAttribute("launch_image");
- }
-
- @Nullable
- Artifact launchStoryboard() {
- return ruleContext.getPrerequisiteArtifact("launch_storyboard", Mode.TARGET);
- }
-
- @Nullable
- Artifact provisioningProfile() {
- Artifact explicitProvisioningProfile =
- ruleContext.getPrerequisiteArtifact("provisioning_profile", Mode.TARGET);
- if (explicitProvisioningProfile != null) {
- return explicitProvisioningProfile;
- }
- return ruleContext.getPrerequisiteArtifact(":default_provisioning_profile", Mode.TARGET);
- }
-
/**
* Returns this target's user-specified {@code ipa_post_processor} or null if not present.
*/
@@ -1096,10 +1104,6 @@ public final class ReleaseBundlingSupport {
return ruleContext.getExecutablePrerequisite("$environment_plist", Mode.HOST);
}
- String bundleId() {
- return checkNotNull(stringAttribute("bundle_id"));
- }
-
ImmutableMap<String, Artifact> cpuSpecificBreakpadFiles() {
ImmutableMap.Builder<String, Artifact> results = ImmutableMap.builder();
if (ruleContext.attributes().has("binary", BuildType.LABEL)) {
@@ -1119,12 +1123,6 @@ public final class ReleaseBundlingSupport {
}
return results.build();
}
-
- @Nullable
- private String stringAttribute(String attribute) {
- String value = ruleContext.attributes().get(attribute, Type.STRING);
- return value.isEmpty() ? null : value;
- }
}
/**