blob: 509661d42144cee88ceffc28a9ec6159f0f86a4b [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.objc;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.FAMILIES_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.BUNDLE_ID_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.DEFAULT_PROVISIONING_PROFILE_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_STORYBOARD_ATTR;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.PROVISIONING_PROFILE_ATTR;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
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.RuleContext;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
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 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.
*
* @deprecated The native bundling rules have been deprecated. This class will be removed in the
* future.
*/
@Deprecated
@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;
private Artifact entitlements;
private Artifact extraEntitlements;
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 Builder setEntitlements(Artifact entitlements) {
this.entitlements = entitlements;
return this;
}
public ReleaseBundling build() {
Preconditions.checkNotNull(intermediateArtifacts, "intermediateArtifacts");
Preconditions.checkNotNull(families, FAMILIES_ATTR);
return new ReleaseBundling(
ipaArtifact,
bundleId,
primaryBundleId,
fallbackBundleId,
appIcon,
launchImage,
launchStoryboard,
provisioningProfile,
provisioningProfileAttributeName,
infoplistInputs.build(),
infoPlistsFromRule,
families,
intermediateArtifacts,
artifactPrefix,
entitlements,
extraEntitlements);
}
}
/**
* 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_ATTR, Type.STRING)),
"requires a bundle_id value");
String primaryBundleId = null;
String fallbackBundleId = null;
Artifact provisioningProfile;
if (ruleContext.attributes().isAttributeValueExplicitlySpecified(BUNDLE_ID_ATTR)) {
primaryBundleId = ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING);
} else {
fallbackBundleId = ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING);
}
Artifact explicitProvisioningProfile =
ruleContext.getPrerequisiteArtifact(PROVISIONING_PROFILE_ATTR, Mode.TARGET);
if (explicitProvisioningProfile != null) {
provisioningProfile = explicitProvisioningProfile;
} else {
provisioningProfile = ruleContext.getPrerequisiteArtifact(DEFAULT_PROVISIONING_PROFILE_ATTR,
Mode.TARGET);
}
ImmutableSet<TargetDeviceFamily> families = null;
List<String> rawFamilies = ruleContext.attributes().get(FAMILIES_ATTR, Type.STRING_LIST);
try {
families = ImmutableSet.copyOf(TargetDeviceFamily.fromNamesInRule(rawFamilies));
} catch (InvalidFamilyNameException | RepeatedFamilyNameException e) {
families = ImmutableSet.of();
}
if (families.isEmpty()) {
ruleContext.attributeError(FAMILIES_ATTR, INVALID_FAMILIES_ERROR);
}
return new ReleaseBundling.Builder()
.setIpaArtifact(ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA))
.setBundleId(ruleContext.attributes().get(BUNDLE_ID_ATTR, Type.STRING))
.setPrimaryBundleId(primaryBundleId)
.setFallbackBundleId(fallbackBundleId)
.setAppIcon(Strings.emptyToNull(ruleContext.attributes().get(APP_ICON_ATTR, Type.STRING)))
.setLaunchImage(Strings.emptyToNull(
ruleContext.attributes().get(LAUNCH_IMAGE_ATTR, Type.STRING)))
.setLaunchStoryboard(
ruleContext.getPrerequisiteArtifact(LAUNCH_STORYBOARD_ATTR, Mode.TARGET))
.setProvisioningProfile(provisioningProfile)
.setProvisioningProfileAttributeName(PROVISIONING_PROFILE_ATTR)
.setTargetDeviceFamilies(families)
.setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
.setEntitlements(ruleContext.getPrerequisiteArtifact("entitlements", Mode.TARGET))
.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 final Artifact entitlements;
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,
Artifact entitlements,
Artifact extraEntitlements) {
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;
this.entitlements = entitlements;
}
/**
* 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 {@link FAMILIES_ATTR} 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;
}
/**
* Returns an {@link Artifact} containing the entitlements used to sign this bundle for
* non-simulator builds; can be null.
*/
public Artifact getEntitlements() {
return entitlements;
}
}