diff options
author | 2017-10-23 10:33:12 +0200 | |
---|---|---|
committer | 2017-10-23 17:16:23 +0200 | |
commit | 0446714686119dd97f8d1f99290f98db91a65e44 (patch) | |
tree | fbf58e2a2b1881299d5703066d6063a85fda4c73 /src/main/java/com/google/devtools/build/lib/rules/apple | |
parent | 61ccb61293030fec874303cf21e70eaf17a0aabb (diff) |
Automated rollback of commit f9a379157d1e992390c5b6f0b75ef853e0870689.
*** Reason for rollback ***
Breaks a single, but very important target :(
*** Original change description ***
Remove OS/Xcode versions (and thus package loading) from AppleConfiguration.Loader.
Fixes #3424.
RELNOTES[INC]: Selecting on "xcode_version" and
"{ios,tvos,macos,watchos}_sdk_version" is not supported anymore. What was config_setting(values={"$FOO_version": $VALUE}) is now config_setting(flag_values={"@bazel_tools//tools/osx:$FOO_version_flag": $VALUE}).
PiperOrigin-RevId: 173085962
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/apple')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java | 201 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java | 131 |
2 files changed, 309 insertions, 23 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java index cdd22ee85f..c445d1710f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java @@ -14,17 +14,22 @@ package com.google.devtools.build.lib.rules.apple; +import static com.google.devtools.build.lib.skyframe.serialization.SerializationCommonUtils.deserializeNullable; +import static com.google.devtools.build.lib.skyframe.serialization.SerializationCommonUtils.serializeNullable; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.lib.analysis.RuleContext; 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.ConfigurationEnvironment; import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; import com.google.devtools.build.lib.analysis.config.FragmentOptions; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions.AppleBitcodeMode; @@ -41,6 +46,8 @@ import com.google.protobuf.CodedOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Objects; import javax.annotation.Nullable; /** A configuration containing flags required for Apple platforms and tools. */ @@ -68,12 +75,23 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { */ public static final String APPLE_SDK_PLATFORM_ENV_NAME = "APPLE_SDK_PLATFORM"; + private static final DottedVersion MINIMUM_BITCODE_XCODE_VERSION = DottedVersion.fromString("7"); + /** Prefix for iOS cpu values. */ public static final String IOS_CPU_PREFIX = "ios_"; /** Default cpu for iOS builds. */ @VisibleForTesting static final String DEFAULT_IOS_CPU = "x86_64"; + @Nullable private final DottedVersion xcodeVersion; + private final DottedVersion iosSdkVersion; + private final DottedVersion iosMinimumOs; + private final DottedVersion watchosSdkVersion; + private final DottedVersion watchosMinimumOs; + private final DottedVersion tvosSdkVersion; + private final DottedVersion tvosMinimumOs; + private final DottedVersion macosSdkVersion; + private final DottedVersion macosMinimumOs; private final String iosCpu; private final String appleSplitCpu; private final PlatformType applePlatformType; @@ -92,8 +110,34 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { private final boolean objcProviderFromLinked; @VisibleForTesting - AppleConfiguration(AppleCommandLineOptions options, String iosCpu) { + AppleConfiguration( + AppleCommandLineOptions options, + String iosCpu, + @Nullable DottedVersion xcodeVersion, + DottedVersion iosSdkVersion, + DottedVersion iosMinimumOs, + DottedVersion watchosSdkVersion, + DottedVersion watchosMinimumOs, + DottedVersion tvosSdkVersion, + DottedVersion tvosMinimumOs, + DottedVersion macosSdkVersion, + DottedVersion macosMinimumOs) { this.options = options; + this.iosSdkVersion = Preconditions.checkNotNull(iosSdkVersion, "iosSdkVersion"); + this.iosMinimumOs = Preconditions.checkNotNull(iosMinimumOs, "iosMinimumOs"); + this.watchosSdkVersion = + Preconditions.checkNotNull(watchosSdkVersion, "watchOsSdkVersion"); + this.watchosMinimumOs = + Preconditions.checkNotNull(watchosMinimumOs, "watchOsMinimumOs"); + this.tvosSdkVersion = + Preconditions.checkNotNull(tvosSdkVersion, "tvOsSdkVersion"); + this.tvosMinimumOs = + Preconditions.checkNotNull(tvosMinimumOs, "tvOsMinimumOs"); + this.macosSdkVersion = + Preconditions.checkNotNull(macosSdkVersion, "macOsSdkVersion"); + this.macosMinimumOs = Preconditions.checkNotNull(macosMinimumOs, "macOsMinimumOs"); + + this.xcodeVersion = xcodeVersion; this.iosCpu = iosCpu; this.appleSplitCpu = Preconditions.checkNotNull(options.appleSplitCpu, "appleSplitCpu"); this.applePlatformType = @@ -133,6 +177,32 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { return options; } + /*** + * @deprecated use {@link XcodeConfig#getMinimumOsForPlatformType(RuleContext, PlatformType)}. + * + * <p>This is only here because the minimum OS version is currently part of the name of the output + * directory. + */ + @Deprecated + // Bug tracking the removal of this method: https://github.com/bazelbuild/bazel/issues/3424 + public DottedVersion getMinimumOsForPlatformType(PlatformType platformType) { + // TODO(b/37240784): Look into using only a single minimum OS flag tied to the current + // apple_platform_type. + switch (platformType) { + case IOS: + return iosMinimumOs; + case TVOS: + return tvosMinimumOs; + case WATCHOS: + return watchosMinimumOs; + case MACOS: + return macosMinimumOs; + default: + throw new IllegalArgumentException("Unhandled platform: " + platformType); + } + } + + /** * Returns a map of environment variables (derived from configuration) that should be propagated * for actions pertaining to building applications for apple platforms. These environment @@ -494,6 +564,23 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { } @Override + public Map<String, Object> lateBoundOptionDefaults() { + // xcode_version and *_sdk_version defaults come from processing the + // target with label given in --xcode_version_override. + ImmutableMap.Builder<String, Object> mapBuilder = ImmutableMap.builder(); + + if (xcodeVersion != null) { + mapBuilder.put("xcode_version", xcodeVersion.toString()); + } + return mapBuilder + .put("ios_sdk_version", iosSdkVersion) + .put("tvos_sdk_version", tvosSdkVersion) + .put("watchos_sdk_version", watchosSdkVersion) + .put("macos_sdk_version", macosSdkVersion) + .build(); + } + + @Override public boolean equals(Object obj) { if (this == obj) { return true; @@ -502,29 +589,124 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { return false; } AppleConfiguration that = (AppleConfiguration) obj; - return this.options.equals(that.options); + return this.options.equals(that.options) + && Objects.equals(this.xcodeVersion, that.xcodeVersion) + && this.iosSdkVersion.equals(that.iosSdkVersion) + && this.iosMinimumOs.equals(that.iosMinimumOs) + && this.watchosSdkVersion.equals(that.watchosSdkVersion) + && this.watchosMinimumOs.equals(that.watchosMinimumOs) + && this.tvosSdkVersion.equals(that.tvosSdkVersion) + && this.tvosMinimumOs.equals(that.tvosMinimumOs) + && this.macosSdkVersion.equals(that.macosSdkVersion) + && this.macosMinimumOs.equals(that.macosMinimumOs); } @Override public int hashCode() { - return options.hashCode(); + return Objects.hash( + options, + xcodeVersion, + iosSdkVersion, + iosMinimumOs, + watchosSdkVersion, + watchosMinimumOs, + tvosSdkVersion, + tvosMinimumOs, + macosSdkVersion, + macosMinimumOs); } void serialize(CodedOutputStream out) throws IOException, SerializationException { options.serialize(out); out.writeStringNoTag(iosCpu); + serializeNullable(xcodeVersion, out, DottedVersion.CODEC); + DottedVersion.CODEC.serialize(iosSdkVersion, out); + DottedVersion.CODEC.serialize(iosMinimumOs, out); + DottedVersion.CODEC.serialize(watchosSdkVersion, out); + DottedVersion.CODEC.serialize(watchosMinimumOs, out); + DottedVersion.CODEC.serialize(tvosSdkVersion, out); + DottedVersion.CODEC.serialize(tvosMinimumOs, out); + DottedVersion.CODEC.serialize(macosSdkVersion, out); + DottedVersion.CODEC.serialize(macosMinimumOs, out); } static AppleConfiguration deserialize(CodedInputStream in) throws IOException, SerializationException { AppleCommandLineOptions options = AppleCommandLineOptions.deserialize(in); String iosCpu = StringCodecs.asciiOptimized().deserialize(in); - return new AppleConfiguration(options, iosCpu); + DottedVersion xcodeVersion = deserializeNullable(in, DottedVersion.CODEC); + return new AppleConfiguration( + options, + iosCpu, + xcodeVersion, + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in), + DottedVersion.CODEC.deserialize(in)); } @VisibleForTesting - static AppleConfiguration create(AppleCommandLineOptions appleOptions, String cpu) { - return new AppleConfiguration(appleOptions, iosCpuFromCpu(cpu)); + static AppleConfiguration create( + AppleCommandLineOptions appleOptions, + String cpu, + XcodeVersionProperties xcodeVersionProperties) + throws InvalidConfigurationException { + DottedVersion iosSdkVersion = + (appleOptions.iosSdkVersion != null) + ? appleOptions.iosSdkVersion + : xcodeVersionProperties.getDefaultIosSdkVersion(); + DottedVersion iosMinimumOsVersion = + (appleOptions.iosMinimumOs != null) ? appleOptions.iosMinimumOs : iosSdkVersion; + DottedVersion watchosSdkVersion = + (appleOptions.watchOsSdkVersion != null) + ? appleOptions.watchOsSdkVersion + : xcodeVersionProperties.getDefaultWatchosSdkVersion(); + DottedVersion watchosMinimumOsVersion = + (appleOptions.watchosMinimumOs != null) ? appleOptions.watchosMinimumOs : watchosSdkVersion; + DottedVersion tvosSdkVersion = + (appleOptions.tvOsSdkVersion != null) + ? appleOptions.tvOsSdkVersion + : xcodeVersionProperties.getDefaultTvosSdkVersion(); + DottedVersion tvosMinimumOsVersion = + (appleOptions.tvosMinimumOs != null) ? appleOptions.tvosMinimumOs : tvosSdkVersion; + DottedVersion macosSdkVersion = + (appleOptions.macOsSdkVersion != null) + ? appleOptions.macOsSdkVersion + : xcodeVersionProperties.getDefaultMacosSdkVersion(); + DottedVersion macosMinimumOsVersion = + (appleOptions.macosMinimumOs != null) ? appleOptions.macosMinimumOs : macosSdkVersion; + AppleConfiguration configuration = + new AppleConfiguration( + appleOptions, + iosCpuFromCpu(cpu), + xcodeVersionProperties.getXcodeVersion().orNull(), + iosSdkVersion, + iosMinimumOsVersion, + watchosSdkVersion, + watchosMinimumOsVersion, + tvosSdkVersion, + tvosMinimumOsVersion, + macosSdkVersion, + macosMinimumOsVersion); + + validate(configuration); + return configuration; + } + + private static void validate(AppleConfiguration config) throws InvalidConfigurationException { + DottedVersion xcodeVersion = config.xcodeVersion; + if (config.getBitcodeMode() != AppleBitcodeMode.NONE + && xcodeVersion != null + && xcodeVersion.compareTo(MINIMUM_BITCODE_XCODE_VERSION) < 0) { + throw new InvalidConfigurationException( + String.format( + "apple_bitcode mode '%s' is unsupported for xcode version '%s'", + config.getBitcodeMode(), xcodeVersion)); + } } /** @@ -532,10 +714,13 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { */ public static class Loader implements ConfigurationFragmentFactory { @Override - public AppleConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) { + public AppleConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) + throws InvalidConfigurationException, InterruptedException { AppleCommandLineOptions appleOptions = buildOptions.get(AppleCommandLineOptions.class); String cpu = buildOptions.get(BuildConfiguration.Options.class).cpu; - return AppleConfiguration.create(appleOptions, cpu); + XcodeVersionProperties xcodeVersionProperties = XcodeConfig. + getXcodeVersionProperties(env, appleOptions); + return AppleConfiguration.create(appleOptions, cpu, xcodeVersionProperties); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java index 1b6e998d3c..7444c45bc0 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java @@ -15,25 +15,79 @@ package com.google.devtools.build.lib.rules.apple; import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.RedirectChaser; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions.AppleBitcodeMode; +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.packages.BuildType; +import com.google.devtools.build.lib.packages.NoSuchPackageException; +import com.google.devtools.build.lib.packages.NoSuchTargetException; +import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper; +import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.packages.Target; +import java.util.List; import java.util.Map; +import javax.annotation.Nullable; /** * Implementation for the {@code xcode_config} rule. */ public class XcodeConfig implements RuleConfiguredTargetFactory { - private static final DottedVersion MINIMUM_BITCODE_XCODE_VERSION = DottedVersion.fromString("7"); + + private static ImmutableList<XcodeVersionRuleData> getAvailableVersions( + ConfigurationEnvironment env, Rule xcodeConfigTarget) + throws InvalidConfigurationException, InterruptedException { + List<Label> xcodeVersionLabels = NonconfigurableAttributeMapper.of(xcodeConfigTarget) + .get(XcodeConfigRule.VERSIONS_ATTR_NAME, BuildType.LABEL_LIST); + ImmutableList.Builder<XcodeVersionRuleData> xcodeVersionRuleListBuilder = + ImmutableList.builder(); + for (Label label : xcodeVersionLabels) { + Rule xcodeVersionRule = getRuleForLabel(label, "xcode_version", env, "xcode_version"); + xcodeVersionRuleListBuilder.add(new XcodeVersionRuleData(label, xcodeVersionRule)); + } + return xcodeVersionRuleListBuilder.build(); + } + + /** + * Uses the {@link AppleCommandLineOptions#xcodeVersion} and {@link + * AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and return the + * effective xcode version properties. Returns absent if no explicit xcode version is declared, + * and host system defaults should be used. + * + * @param env the current configuration environment + * @param appleOptions the command line options + * @throws InvalidConfigurationException if the options given (or configuration targets) were + * malformed and thus the xcode version could not be determined + */ + static XcodeVersionProperties getXcodeVersionProperties( + ConfigurationEnvironment env, AppleCommandLineOptions appleOptions) + throws InvalidConfigurationException, InterruptedException { + Label xcodeVersionConfigLabel = appleOptions.xcodeVersionConfig; + + Rule xcodeConfigRule = getRuleForLabel( + xcodeVersionConfigLabel, "xcode_config", env, "xcode_version_config"); + + ImmutableList<XcodeVersionRuleData> versions = getAvailableVersions(env, xcodeConfigRule); + XcodeVersionRuleData defaultVersion = getDefaultVersion(env, xcodeConfigRule); + + try { + return resolveXcodeVersion(appleOptions.xcodeVersion, versions, defaultVersion); + } catch (XcodeConfigException e) { + throw new InvalidConfigurationException(e.getMessage()); + } + } /** * An exception that signals that an Xcode config setup was invalid. @@ -48,8 +102,8 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { - AppleConfiguration appleConfig = ruleContext.getFragment(AppleConfiguration.class); - AppleCommandLineOptions appleOptions = appleConfig.getOptions(); + AppleCommandLineOptions appleOptions = + ruleContext.getFragment(AppleConfiguration.class).getOptions(); XcodeVersionRuleData defaultVersion = ruleContext.getPrerequisite( XcodeConfigRule.DEFAULT_ATTR_NAME, RuleConfiguredTarget.Mode.TARGET, XcodeVersionRuleData.class); @@ -91,16 +145,6 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { macosSdkVersion, macosMinimumOsVersion, xcodeVersionProperties.getXcodeVersion().orNull()); - AppleBitcodeMode bitcodeMode = appleConfig.getBitcodeMode(); - DottedVersion xcodeVersion = xcodeVersions.getXcodeVersion(); - if (bitcodeMode != AppleBitcodeMode.NONE - && xcodeVersion != null - && xcodeVersion.compareTo(MINIMUM_BITCODE_XCODE_VERSION) < 0) { - ruleContext.throwWithRuleError(String.format( - "apple_bitcode mode '%s' is unsupported for xcode version '%s'", - bitcodeMode, xcodeVersion)); - } - return new RuleConfiguredTargetBuilder(ruleContext) .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY) .addNativeDeclaredProvider(xcodeVersions) @@ -182,6 +226,25 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { } /** + * Returns the default xcode version to use, if no {@code --xcode_version} command line flag was + * specified. + */ + @Nullable + private static XcodeVersionRuleData getDefaultVersion( + ConfigurationEnvironment env, Rule xcodeConfigTarget) + throws InvalidConfigurationException, InterruptedException { + Label defaultVersionLabel = NonconfigurableAttributeMapper.of(xcodeConfigTarget) + .get(XcodeConfigRule.DEFAULT_ATTR_NAME, BuildType.LABEL); + if (defaultVersionLabel != null) { + Rule defaultVersionRule = getRuleForLabel( + defaultVersionLabel, "xcode_version", env, "default xcode version"); + return new XcodeVersionRuleData(defaultVersionLabel, defaultVersionRule); + } else { + return null; + } + } + + /** * Returns a map where keys are "names" of xcode versions as defined by the configuration target, * and values are the rule data objects which contain information regarding that xcode version. * @@ -231,16 +294,54 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { } /** + * If the given label (following redirects) is a target for a rule of type {@code type}, then + * returns the {@link Rule} representing that target. Otherwise, throws a {@link + * InvalidConfigurationException}. + */ + static Rule getRuleForLabel( + Label label, String type, ConfigurationEnvironment env, String description) + throws InvalidConfigurationException, InterruptedException { + label = RedirectChaser.followRedirects(env, label, description); + + if (label == null) { + throw new InvalidConfigurationException(String.format( + "Expected value of %s (%s) to resolve to a target of type %s", + description, label, type)); + } + + try { + Target target = env.getTarget(label); + + if (target instanceof Rule && ((Rule) target).getRuleClass().equals(type)) { + return (Rule) target; + } else { + throw new InvalidConfigurationException(String.format( + "Expected value of %s (%s) to resolve to a target of type %s", + description, label, type)); + } + } catch (NoSuchPackageException | NoSuchTargetException exception) { + env.getEventHandler().handle(Event.error(exception.getMessage())); + throw new InvalidConfigurationException(exception); + } + } + + /** * Returns the minimum compatible OS version for target simulator and devices for a particular * platform type. */ public static DottedVersion getMinimumOsForPlatformType( RuleContext ruleContext, ApplePlatform.PlatformType platformType) { + AppleConfiguration config = ruleContext.getFragment(AppleConfiguration.class); XcodeConfigProvider versions = ruleContext.getPrerequisite( XcodeConfigRule.XCODE_CONFIG_ATTR_NAME, RuleConfiguredTarget.Mode.TARGET, XcodeConfigProvider.PROVIDER); - return versions.getMinimumOsForPlatformType(platformType); + DottedVersion fromProvider = versions.getMinimumOsForPlatformType(platformType); + DottedVersion fromConfig = config.getMinimumOsForPlatformType(platformType); + // This sanity check is there to keep this provider in sync with AppleConfiguration until the + // latter can be removed. Tracking bug: https://github.com/bazelbuild/bazel/issues/3424 + Preconditions.checkState(fromProvider.equals(fromConfig)); + return fromProvider; } /** |