diff options
author | Chris Parsons <cparsons@google.com> | 2016-01-29 22:27:40 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2016-02-01 09:45:54 +0000 |
commit | 4be631ec58ad8aacec12c7bca76865ee63eb5669 (patch) | |
tree | 7d747712bd55118585544a311ceee40f57b7c11c /src | |
parent | f941d56acfad5f8c819c81b494f806ea74ea7fd8 (diff) |
Redesign xcode_config rule to be evaluated at the level of configuration instead of target depss
--
MOS_MIGRATED_REVID=113398355
Diffstat (limited to 'src')
12 files changed, 229 insertions, 206 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java index 5ad748a217..de868a123f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleCommandLineOptions.java @@ -131,6 +131,7 @@ public class AppleCommandLineOptions extends FragmentOptions { if (getPlatform() == Platform.IOS_DEVICE) { labelMap.put("default_provisioning_profile", defaultProvisioningProfile); } + labelMap.put("xcode_version_config", xcodeVersionConfig); } /** @@ -193,6 +194,7 @@ public class AppleCommandLineOptions extends FragmentOptions { AppleCommandLineOptions host = (AppleCommandLineOptions) super.getHost(fallback); // Set options needed in the host configuration. + host.xcodeVersionConfig = xcodeVersionConfig; host.xcodeVersion = xcodeVersion; host.appleBitcodeMode = appleBitcodeMode; 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 73096ec15a..01265a618f 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 @@ -48,17 +48,20 @@ 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"); + private final DottedVersion iosSdkVersion; private final String iosCpu; - private final Optional<DottedVersion> xcodeVersionOverride; + private final Optional<DottedVersion> xcodeVersion; private final List<String> iosMultiCpus; private final AppleBitcodeMode bitcodeMode; private final Label xcodeConfigLabel; @Nullable private final Label defaultProvisioningProfileLabel; - AppleConfiguration(AppleCommandLineOptions appleOptions) { + AppleConfiguration(AppleCommandLineOptions appleOptions, + Optional<DottedVersion> xcodeVersionOverride) { this.iosSdkVersion = Preconditions.checkNotNull(appleOptions.iosSdkVersion, "iosSdkVersion"); - this.xcodeVersionOverride = Optional.fromNullable(appleOptions.xcodeVersion); + this.xcodeVersion = Preconditions.checkNotNull(xcodeVersionOverride); this.iosCpu = Preconditions.checkNotNull(appleOptions.iosCpu, "iosCpu"); this.iosMultiCpus = Preconditions.checkNotNull(appleOptions.iosMultiCpus, "iosMultiCpus"); this.bitcodeMode = appleOptions.appleBitcodeMode; @@ -76,14 +79,12 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { } /** - * Returns the value of the xcode version build flag if available. This is obtained directly from - * the {@code --xcode_version} build flag. - * - * <p>Most rules should avoid using this flag value, and instead obtain the appropriate xcode - * version from {@link XcodeConfigProvider#getXcodeVersion}. + * Returns the value of the xcode version, if available. This is determined based on a combination + * of the {@code --xcode_version} build flag and the {@code xcode_config} target defined in the + * {@code --xcode_version_config} flag. */ - public Optional<DottedVersion> getXcodeVersionOverrideFlag() { - return xcodeVersionOverride; + public Optional<DottedVersion> getXcodeVersion() { + return xcodeVersion; } /** @@ -97,6 +98,20 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { mapBuilder.putAll(appleTargetPlatformEnv(Platform.forIosArch(getIosCpu()))); return mapBuilder.build(); } + + /** + * Returns a map of environment variables that should be propagated for actions that build on an + * apple host system. These environment variables are needed by the apple toolchain. Keys are + * variable names and values are their corresponding values. + */ + public Map<String, String> getAppleHostSystemEnv() { + Optional<DottedVersion> xcodeVersion = getXcodeVersion(); + ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + if (xcodeVersion.isPresent()) { + builder.put(AppleConfiguration.XCODE_VERSION_ENV_NAME, xcodeVersion.get().toString()); + } + return builder.build(); + } /** * Returns a map of environment variables (derived from configuration) that should be propagated @@ -198,8 +213,23 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { public AppleConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions) throws InvalidConfigurationException { AppleCommandLineOptions appleOptions = buildOptions.get(AppleCommandLineOptions.class); + Optional<DottedVersion> xcodeVersionFlag = getXcodeVersion(env, appleOptions); + AppleConfiguration configuration = new AppleConfiguration(appleOptions, xcodeVersionFlag); - return new AppleConfiguration(appleOptions); + validate(configuration); + return configuration; + } + + private void validate(AppleConfiguration config) + throws InvalidConfigurationException { + Optional<DottedVersion> xcodeVersion = config.getXcodeVersion(); + if (config.getBitcodeMode() != AppleBitcodeMode.NONE + && xcodeVersion.isPresent() + && xcodeVersion.get().compareTo(MINIMUM_BITCODE_XCODE_VERSION) < 0) { + throw new InvalidConfigurationException( + String.format("apple_bitcode mode '%s' is unsupported for xcode version '%s'", + config.getBitcodeMode(), xcodeVersion.get())); + } } @Override @@ -211,5 +241,26 @@ public class AppleConfiguration extends BuildConfiguration.Fragment { public ImmutableSet<Class<? extends FragmentOptions>> requiredOptions() { return ImmutableSet.<Class<? extends FragmentOptions>>of(AppleCommandLineOptions.class); } + + /** + * Uses the {@link AppleCommandLineOptions#xcodeVersion} and + * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and + * return the effective xcode version. 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 + */ + private Optional<DottedVersion> getXcodeVersion(ConfigurationEnvironment env, + AppleCommandLineOptions appleOptions) throws InvalidConfigurationException { + Optional<DottedVersion> xcodeVersionCommandLineFlag = + Optional.fromNullable(appleOptions.xcodeVersion); + Label xcodeVersionConfigLabel = appleOptions.xcodeVersionConfig; + + return XcodeConfig.resolveXcodeVersion(env, xcodeVersionConfigLabel, + xcodeVersionCommandLineFlag, "xcode_version_config"); + } } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java index e05b686760..bf55f10a67 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java @@ -20,7 +20,6 @@ import static com.google.devtools.build.lib.packages.BuildType.LABEL; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.analysis.RuleDefinition; @@ -34,8 +33,6 @@ import com.google.devtools.build.lib.packages.RuleClass.Builder; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.XcodeprojBuildSetting; -import java.util.Map; - /** * Utility class for resolving items for the Apple toolchain (such as common tool flags, and paths). */ @@ -168,25 +165,7 @@ public class AppleToolchain { } }); } - - /** - * Returns a map of environment variables (derived from configuration) that should be propagated - * for actions that build on an apple host system. These environment variables are needed by - * the apple toolchain. Keys are variable names and values are their corresponding values. - * - * @param configProvider info derived from the {@code xcode_config} rule targeted by the label - * of the build flag {@code --xcode_config} - */ - public static Map<String, String> appleHostSystemEnv(XcodeConfigProvider configProvider) { - Preconditions.checkNotNull(configProvider); - ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); - if (configProvider.getXcodeVersion().isPresent()) { - builder.put(AppleConfiguration.XCODE_VERSION_ENV_NAME, - configProvider.getXcodeVersion().get().toString()); - } - return builder.build(); - } - + /** * Base rule definition to be ancestor for rules which may require an xcode toolchain. */ 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 eb789b3c50..1740a12de1 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 @@ -14,21 +14,28 @@ package com.google.devtools.build.lib.rules.apple; -import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; - import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.google.devtools.build.lib.analysis.ConfiguredTarget; -import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RedirectChaser; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; 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.cmdline.Label; +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 com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; -import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions.AppleBitcodeMode; +import com.google.devtools.build.lib.syntax.Type; +import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -38,43 +45,40 @@ import javax.annotation.Nullable; */ public class XcodeConfig implements RuleConfiguredTargetFactory { - private static final DottedVersion MINIMUM_BITCODE_XCODE_VERSION = DottedVersion.fromString("7"); - @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException { - AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class); - Optional<DottedVersion> versionOverrideFlag = configuration.getXcodeVersionOverrideFlag(); - - DottedVersion targetVersion = resolveExplicitlyDefinedVersion(ruleContext); - - XcodeConfigProvider xcodeConfigProvider; - if (targetVersion == null) { - if (versionOverrideFlag.isPresent()) { - xcodeConfigProvider = new XcodeConfigProvider(versionOverrideFlag.get()); - } else { - xcodeConfigProvider = XcodeConfigProvider.hostSystemDefault(); - } - } else { - xcodeConfigProvider = new XcodeConfigProvider(targetVersion); - } - - validateXcodeConfig(ruleContext, configuration, xcodeConfigProvider); - return new RuleConfiguredTargetBuilder(ruleContext) .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY) - .addProvider(XcodeConfigProvider.class, xcodeConfigProvider) .build(); } - - private void validateXcodeConfig(RuleContext ruleContext, AppleConfiguration config, - XcodeConfigProvider xcodeConfigProvider) { - Optional<DottedVersion> xcodeVersion = xcodeConfigProvider.getXcodeVersion(); - if (config.getBitcodeMode() != AppleBitcodeMode.NONE - && xcodeVersion.isPresent() - && xcodeVersion.get().compareTo(MINIMUM_BITCODE_XCODE_VERSION) < 0) { - ruleContext.ruleError( - String.format("apple_bitcode mode '%s' is unsupported for xcode version '%s'", - config.getBitcodeMode(), xcodeVersion.get())); + + /** + * Uses the {@link AppleCommandLineOptions#xcodeVersion} and + * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and + * return the effective xcode version. + * + * @param env the current configuration environment + * @param xcodeConfigLabel the label for the xcode_config target to parse + * @param xcodeVersionOverrideFlag the value of the command line flag to override the default + * xcode version, absent if unspecified + * @param errorDescription a description of the origin of {@code #xcodeConfigLabel} for messaging + * parse errors + * @throws InvalidConfigurationException if the options given (or configuration targets) were + * malformed and thus the xcode version could not be determined + */ + public static Optional<DottedVersion> resolveXcodeVersion(ConfigurationEnvironment env, + Label xcodeConfigLabel, Optional<DottedVersion> xcodeVersionOverrideFlag, + String errorDescription) throws InvalidConfigurationException { + Rule xcodeConfigRule = + getRuleForLabel(xcodeConfigLabel, "xcode_config", env, errorDescription); + + DottedVersion dottedVersion = + resolveExplicitlyDefinedVersion(env, xcodeConfigRule, xcodeVersionOverrideFlag); + + if (dottedVersion != null) { + return Optional.of(dottedVersion); + } else { + return xcodeVersionOverrideFlag; } } @@ -83,70 +87,126 @@ public class XcodeConfig implements RuleConfiguredTargetFactory { * is an available {@code xcode_version} target which recognizes the flag value as either * an official version or an alias. Returns null if no such target is found. */ - @Nullable private DottedVersion resolveExplicitlyDefinedVersion(RuleContext ruleContext) { - AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class); - Optional<DottedVersion> versionOverrideFlag = configuration.getXcodeVersionOverrideFlag(); + @Nullable private static DottedVersion resolveExplicitlyDefinedVersion( + ConfigurationEnvironment env, Rule xcodeConfigTarget, + Optional<DottedVersion> versionOverrideFlag) throws InvalidConfigurationException { if (versionOverrideFlag.isPresent()) { // The version override flag is not necessarily an actual version - it may be a version // alias. - DottedVersion explicitVerison = - aliasesToVersionMap(ruleContext).get(versionOverrideFlag.get().toString()); - if (explicitVerison != null) { - return explicitVerison; + DottedVersion explicitVersion = + aliasesToVersionMap(env, xcodeConfigTarget).get(versionOverrideFlag.get().toString()); + if (explicitVersion != null) { + return explicitVersion; } } else { // No override specified. Use default. - XcodeVersionProvider defaultProvider = ruleContext.getPrerequisite( - XcodeConfigRule.DEFAULT_ATTR_NAME, Mode.TARGET, XcodeVersionProvider.class); - - if (defaultProvider != null) { - return defaultProvider.getVersion(); + DottedVersion defaultVersion = getDefaultVersion(env, xcodeConfigTarget); + + if (defaultVersion != null) { + return defaultVersion; } } - - boolean requireDefinedVersions = ruleContext.attributes().get( - XcodeConfigRule.REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN); + + boolean requireDefinedVersions = NonconfigurableAttributeMapper.of(xcodeConfigTarget) + .get(XcodeConfigRule.REQUIRE_DEFINED_VERSIONS_ATTR_NAME, Type.BOOLEAN); if (requireDefinedVersions) { - ruleContext.ruleError( + throw new InvalidConfigurationException( "xcode version config required an explicitly defined version, but none was available"); } return null; } - private static Map<String, DottedVersion> aliasesToVersionMap(RuleContext ruleContext) { - Iterable<XcodeVersionProvider> xcodeVersionProviders = - ruleContext.getPrerequisites(XcodeConfigRule.VERSIONS_ATTR_NAME, Mode.TARGET, - XcodeVersionProvider.class); + /** + * Returns the default xcode version to use, if no {@code --xcode_version} command line flag + * was specified. + */ + @Nullable private static DottedVersion getDefaultVersion(ConfigurationEnvironment env, + Rule xcodeConfigTarget) throws InvalidConfigurationException { + 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).getVersion(); + } else { + return null; + } + } + + private static Map<String, DottedVersion> aliasesToVersionMap(ConfigurationEnvironment env, + Rule xcodeConfigTarget) throws InvalidConfigurationException { + 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)); + } + ImmutableList<XcodeVersionRuleData> xcodeVersionRules = xcodeVersionRuleListBuilder.build(); Map<String, DottedVersion> aliasesToVersionMap = Maps.newLinkedHashMap(); - for (XcodeVersionProvider versionProvider : xcodeVersionProviders) { - for (String alias : versionProvider.getAliases()) { - if (aliasesToVersionMap.put(alias, versionProvider.getVersion()) != null) { - ruleErrorDuplicateAlias(alias, ruleContext); + for (XcodeVersionRuleData xcodeVersionRule : xcodeVersionRules) { + for (String alias : xcodeVersionRule.getAliases()) { + if (aliasesToVersionMap.put(alias, xcodeVersionRule.getVersion()) != null) { + configErrorDuplicateAlias(alias, xcodeVersionRules); } } if (aliasesToVersionMap.put( - versionProvider.getVersion().toString(), versionProvider.getVersion()) != null) { - ruleErrorDuplicateAlias(versionProvider.getVersion().toString(), ruleContext); + xcodeVersionRule.getVersion().toString(), xcodeVersionRule.getVersion()) != null) { + configErrorDuplicateAlias(xcodeVersionRule.getVersion().toString(), xcodeVersionRules); } } return aliasesToVersionMap; } - private static void ruleErrorDuplicateAlias(String alias, RuleContext ruleContext) { - Iterable<XcodeVersionProvider> xcodeVersionProviders = - ruleContext.getPrerequisites(XcodeConfigRule.VERSIONS_ATTR_NAME, Mode.TARGET, - XcodeVersionProvider.class); - + /** + * Convenience method for throwing an {@link InvalidConfigurationException} due to presence + * of duplicate aliases in an {@code xcode_config} target definition. + */ + private static void configErrorDuplicateAlias(String alias, + List<XcodeVersionRuleData> xcodeVersionRules) throws InvalidConfigurationException { + ImmutableList.Builder<Label> labelsContainingAlias = ImmutableList.builder(); - for (XcodeVersionProvider versionProvider : xcodeVersionProviders) { - if (versionProvider.getAliases().contains(alias) - || versionProvider.getVersion().toString().equals(alias)) { - labelsContainingAlias.add(versionProvider.getLabel()); + for (XcodeVersionRuleData xcodeVersionRule : xcodeVersionRules) { + if (xcodeVersionRule.getAliases().contains(alias) + || xcodeVersionRule.getVersion().toString().equals(alias)) { + labelsContainingAlias.add(xcodeVersionRule.getLabel()); + } + } + + throw new InvalidConfigurationException( + String.format("'%s' is registered to multiple labels (%s) in a single xcode_config rule", + alias, Joiner.on(", ").join(labelsContainingAlias.build()))); + } + + /** + * 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}. + */ + private static Rule getRuleForLabel(Label label, String type, ConfigurationEnvironment env, + String description) throws InvalidConfigurationException { + 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) { + throw new InvalidConfigurationException(exception); } - ruleContext.ruleError(String.format( - "'%s' is registered to multiple labels (%s) in a single xcode version " - + "configuration", alias, Joiner.on(", ").join(labelsContainingAlias.build()))); } }
\ No newline at end of file diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java deleted file mode 100644 index 5241e04867..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2015 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.apple; - -import com.google.common.base.Optional; -import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; -import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; - -/** - * Provides a version of xcode based on a combination of the {@code --xcode_version} build flag - * and a {@code xcode_config} target. This version of xcode should be used for selecting apple - * toolchains and SDKs. - */ -@Immutable -public final class XcodeConfigProvider implements TransitiveInfoProvider { - private final Optional<DottedVersion> xcodeVersion; - - XcodeConfigProvider(DottedVersion xcodeVersion) { - this.xcodeVersion = Optional.of(xcodeVersion); - } - - private XcodeConfigProvider() { - this.xcodeVersion = Optional.absent(); - } - - /** - * Returns a {@link XcodeConfigProvider} with no xcode version specified. The host system - * default xcode should be used. See {@link #getXcodeVersion}. - */ - static XcodeConfigProvider hostSystemDefault() { - return new XcodeConfigProvider(); - } - - /** - * Returns either an explicit xcode version which should be used in actions which require an - * apple toolchain, or {@link Optional#absent} if the host system default should be used. - */ - public Optional<DottedVersion> getXcodeVersion() { - return xcodeVersion; - } -} diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java index 58275f034f..ecfb643458 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfigRule.java @@ -47,7 +47,8 @@ public class XcodeConfigRule implements RuleDefinition { <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ .add(attr(DEFAULT_ATTR_NAME, LABEL) .allowedRuleClasses("xcode_version") - .allowedFileTypes()) + .allowedFileTypes() + .nonconfigurable("this rule determines configuration")) /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) --> Accepted <code>xcode_version<code> targets that may be used. If the value of the <code>xcode_version</code> build flag matches one of the aliases @@ -56,14 +57,17 @@ public class XcodeConfigRule implements RuleDefinition { <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ .add(attr(VERSIONS_ATTR_NAME, LABEL_LIST) .allowedRuleClasses("xcode_version") - .allowedFileTypes()) + .allowedFileTypes() + .nonconfigurable("this rule determines configuration")) /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) --> Whether to require the build's xcode version match one of the declared targets. If true, this will raise an error if either the <code>xcode_version</code> flag value or <code>default</code> attribute value do not match one of the versions declared among <code>xcode_verison</code> targets. <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ - .add(attr(REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN).value(false)) + .add(attr(REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN) + .value(false) + .nonconfigurable("this rule determines configuration")) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java index 2b363e6c62..f7e321f285 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersion.java @@ -14,17 +14,12 @@ package com.google.devtools.build.lib.rules.apple; -import static com.google.devtools.build.lib.syntax.Type.STRING; -import static com.google.devtools.build.lib.syntax.Type.STRING_LIST; - import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; -import java.util.List; - /** * Implementation for the {@code xcode_version} rule. */ @@ -32,15 +27,8 @@ public class XcodeVersion implements RuleConfiguredTargetFactory { @Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException { - DottedVersion version = DottedVersion.fromString( - ruleContext.attributes().get(XcodeVersionRule.VERSION_ATTR_NAME, STRING)); - List<String> aliases = - ruleContext.attributes().get(XcodeVersionRule.ALIASES_ATTR_NAME, STRING_LIST); - return new RuleConfiguredTargetBuilder(ruleContext) .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY) - .addProvider(XcodeVersionProvider.class, - new XcodeVersionProvider(ruleContext.getLabel(), version, aliases)) .build(); } }
\ No newline at end of file diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java index d78337bcdf..f6e8274902 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRule.java @@ -41,13 +41,16 @@ public class XcodeVersionRule implements RuleDefinition { /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) --> The official version number of a version of Xcode. <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ - .add(attr(VERSION_ATTR_NAME, STRING).mandatory()) + .add(attr(VERSION_ATTR_NAME, STRING) + .mandatory() + .nonconfigurable("this rule determines configuration")) /* <!-- #BLAZE_RULE(proto_library).ATTRIBUTE(version) --> Accepted aliases for this version of Xcode. If the value of the <code>xcode_version</code> build flag matches any of the given alias strings, this xcode version will be used. <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ - .add(attr(ALIASES_ATTR_NAME, STRING_LIST)) + .add(attr(ALIASES_ATTR_NAME, STRING_LIST) + .nonconfigurable("this rule determines configuration")) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProvider.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java index f7b15b60d6..02bf38dc48 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java @@ -15,30 +15,35 @@ package com.google.devtools.build.lib.rules.apple; import com.google.common.collect.ImmutableList; -import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper; +import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.syntax.Type; import java.util.List; /** - * Provides the information in a single {@code xcode_version} target. A single target of this rule - * contains an official version label decided by Apple and a number of supported aliases one might - * use to reference this version. + * A tuple containing the information in a single target of the {@code xcode_version} rule. + * A single target of this rule contains an official version label decided by Apple and a number + * of supported aliases one might use to reference this version. * * <p>For example, one may want to reference official xcode version 7.0.1 using the "7" or * "7.0" aliases. */ -@Immutable -public final class XcodeVersionProvider implements TransitiveInfoProvider { +public class XcodeVersionRuleData { private final Label label; private final DottedVersion version; private final ImmutableList<String> aliases; - - XcodeVersionProvider(Label label, DottedVersion version, List<String> aliases) { + + XcodeVersionRuleData(Label label, Rule rule) { + NonconfigurableAttributeMapper attrMapper = + NonconfigurableAttributeMapper.of(rule); + this.label = label; - this.version = version; - this.aliases = ImmutableList.copyOf(aliases); + this.version = DottedVersion.fromString( + attrMapper.get(XcodeVersionRule.VERSION_ATTR_NAME, Type.STRING)); + this.aliases = ImmutableList.copyOf( + attrMapper.get(XcodeVersionRule.ALIASES_ATTR_NAME, Type.STRING_LIST)); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java index 54bfe47c41..01d1899595 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java @@ -36,7 +36,6 @@ import com.google.devtools.build.lib.actions.PackageRootResolver; import com.google.devtools.build.lib.actions.ResourceSet; import com.google.devtools.build.lib.actions.extra.CppCompileInfo; import com.google.devtools.build.lib.actions.extra.ExtraActionInfo; -import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; 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.PerLabelOptions; @@ -51,9 +50,7 @@ import com.google.devtools.build.lib.events.EventKind; import com.google.devtools.build.lib.profiler.Profiler; import com.google.devtools.build.lib.profiler.ProfilerTask; 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.apple.XcodeConfigProvider; import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; import com.google.devtools.build.lib.rules.cpp.CppCompileActionContext.Reply; import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool; @@ -157,9 +154,6 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable private final Iterable<IncludeScannable> lipoScannables; private final CppCompileCommandLine cppCompileCommandLine; private final boolean usePic; - // TODO(bazel-team): Needed for lazily evaluating xcode configuration attribute. Remove when - // this logic is refactored into crosstool expansion. - private final RuleContext ruleContext; @VisibleForTesting final CppConfiguration cppConfiguration; @@ -274,7 +268,6 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable this.lipoScannables = lipoScannables; this.actionClassId = actionClassId; this.usePic = usePic; - this.ruleContext = ruleContext; // We do not need to include the middleman artifact since it is a generated // artifact and will definitely exist prior to this action execution. @@ -612,9 +605,7 @@ public class CppCompileAction extends AbstractAction implements IncludeScannable // evaluation here. AppleConfiguration appleConfiguration = configuration.getFragment(AppleConfiguration.class); if (CppConfiguration.MAC_SYSTEM_NAME.equals(getHostSystemName())) { - XcodeConfigProvider xcodeConfigProvider = - ruleContext.getPrerequisite(":xcode_config", Mode.HOST, XcodeConfigProvider.class); - environment.putAll(AppleToolchain.appleHostSystemEnv(xcodeConfigProvider)); + environment.putAll(appleConfiguration.getAppleHostSystemEnv()); } if (Platform.isApplePlatform(cppConfiguration.getTargetCpu())) { environment.putAll(appleConfiguration.appleTargetPlatformEnv( 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 99c880f8b6..23acbd12ad 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 @@ -53,7 +53,6 @@ import com.google.devtools.build.lib.rules.apple.AppleToolchain; import com.google.devtools.build.lib.rules.apple.AppleToolchain.RequiresXcodeConfigRule; import com.google.devtools.build.lib.rules.apple.DottedVersion; import com.google.devtools.build.lib.rules.apple.Platform; -import com.google.devtools.build.lib.rules.apple.XcodeConfigProvider; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; import com.google.devtools.build.lib.util.FileTypeSet; @@ -165,12 +164,10 @@ public class ObjcRuleClasses { */ static SpawnAction.Builder spawnXcrunActionBuilder(RuleContext ruleContext) { AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); - XcodeConfigProvider xcodeConfigProvider = - ruleContext.getPrerequisite(":xcode_config", Mode.HOST, XcodeConfigProvider.class); ImmutableMap.Builder<String, String> envBuilder = ImmutableMap.<String, String>builder() .putAll(appleConfiguration.getEnvironmentForIosAction()) - .putAll(AppleToolchain.appleHostSystemEnv(xcodeConfigProvider)); + .putAll(appleConfiguration.getAppleHostSystemEnv()); return spawnOnDarwinActionBuilder() .setEnvironment(envBuilder.build()); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java index aca9e11dd5..ce49995630 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java @@ -32,8 +32,6 @@ import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Su import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; 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.XcodeConfigProvider; import com.google.devtools.build.lib.rules.test.TestEnvironmentProvider; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; @@ -234,13 +232,11 @@ public class TestSupport { */ public Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> getExtraProviders() { AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class); - XcodeConfigProvider xcodeConfigProvider = - ruleContext.getPrerequisite(":xcode_config", Mode.HOST, XcodeConfigProvider.class); ImmutableMap.Builder<String, String> envBuilder = ImmutableMap.builder(); envBuilder.putAll(configuration.getEnvironmentForIosAction()); - envBuilder.putAll(AppleToolchain.appleHostSystemEnv(xcodeConfigProvider)); + envBuilder.putAll(configuration.getAppleHostSystemEnv()); if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { envBuilder.put("COVERAGE_GCOV_PATH", |