Use platform mappings. Applying platform mapping to all BuildConfigurationValue.Key instances. This will cause all configurations to apply the platform mapping before being loaded. Step 7/N towards the platforms mapping functionality for https://github.com/bazelbuild/bazel/issues/6426 RELNOTES: New platform_mappings ability to allow gradual flag to platforms/toolchains migration. See also https://github.com/bazelbuild/bazel/issues/6426 PiperOrigin-RevId: 244731653
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java index e99e9a7..9f224bb 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisUtils.java
@@ -22,6 +22,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; import com.google.devtools.build.lib.analysis.config.ConfigurationResolver; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.config.TransitionResolver; import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition; import com.google.devtools.build.lib.analysis.config.transitions.NoTransition; @@ -183,7 +184,8 @@ Collection<Target> targets, ExtendedEventHandler eventHandler, ConfiguredRuleClassProvider ruleClassProvider, - SkyframeExecutor skyframeExecutor) { + SkyframeExecutor skyframeExecutor) + throws InvalidConfigurationException { // We use a hash set here to remove duplicate nodes; this can happen for input files and package // groups. LinkedHashSet<TargetAndConfiguration> nodes = new LinkedHashSet<>(targets.size());
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java index d71e03c..6adfaae6 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java
@@ -30,6 +30,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.Dependency; import com.google.devtools.build.lib.analysis.DependencyResolver.DependencyKind; +import com.google.devtools.build.lib.analysis.PlatformOptions; import com.google.devtools.build.lib.analysis.TargetAndConfiguration; import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition; import com.google.devtools.build.lib.analysis.config.transitions.NoTransition; @@ -47,14 +48,17 @@ import com.google.devtools.build.lib.skyframe.BuildConfigurationValue; import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction; import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue; +import com.google.devtools.build.lib.skyframe.PlatformMappingValue; import com.google.devtools.build.lib.skyframe.SkyframeExecutor; import com.google.devtools.build.lib.skyframe.TransitiveTargetKey; import com.google.devtools.build.lib.skyframe.TransitiveTargetValue; import com.google.devtools.build.lib.util.OrderedSetMultimap; +import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException; +import com.google.devtools.common.options.OptionsParsingException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -261,20 +265,38 @@ } // If we get here, we have to get the configuration from Skyframe. - for (BuildOptions options : toOptions) { - if (sameFragments) { - keysToEntries.put( - BuildConfigurationValue.key( - currentConfiguration.fragmentClasses(), - BuildOptions.diffForReconstruction(defaultBuildOptions, options)), - depsEntry); + PathFragment platformMappingPath = + currentConfiguration.getOptions().get(PlatformOptions.class).platformMappings; + PlatformMappingValue platformMappingValue = + (PlatformMappingValue) env.getValue(PlatformMappingValue.Key.create(platformMappingPath)); + if (platformMappingValue == null) { + return null; + } - } else { - keysToEntries.put( - BuildConfigurationValue.key( - depFragments, BuildOptions.diffForReconstruction(defaultBuildOptions, options)), - depsEntry); + try { + for (BuildOptions options : toOptions) { + if (sameFragments) { + keysToEntries.put( + BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + currentConfiguration.fragmentClasses(), + BuildOptions.diffForReconstruction(defaultBuildOptions, options)), + depsEntry); + + } else { + keysToEntries.put( + BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + depFragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, options)), + depsEntry); + } } + } catch (OptionsParsingException e) { + throw new ConfiguredTargetFunction.DependencyEvaluationException( + new InvalidConfigurationException(e)); } } @@ -631,7 +653,8 @@ Iterable<TargetAndConfiguration> defaultContext, Multimap<BuildConfiguration, Dependency> targetsToEvaluate, ExtendedEventHandler eventHandler, - SkyframeExecutor skyframeExecutor) { + SkyframeExecutor skyframeExecutor) + throws InvalidConfigurationException { Map<Label, Target> labelsToTargets = new LinkedHashMap<>(); for (TargetAndConfiguration targetAndConfig : defaultContext) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationValue.java index 90479a9..924a601 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationValue.java
@@ -26,10 +26,10 @@ import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; +import com.google.devtools.common.options.OptionsParsingException; import java.io.Serializable; import java.util.Objects; import java.util.Set; -import java.util.logging.Logger; /** A Skyframe value representing a {@link BuildConfiguration}. */ // TODO(bazel-team): mark this immutable when BuildConfiguration is immutable. @@ -37,7 +37,6 @@ @AutoCodec @ThreadSafe public class BuildConfigurationValue implements SkyValue { - private static final Logger logger = Logger.getLogger(BuildConfigurationValue.class.getName()); private final BuildConfiguration configuration; BuildConfigurationValue(BuildConfiguration configuration) { @@ -49,14 +48,61 @@ } /** + * Creates a new configuration key based on the given diff, after applying a platform mapping + * transformation. + * + * @param platformMappingValue sky value that can transform a configuration key based on a + * platform mapping + * @param defaultBuildOptions set of native build options without modifications based on parsing + * flags + * @param fragments set of options fragments this configuration should cover + * @param optionsDiff diff between the default options and the desired configuration + * @throws OptionsParsingException if the platform mapping cannot be parsed + */ + public static Key keyWithPlatformMapping( + PlatformMappingValue platformMappingValue, + BuildOptions defaultBuildOptions, + FragmentClassSet fragments, + BuildOptions.OptionsDiffForReconstruction optionsDiff) + throws OptionsParsingException { + return platformMappingValue.map( + keyWithoutPlatformMapping(fragments, optionsDiff), defaultBuildOptions); + } + + /** + * Creates a new configuration key based on the given diff, after applying a platform mapping + * transformation. + * + * @param platformMappingValue sky value that can transform a configuration key based on a + * platform mapping + * @param defaultBuildOptions set of native build options without modifications based on parsing + * flags + * @param fragments set of options fragments this configuration should cover + * @param optionsDiff diff between the default options and the desired configuration + * @throws OptionsParsingException if the platform mapping cannot be parsed + */ + public static Key keyWithPlatformMapping( + PlatformMappingValue platformMappingValue, + BuildOptions defaultBuildOptions, + Set<Class<? extends BuildConfiguration.Fragment>> fragments, + BuildOptions.OptionsDiffForReconstruction optionsDiff) + throws OptionsParsingException { + return platformMappingValue.map( + keyWithoutPlatformMapping(fragments, optionsDiff), defaultBuildOptions); + } + + /** * Returns the key for a requested configuration. * + * <p>Callers are responsible for applying the platform mapping or ascertaining that a platform + * mapping is not required. + * * @param fragments the fragments the configuration should contain * @param optionsDiff the {@link BuildOptions.OptionsDiffForReconstruction} object the {@link * BuildOptions} should be rebuilt from */ @ThreadSafe - public static Key key( + static Key keyWithoutPlatformMapping( Set<Class<? extends BuildConfiguration.Fragment>> fragments, BuildOptions.OptionsDiffForReconstruction optionsDiff) { return Key.create( @@ -65,13 +111,23 @@ optionsDiff); } - public static Key key( + private static Key keyWithoutPlatformMapping( FragmentClassSet fragmentClassSet, BuildOptions.OptionsDiffForReconstruction optionsDiff) { return Key.create(fragmentClassSet, optionsDiff); } + /** + * Returns a configuration key for the given configuration. + * + * <p>Note that this key creation method does not apply a platform mapping, it is assumed that the + * passed configuration was created with one such and thus its key does not need to be mapped + * again. + * + * @param buildConfiguration configuration whose key is requested + */ public static Key key(BuildConfiguration buildConfiguration) { - return key(buildConfiguration.fragmentClasses(), buildConfiguration.getBuildOptionsDiff()); + return keyWithoutPlatformMapping( + buildConfiguration.fragmentClasses(), buildConfiguration.getBuildOptionsDiff()); } /** {@link SkyKey} for {@link BuildConfigurationValue}. */
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java index db9fb4c..9f37b18 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingValue.java
@@ -228,7 +228,7 @@ } } - return BuildConfigurationValue.key( + return BuildConfigurationValue.keyWithoutPlatformMapping( original.getFragments(), BuildOptions.diffForReconstruction(defaultBuildOptions, modifiedOptions)); }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareAnalysisPhaseFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareAnalysisPhaseFunction.java index 98850f4..06fed8a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareAnalysisPhaseFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareAnalysisPhaseFunction.java
@@ -23,6 +23,7 @@ import com.google.devtools.build.lib.analysis.AnalysisUtils; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; import com.google.devtools.build.lib.analysis.Dependency; +import com.google.devtools.build.lib.analysis.PlatformOptions; import com.google.devtools.build.lib.analysis.TargetAndConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildOptions; @@ -40,11 +41,13 @@ import com.google.devtools.build.lib.packages.NoSuchThingException; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.skyframe.PrepareAnalysisPhaseValue.PrepareAnalysisPhaseKey; +import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.SkyFunction; import com.google.devtools.build.skyframe.SkyFunctionException; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.ValueOrException; +import com.google.devtools.common.options.OptionsParsingException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -82,19 +85,36 @@ ImmutableSortedSet<Class<? extends BuildConfiguration.Fragment>> allFragments = options.getFragments().fragmentClasses(); - BuildConfigurationValue.Key hostConfigurationKey = - BuildConfigurationValue.key( - allFragments, - BuildOptions.diffForReconstruction(defaultBuildOptions, hostOptions)); - ImmutableList<BuildConfigurationValue.Key> targetConfigurationKeys = - getTopLevelBuildOptions(targetOptions, options.getMultiCpu()) - .stream() - .map( - elem -> - BuildConfigurationValue.key( - allFragments, - BuildOptions.diffForReconstruction(defaultBuildOptions, elem))) - .collect(ImmutableList.toImmutableList()); + + PathFragment platformMappingPath = targetOptions.get(PlatformOptions.class).platformMappings; + PlatformMappingValue platformMappingValue = + (PlatformMappingValue) env.getValue(PlatformMappingValue.Key.create(platformMappingPath)); + if (platformMappingValue == null) { + return null; + } + + BuildConfigurationValue.Key hostConfigurationKey = null; + ImmutableList.Builder<BuildConfigurationValue.Key> targetConfigurationKeysBuilder = + ImmutableList.builder(); + try { + hostConfigurationKey = + BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + allFragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, hostOptions)); + for (BuildOptions buildOptions : + getTopLevelBuildOptions(targetOptions, options.getMultiCpu())) { + targetConfigurationKeysBuilder.add( + BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + allFragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, buildOptions))); + } + } catch (OptionsParsingException e) { + throw new PrepareAnalysisPhaseFunctionException(new InvalidConfigurationException(e)); + } // We don't need the host configuration below, but we call this to get the error, if any. try { @@ -103,6 +123,8 @@ throw new PrepareAnalysisPhaseFunctionException(e); } + ImmutableList<BuildConfigurationValue.Key> targetConfigurationKeys = + targetConfigurationKeysBuilder.build(); Map<SkyKey, SkyValue> configs = env.getValues(targetConfigurationKeys); // We only report invalid options for the target configurations, and abort if there's an error. @@ -148,7 +170,7 @@ LinkedHashSet<TargetAndConfiguration> topLevelTargetsWithConfigs; try { topLevelTargetsWithConfigs = resolveConfigurations(env, nodes, asDeps); - } catch (TransitionException e) { + } catch (TransitionException | OptionsParsingException e) { throw new PrepareAnalysisPhaseFunctionException(new InvalidConfigurationException(e)); } if (env.valuesMissing()) { @@ -189,7 +211,7 @@ SkyFunction.Environment env, Iterable<TargetAndConfiguration> nodes, Multimap<BuildConfiguration, Dependency> asDeps) - throws InterruptedException, TransitionException { + throws InterruptedException, TransitionException, OptionsParsingException { Map<Label, Target> labelsToTargets = new LinkedHashMap<>(); for (TargetAndConfiguration node : nodes) { labelsToTargets.put(node.getTarget().getLabel(), node.getTarget()); @@ -244,7 +266,7 @@ // Note: this implementation runs inside Skyframe, so it has access to SkyFunction.Environment. private Multimap<Dependency, BuildConfiguration> getConfigurations( SkyFunction.Environment env, BuildOptions fromOptions, Iterable<Dependency> keys) - throws InterruptedException, TransitionException { + throws InterruptedException, TransitionException, OptionsParsingException { Multimap<Dependency, BuildConfiguration> builder = ArrayListMultimap.<Dependency, BuildConfiguration>create(); Set<Dependency> depsToEvaluate = new HashSet<>(); @@ -295,6 +317,13 @@ } // Now get the configurations. + PathFragment platformMappingPath = fromOptions.get(PlatformOptions.class).platformMappings; + PlatformMappingValue platformMappingValue = + (PlatformMappingValue) env.getValue(PlatformMappingValue.Key.create(platformMappingPath)); + if (platformMappingValue == null) { + return null; + } + final List<SkyKey> configSkyKeys = new ArrayList<>(); for (Dependency key : keys) { if (labelsWithErrors.contains(key.getLabel()) || key.hasExplicitConfiguration()) { @@ -306,6 +335,7 @@ ConfigurationTransition transition = key.getTransition(); ImmutableSortedSet<Class<? extends BuildConfiguration.Fragment>> depFragments = fragmentsMap.get(key.getLabel()); + if (depFragments != null) { // TODO(juliexxia): combine these skyframe calls with other skyframe calls for this // configured target. @@ -333,8 +363,11 @@ StarlarkTransition.replayEvents(env.getListener(), transition); for (BuildOptions toOption : toOptions) { configSkyKeys.add( - BuildConfigurationValue.key( - depFragments, BuildOptions.diffForReconstruction(defaultBuildOptions, toOption))); + BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + depFragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, toOption))); } } } @@ -376,8 +409,11 @@ buildSettingOutputPackages); for (BuildOptions toOption : toOptions) { SkyKey configKey = - BuildConfigurationValue.key( - depFragments, BuildOptions.diffForReconstruction(defaultBuildOptions, toOption)); + BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + depFragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, toOption)); BuildConfigurationValue configValue = ((BuildConfigurationValue) configsResult.get(configKey)); // configValue will be null here if there was an exception thrown during configuration
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java index 04b5338..b6450dc 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -67,6 +67,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.Dependency; +import com.google.devtools.build.lib.analysis.PlatformOptions; import com.google.devtools.build.lib.analysis.TopLevelArtifactContext; import com.google.devtools.build.lib.analysis.WorkspaceStatusAction; import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory; @@ -176,6 +177,7 @@ import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import com.google.devtools.build.skyframe.WalkableGraph.WalkableGraphFactory; +import com.google.devtools.common.options.OptionsParsingException; import com.google.devtools.common.options.OptionsProvider; import java.io.PrintStream; import java.math.BigInteger; @@ -1451,6 +1453,7 @@ getConfigurations( eventHandler, PrepareAnalysisPhaseFunction.getTopLevelBuildOptions(buildOptions, multiCpu), + buildOptions, keepGoing); BuildConfiguration firstTargetConfig = topLevelTargetConfigs.get(0); @@ -1603,7 +1606,8 @@ public ImmutableList<ConfiguredTargetAndData> getConfiguredTargetsForTesting( ExtendedEventHandler eventHandler, BuildConfiguration originalConfig, - Iterable<Dependency> keys) { + Iterable<Dependency> keys) + throws TransitionException, InvalidConfigurationException { return getConfiguredTargetMapForTesting(eventHandler, originalConfig, keys).values().asList(); } @@ -1619,7 +1623,8 @@ public ImmutableList<ConfiguredTargetAndData> getConfiguredTargetsForTesting( ExtendedEventHandler eventHandler, BuildConfigurationValue.Key originalConfig, - Iterable<Dependency> keys) { + Iterable<Dependency> keys) + throws TransitionException, InvalidConfigurationException { return getConfiguredTargetMapForTesting(eventHandler, originalConfig, keys).values().asList(); } @@ -1636,7 +1641,8 @@ public ImmutableMultimap<Dependency, ConfiguredTargetAndData> getConfiguredTargetMapForTesting( ExtendedEventHandler eventHandler, BuildConfigurationValue.Key originalConfig, - Iterable<Dependency> keys) { + Iterable<Dependency> keys) + throws TransitionException, InvalidConfigurationException { return getConfiguredTargetMapForTesting( eventHandler, getConfiguration(eventHandler, originalConfig), keys); } @@ -1654,7 +1660,8 @@ private ImmutableMultimap<Dependency, ConfiguredTargetAndData> getConfiguredTargetMapForTesting( ExtendedEventHandler eventHandler, BuildConfiguration originalConfig, - Iterable<Dependency> keys) { + Iterable<Dependency> keys) + throws TransitionException, InvalidConfigurationException { checkActive(); Multimap<Dependency, BuildConfiguration> configs; @@ -1810,7 +1817,7 @@ ExtendedEventHandler eventHandler, BuildOptions options, boolean keepGoing) throws InvalidConfigurationException { return Iterables.getOnlyElement( - getConfigurations(eventHandler, ImmutableList.of(options), keepGoing)); + getConfigurations(eventHandler, ImmutableList.of(options), options, keepGoing)); } @VisibleForTesting @@ -1840,8 +1847,11 @@ * @throws InvalidConfigurationException if any build options produces an invalid configuration */ // TODO(ulfjack): Remove this legacy method after switching to the Skyframe-based implementation. - public List<BuildConfiguration> getConfigurations( - ExtendedEventHandler eventHandler, List<BuildOptions> optionsList, boolean keepGoing) + private List<BuildConfiguration> getConfigurations( + ExtendedEventHandler eventHandler, + List<BuildOptions> optionsList, + BuildOptions referenceBuildOptions, + boolean keepGoing) throws InvalidConfigurationException { Preconditions.checkArgument(!Iterables.isEmpty(optionsList)); @@ -1852,14 +1862,16 @@ .map(factory -> factory.creates()) .collect( ImmutableSortedSet.toImmutableSortedSet(BuildConfiguration.lexicalFragmentSorter)); - final ImmutableList<SkyKey> configSkyKeys = - optionsList.stream() - .map( - elem -> - BuildConfigurationValue.key( - allFragments, - BuildOptions.diffForReconstruction(defaultBuildOptions, elem))) - .collect(ImmutableList.toImmutableList()); + + PlatformMappingValue platformMappingValue = + getPlatformMappingValue(eventHandler, referenceBuildOptions); + + ImmutableList.Builder<SkyKey> configSkyKeysBuilder = ImmutableList.builder(); + for (BuildOptions options : optionsList) { + configSkyKeysBuilder.add(toConfigurationKey(platformMappingValue, allFragments, options)); + } + + ImmutableList<SkyKey> configSkyKeys = configSkyKeysBuilder.build(); // Skyframe-evaluate the configurations and throw errors if any. EvaluationResult<SkyValue> evalResult = evaluateSkyKeys(eventHandler, configSkyKeys, keepGoing); @@ -1898,14 +1910,15 @@ // Keep this in sync with {@link PrepareAnalysisPhaseFunction#getConfigurations}. // TODO(ulfjack): Remove this legacy method after switching to the Skyframe-based implementation. public Multimap<Dependency, BuildConfiguration> getConfigurations( - ExtendedEventHandler eventHandler, BuildOptions fromOptions, Iterable<Dependency> keys) { + ExtendedEventHandler eventHandler, BuildOptions fromOptions, Iterable<Dependency> keys) + throws InvalidConfigurationException { Multimap<Dependency, BuildConfiguration> builder = ArrayListMultimap.<Dependency, BuildConfiguration>create(); Set<Dependency> depsToEvaluate = new HashSet<>(); ImmutableSortedSet<Class<? extends BuildConfiguration.Fragment>> allFragments = null; if (useUntrimmedConfigs(fromOptions)) { - allFragments = ((ConfiguredRuleClassProvider) ruleClassProvider).getAllFragments(); + allFragments = ruleClassProvider.getAllFragments(); } // Get the fragments needed for dynamic configuration nodes. @@ -1944,6 +1957,8 @@ } } + PlatformMappingValue platformMappingValue = getPlatformMappingValue(eventHandler, fromOptions); + // Now get the configurations. final List<SkyKey> configSkyKeys = new ArrayList<>(); for (Dependency key : keys) { @@ -1979,9 +1994,7 @@ eventHandler.handle(Event.error(e.getMessage())); } for (BuildOptions toOption : toOptions) { - configSkyKeys.add( - BuildConfigurationValue.key( - depFragments, BuildOptions.diffForReconstruction(defaultBuildOptions, toOption))); + configSkyKeys.add(toConfigurationKey(platformMappingValue, depFragments, toOption)); } } } @@ -2018,9 +2031,8 @@ eventHandler.handle(Event.error(e.getMessage())); } for (BuildOptions toOption : toOptions) { - SkyKey configKey = - BuildConfigurationValue.key( - depFragments, BuildOptions.diffForReconstruction(defaultBuildOptions, toOption)); + BuildConfigurationValue.Key configKey = + toConfigurationKey(platformMappingValue, depFragments, toOption); BuildConfigurationValue configValue = ((BuildConfigurationValue) configsResult.get(configKey)); // configValue will be null here if there was an exception thrown during configuration @@ -2034,6 +2046,38 @@ return builder; } + private PlatformMappingValue getPlatformMappingValue( + ExtendedEventHandler eventHandler, BuildOptions referenceBuildOptions) + throws InvalidConfigurationException { + PathFragment platformMappingPath = + referenceBuildOptions.get(PlatformOptions.class).platformMappings; + + PlatformMappingValue.Key platformMappingKey = + PlatformMappingValue.Key.create(platformMappingPath); + EvaluationResult<SkyValue> evaluationResult = + evaluateSkyKeys(eventHandler, ImmutableSet.of(platformMappingKey)); + if (evaluationResult.hasError()) { + throw new InvalidConfigurationException(evaluationResult.getError().getException()); + } + return (PlatformMappingValue) evaluationResult.get(platformMappingKey); + } + + private BuildConfigurationValue.Key toConfigurationKey( + PlatformMappingValue platformMappingValue, + ImmutableSortedSet<Class<? extends BuildConfiguration.Fragment>> depFragments, + BuildOptions toOption) + throws InvalidConfigurationException { + try { + return BuildConfigurationValue.keyWithPlatformMapping( + platformMappingValue, + defaultBuildOptions, + depFragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, toOption)); + } catch (OptionsParsingException e) { + throw new InvalidConfigurationException(e); + } + } + private Map<SkyKey, SkyValue> collectBuildSettingValues( ConfigurationTransition transition, ExtendedEventHandler eventHandler, @@ -2104,10 +2148,13 @@ @VisibleForTesting public BuildConfiguration getConfigurationForTesting( ExtendedEventHandler eventHandler, FragmentClassSet fragments, BuildOptions options) - throws InterruptedException { + throws InterruptedException, OptionsParsingException, InvalidConfigurationException { SkyKey key = - BuildConfigurationValue.key( - fragments, BuildOptions.diffForReconstruction(defaultBuildOptions, options)); + BuildConfigurationValue.keyWithPlatformMapping( + getPlatformMappingValue(eventHandler, options), + defaultBuildOptions, + fragments, + BuildOptions.diffForReconstruction(defaultBuildOptions, options)); BuildConfigurationValue result = (BuildConfigurationValue) evaluate( @@ -2123,7 +2170,8 @@ @VisibleForTesting @Nullable public ConfiguredTarget getConfiguredTargetForTesting( - ExtendedEventHandler eventHandler, Label label, BuildConfiguration configuration) { + ExtendedEventHandler eventHandler, Label label, BuildConfiguration configuration) + throws TransitionException, InvalidConfigurationException { return getConfiguredTargetForTesting(eventHandler, label, configuration, NoTransition.INSTANCE); } @@ -2134,7 +2182,8 @@ ExtendedEventHandler eventHandler, Label label, BuildConfiguration configuration, - ConfigurationTransition transition) { + ConfigurationTransition transition) + throws TransitionException, InvalidConfigurationException { ConfiguredTargetAndData configuredTargetAndData = getConfiguredTargetAndDataForTesting(eventHandler, label, configuration, transition); return configuredTargetAndData == null ? null : configuredTargetAndData.getConfiguredTarget(); @@ -2146,7 +2195,8 @@ ExtendedEventHandler eventHandler, Label label, BuildConfiguration configuration, - ConfigurationTransition transition) { + ConfigurationTransition transition) + throws TransitionException, InvalidConfigurationException { return Iterables.getFirst( getConfiguredTargetsForTesting( eventHandler, @@ -2162,7 +2212,8 @@ @VisibleForTesting @Nullable public ConfiguredTargetAndData getConfiguredTargetAndDataForTesting( - ExtendedEventHandler eventHandler, Label label, BuildConfiguration configuration) { + ExtendedEventHandler eventHandler, Label label, BuildConfiguration configuration) + throws TransitionException, InvalidConfigurationException { return getConfiguredTargetAndDataForTesting( eventHandler, label, configuration, NoTransition.INSTANCE); }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java index 745c637..5ef6c9f 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisTestCase.java
@@ -44,7 +44,9 @@ import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.configuredtargets.InputFileConfiguredTarget; +import com.google.devtools.build.lib.analysis.skylark.StarlarkTransition; import com.google.devtools.build.lib.buildtool.BuildRequestOptions; import com.google.devtools.build.lib.clock.BlazeClock; import com.google.devtools.build.lib.cmdline.Label; @@ -449,7 +451,11 @@ } catch (LabelSyntaxException e) { throw new AssertionError(e); } - return skyframeExecutor.getConfiguredTargetAndDataForTesting(reporter, parsedLabel, config); + try { + return skyframeExecutor.getConfiguredTargetAndDataForTesting(reporter, parsedLabel, config); + } catch (StarlarkTransition.TransitionException | InvalidConfigurationException e) { + throw new AssertionError(e); + } } protected Target getTarget(String label) throws InterruptedException { @@ -494,8 +500,12 @@ } catch (LabelSyntaxException e) { throw new AssertionError(e); } - return skyframeExecutor.getConfiguredTargetAndDataForTesting( - reporter, parsedLabel, configuration); + try { + return skyframeExecutor.getConfiguredTargetAndDataForTesting( + reporter, parsedLabel, configuration); + } catch (StarlarkTransition.TransitionException | InvalidConfigurationException e) { + throw new AssertionError(e); + } } protected final BuildConfiguration getConfiguration(TransitiveInfoCollection ct) {
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java index 849b3502..c99c79a 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewForTesting.java
@@ -54,6 +54,7 @@ import com.google.devtools.build.lib.analysis.config.TransitionResolver; import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition; import com.google.devtools.build.lib.analysis.config.transitions.NoTransition; +import com.google.devtools.build.lib.analysis.skylark.StarlarkTransition; import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory; import com.google.devtools.build.lib.causes.Cause; import com.google.devtools.build.lib.cmdline.Label; @@ -188,7 +189,8 @@ */ @VisibleForTesting public BuildConfiguration getConfigurationForTesting( - Target target, BuildConfiguration config, ExtendedEventHandler eventHandler) { + Target target, BuildConfiguration config, ExtendedEventHandler eventHandler) + throws StarlarkTransition.TransitionException, InvalidConfigurationException { List<TargetAndConfiguration> node = ImmutableList.<TargetAndConfiguration>of(new TargetAndConfiguration(target, config)); LinkedHashSet<TargetAndConfiguration> configs = @@ -216,7 +218,7 @@ ConfiguredTarget ct, BuildConfigurationCollection configurations) throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException { + InconsistentAspectOrderException, StarlarkTransition.TransitionException { return Collections2.transform( getConfiguredTargetAndDataDirectPrerequisitesForTesting(eventHandler, ct, configurations), ConfiguredTargetAndData::getConfiguredTarget); @@ -224,24 +226,24 @@ // TODO(janakr): pass the configuration in as a parameter here and above. private Collection<ConfiguredTargetAndData> - getConfiguredTargetAndDataDirectPrerequisitesForTesting( - ExtendedEventHandler eventHandler, - ConfiguredTarget ct, - BuildConfigurationCollection configurations) - throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException { + getConfiguredTargetAndDataDirectPrerequisitesForTesting( + ExtendedEventHandler eventHandler, + ConfiguredTarget ct, + BuildConfigurationCollection configurations) + throws EvalException, InvalidConfigurationException, InterruptedException, + InconsistentAspectOrderException, StarlarkTransition.TransitionException { return getConfiguredTargetAndDataDirectPrerequisitesForTesting( eventHandler, ct, ct.getConfigurationKey(), configurations); } @VisibleForTesting public Collection<ConfiguredTargetAndData> - getConfiguredTargetAndDataDirectPrerequisitesForTesting( - ExtendedEventHandler eventHandler, - ConfiguredTargetAndData ct, - BuildConfigurationCollection configurations) - throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException { + getConfiguredTargetAndDataDirectPrerequisitesForTesting( + ExtendedEventHandler eventHandler, + ConfiguredTargetAndData ct, + BuildConfigurationCollection configurations) + throws EvalException, InvalidConfigurationException, InterruptedException, + InconsistentAspectOrderException, StarlarkTransition.TransitionException { return getConfiguredTargetAndDataDirectPrerequisitesForTesting( eventHandler, ct.getConfiguredTarget(), @@ -250,13 +252,13 @@ } private Collection<ConfiguredTargetAndData> - getConfiguredTargetAndDataDirectPrerequisitesForTesting( - ExtendedEventHandler eventHandler, - ConfiguredTarget ct, - BuildConfigurationValue.Key configuration, - BuildConfigurationCollection configurations) - throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException { + getConfiguredTargetAndDataDirectPrerequisitesForTesting( + ExtendedEventHandler eventHandler, + ConfiguredTarget ct, + BuildConfigurationValue.Key configuration, + BuildConfigurationCollection configurations) + throws EvalException, InvalidConfigurationException, InterruptedException, + InconsistentAspectOrderException, StarlarkTransition.TransitionException { return skyframeExecutor.getConfiguredTargetsForTesting( eventHandler, configuration, @@ -272,7 +274,8 @@ final ConfiguredTarget ct, BuildConfigurationCollection configurations, ImmutableSet<Label> toolchainLabels) - throws EvalException, InterruptedException, InconsistentAspectOrderException { + throws EvalException, InterruptedException, InconsistentAspectOrderException, + StarlarkTransition.TransitionException, InvalidConfigurationException { Target target = null; try { @@ -336,7 +339,8 @@ * present in this rule's attributes. */ private ImmutableMap<Label, ConfigMatchingProvider> getConfigurableAttributeKeysForTesting( - ExtendedEventHandler eventHandler, TargetAndConfiguration ctg) { + ExtendedEventHandler eventHandler, TargetAndConfiguration ctg) + throws StarlarkTransition.TransitionException, InvalidConfigurationException { if (!(ctg.getTarget() instanceof Rule)) { return ImmutableMap.of(); } @@ -362,7 +366,7 @@ BuildConfigurationCollection configurations, ImmutableSet<Label> toolchainLabels) throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException { + InconsistentAspectOrderException, StarlarkTransition.TransitionException { OrderedSetMultimap<DependencyKind, Dependency> depNodeNames = getDirectPrerequisiteDependenciesForTesting( eventHandler, target, configurations, toolchainLabels); @@ -412,7 +416,8 @@ */ @VisibleForTesting public ConfiguredTarget getConfiguredTargetForTesting( - ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) { + ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) + throws StarlarkTransition.TransitionException, InvalidConfigurationException { ConfigurationTransition transition = getTopLevelTransitionForTarget(label, config, eventHandler); if (transition == null) { @@ -423,15 +428,15 @@ @VisibleForTesting public ConfiguredTargetAndData getConfiguredTargetAndDataForTesting( - ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) { + ExtendedEventHandler eventHandler, Label label, BuildConfiguration config) + throws StarlarkTransition.TransitionException, InvalidConfigurationException { ConfigurationTransition transition = getTopLevelTransitionForTarget(label, config, eventHandler); if (transition == null) { return null; } - return skyframeExecutor.getConfiguredTargetAndDataForTesting( - eventHandler, label, config, transition); - + return skyframeExecutor.getConfiguredTargetAndDataForTesting( + eventHandler, label, config, transition); } /** @@ -443,7 +448,8 @@ StoredEventHandler eventHandler, BuildConfigurationCollection configurations) throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException, ToolchainException { + InconsistentAspectOrderException, ToolchainException, + StarlarkTransition.TransitionException { BuildConfiguration targetConfig = skyframeExecutor.getConfiguration(eventHandler, target.getConfigurationKey()); CachingAnalysisEnvironment env = @@ -470,7 +476,8 @@ AnalysisEnvironment env, BuildConfigurationCollection configurations) throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException, ToolchainException { + InconsistentAspectOrderException, ToolchainException, + StarlarkTransition.TransitionException { BuildConfiguration targetConfig = skyframeExecutor.getConfiguration(eventHandler, configuredTarget.getConfigurationKey()); Target target = null; @@ -538,7 +545,7 @@ Label desiredTarget, BuildConfigurationCollection configurations) throws EvalException, InvalidConfigurationException, InterruptedException, - InconsistentAspectOrderException { + InconsistentAspectOrderException, StarlarkTransition.TransitionException { Collection<ConfiguredTargetAndData> configuredTargets = getPrerequisiteMapForTesting( eventHandler,
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java index 58fa36d..a8ee477 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -85,12 +85,14 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Options.ConfigsMode; import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; import com.google.devtools.build.lib.analysis.config.BuildOptions; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.config.transitions.NoTransition; import com.google.devtools.build.lib.analysis.config.transitions.NullTransition; import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition; import com.google.devtools.build.lib.analysis.configuredtargets.FileConfiguredTarget; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.analysis.extra.ExtraAction; +import com.google.devtools.build.lib.analysis.skylark.StarlarkTransition; import com.google.devtools.build.lib.analysis.test.BaselineCoverageAction; import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo; import com.google.devtools.build.lib.buildtool.BuildRequestOptions; @@ -872,16 +874,24 @@ * may return null. In that case, use a debugger to inspect the {@link ErrorInfo} for the * evaluation, which is produced by the {@link MemoizingEvaluator#getExistingValue} call in {@link * SkyframeExecutor#getConfiguredTargetForTesting}. See also b/26382502. + * + * @throws AssertionError if the target cannot be transitioned into with the given configuration */ protected ConfiguredTarget getConfiguredTarget(Label label, BuildConfiguration config) { - return view.getConfiguredTargetForTesting(reporter, BlazeTestUtils.convertLabel(label), config); + try { + return view.getConfiguredTargetForTesting( + reporter, BlazeTestUtils.convertLabel(label), config); + } catch (InvalidConfigurationException | StarlarkTransition.TransitionException e) { + throw new AssertionError(e); + } } /** * Returns a ConfiguredTargetAndData for the specified label, using the given build configuration. */ protected ConfiguredTargetAndData getConfiguredTargetAndData( - Label label, BuildConfiguration config) { + Label label, BuildConfiguration config) + throws StarlarkTransition.TransitionException, InvalidConfigurationException { return view.getConfiguredTargetAndDataForTesting(reporter, label, config); } @@ -891,7 +901,8 @@ * config in the ConfiguredTargetAndData's ConfiguredTarget. */ public ConfiguredTargetAndData getConfiguredTargetAndData(String label) - throws LabelSyntaxException { + throws LabelSyntaxException, StarlarkTransition.TransitionException, + InvalidConfigurationException { return getConfiguredTargetAndData(Label.parseAbsolute(label, ImmutableMap.of()), targetConfig); } @@ -1714,16 +1725,22 @@ /** * Returns the configuration created by applying the given transition to the source configuration. + * + * @throws AssertionError if the transition couldn't be evaluated */ - protected BuildConfiguration getConfiguration(BuildConfiguration fromConfig, - PatchTransition transition) throws InterruptedException { + protected BuildConfiguration getConfiguration( + BuildConfiguration fromConfig, PatchTransition transition) throws InterruptedException { if (transition == NoTransition.INSTANCE) { return fromConfig; } else if (transition == NullTransition.INSTANCE) { return null; } else { - return skyframeExecutor.getConfigurationForTesting( - reporter, fromConfig.fragmentClasses(), transition.patch(fromConfig.getOptions())); + try { + return skyframeExecutor.getConfigurationForTesting( + reporter, fromConfig.fragmentClasses(), transition.patch(fromConfig.getOptions())); + } catch (OptionsParsingException | InvalidConfigurationException e) { + throw new AssertionError(e); + } } } @@ -1750,7 +1767,9 @@ ConfiguredTargetAndData ctad; try { ctad = getConfiguredTargetAndData(ct.getLabel().toString()); - } catch (LabelSyntaxException e) { + } catch (LabelSyntaxException + | StarlarkTransition.TransitionException + | InvalidConfigurationException e) { throw new RuntimeException(e); } return getMapperFromConfiguredTargetAndTarget(ctad);
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java index 28e7052..58d5e72 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java
@@ -42,6 +42,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.CompilationMode; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition; import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter; @@ -59,6 +60,7 @@ import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; import com.google.devtools.build.lib.testutil.TestConstants; import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.common.options.OptionsParsingException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -299,8 +301,9 @@ * Returns all child configurations resulting from a given split transition on a given * configuration. */ - protected List<BuildConfiguration> getSplitConfigurations(BuildConfiguration configuration, - SplitTransition splitTransition) throws InterruptedException { + protected List<BuildConfiguration> getSplitConfigurations( + BuildConfiguration configuration, SplitTransition splitTransition) + throws InterruptedException, OptionsParsingException, InvalidConfigurationException { ImmutableList.Builder<BuildConfiguration> splitConfigs = ImmutableList.builder(); for (BuildOptions splitOptions : splitTransition.split(configuration.getOptions())) {
diff --git a/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformConfigurationApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformConfigurationApiTest.java index f35776c..34437c6 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformConfigurationApiTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/platform/PlatformConfigurationApiTest.java
@@ -74,33 +74,6 @@ } @Test - public void testTargetPlatform_multiple() throws Exception { - scratch.file( - "platforms/BUILD", - "platform(name = 'test_platform1')", - "platform(name = 'test_platform2')"); - - useConfiguration("--platforms=//platforms:test_platform1,//platforms:test_platform2"); - ruleBuilder().build(); - scratch.file( - "foo/BUILD", - "load(':extension.bzl', 'my_rule')", - "my_rule(", - " name = 'my_skylark_rule',", - ")"); - assertNoEvents(); - - PlatformConfigurationApi platformConfiguration = fetchPlatformConfiguration(); - assertThat(platformConfiguration).isNotNull(); - // Despite setting two platforms in the flag, only a single platform should be visible to the - // target. - assertThat(platformConfiguration.getTargetPlatform()) - .isEqualTo(Label.parseAbsoluteUnchecked("//platforms:test_platform1")); - assertThat(platformConfiguration.getTargetPlatforms()) - .containsExactly(Label.parseAbsoluteUnchecked("//platforms:test_platform1")); - } - - @Test public void testEnabledToolchainTypes() throws Exception { scratch.file( "toolchains/BUILD",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunctionTest.java index 5a0867e..c5a962b 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunctionTest.java
@@ -83,7 +83,7 @@ executeFunction(PlatformMappingValue.Key.create(null)); BuildConfigurationValue.Key key = - BuildConfigurationValue.key(PLATFORM_FRAGMENT_CLASS, EMPTY_DIFF); + BuildConfigurationValue.keyWithoutPlatformMapping(PLATFORM_FRAGMENT_CLASS, EMPTY_DIFF); BuildConfigurationValue.Key mapped = platformMappingValue.map(key, DEFAULT_BUILD_CONFIG_PLATFORM_OPTIONS); @@ -155,6 +155,6 @@ BuildOptions.OptionsDiffForReconstruction diff = BuildOptions.diffForReconstruction(DEFAULT_BUILD_CONFIG_PLATFORM_OPTIONS, modifiedOptions); - return BuildConfigurationValue.key(PLATFORM_FRAGMENT_CLASS, diff); + return BuildConfigurationValue.keyWithoutPlatformMapping(PLATFORM_FRAGMENT_CLASS, diff); } }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingValueTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingValueTest.java index af8c114..39a2e04 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingValueTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/PlatformMappingValueTest.java
@@ -65,7 +65,7 @@ new PlatformMappingValue(ImmutableMap.of(), ImmutableMap.of()); BuildConfigurationValue.Key key = - BuildConfigurationValue.key(PLATFORM_FRAGMENT_CLASS, EMPTY_DIFF); + BuildConfigurationValue.keyWithoutPlatformMapping(PLATFORM_FRAGMENT_CLASS, EMPTY_DIFF); BuildConfigurationValue.Key mapped = mappingValue.map(key, DEFAULT_BUILD_CONFIG_PLATFORM_OPTIONS); @@ -238,6 +238,6 @@ BuildOptions.OptionsDiffForReconstruction diff = BuildOptions.diffForReconstruction(DEFAULT_BUILD_CONFIG_PLATFORM_OPTIONS, modifiedOptions); - return BuildConfigurationValue.key(PLATFORM_FRAGMENT_CLASS, diff); + return BuildConfigurationValue.keyWithoutPlatformMapping(PLATFORM_FRAGMENT_CLASS, diff); } }
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD index 94c7075..2df2986 100644 --- a/src/test/shell/bazel/BUILD +++ b/src/test/shell/bazel/BUILD
@@ -880,3 +880,10 @@ data = [":test-deps"], deps = ["@bazel_tools//tools/bash/runfiles"], ) + +sh_test( + name = "platform_mapping_test", + srcs = ["platform_mapping_test.sh"], + data = [":test-deps"], + tags = ["no_windows"], +)
diff --git a/src/test/shell/bazel/platform_mapping_test.sh b/src/test/shell/bazel/platform_mapping_test.sh new file mode 100755 index 0000000..9be52af --- /dev/null +++ b/src/test/shell/bazel/platform_mapping_test.sh
@@ -0,0 +1,195 @@ +#!/bin/bash +# +# Copyright 2017 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. +# +# Test the providers and rules related to toolchains. +# + +# Load the test setup defined in the parent directory +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${CURRENT_DIR}/../integration_test_setup.sh" \ + || { echo "integration_test_setup.sh not found!" >&2; exit 1; } + +function set_up() { + create_new_workspace + + mkdir package + + # Create shared platform definitions + mkdir plat + cat > plat/BUILD <<EOF +platform( + name = 'platform1', + constraint_values = []) + +platform( + name = 'platform2', + constraint_values = []) +EOF + + # Create shared report rule for printing flag and platform info. + mkdir report + touch report/BUILD + cat > report/report.bzl <<EOF +def _report_impl(ctx): + print('copts: %s' % ctx.fragments.cpp.copts) + print('platform: %s' % ctx.fragments.platform.platform) + +report_flags = rule( + implementation = _report_impl, + attrs = {}, + fragments = ["cpp", "platform"] +) +EOF +} + +function test_top_level_flags_to_platform_mapping() { + cat > platform_mappings <<EOF +flags: + --cpu=arm64 + //plat:platform1 +EOF + + cat > package/BUILD <<EOF +load("//report:report.bzl", "report_flags") +report_flags(name = "report") +EOF + + bazel build --cpu=arm64 package:report &> $TEST_log \ + || fail "Build failed unexpectedly" + expect_log "platform: //plat:platform1" +} + +function test_top_level_platform_to_flags_mapping() { + cat > platform_mappings <<EOF +platforms: + //plat:platform1 + --copt=foo +EOF + + cat > package/BUILD <<EOF +load("//report:report.bzl", "report_flags") +report_flags(name = "report") +EOF + + bazel build --platforms=//plat:platform1 package:report &> $TEST_log \ + || fail "Build failed unexpectedly" + expect_log "copts: \[\"foo\"\]" +} + +function test_custom_platform_mapping_location() { + mkdir custom + cat > custom/platform_mappings <<EOF +flags: + --cpu=arm64 + //plat:platform1 +EOF + + cat > package/BUILD <<EOF +load("//report:report.bzl", "report_flags") +report_flags(name = "report") +EOF + + bazel build --cpu=arm64 --platform_mappings=custom/platform_mappings \ + package:report &> $TEST_log || fail "Build failed unexpectedly" + expect_log "platform: //plat:platform1" +} + +function test_top_level_multi_platform_mapping() { + cat > platform_mappings <<EOF +flags: + --cpu=k8 + //plat:platform1 + --cpu=arm64 + //plat:platform2 +EOF + + cat > package/BUILD <<EOF +load("//report:report.bzl", "report_flags") +report_flags(name = "report") +EOF + + bazel build --experimental_multi_cpu=k8,arm64 package:report &> $TEST_log \ + || fail "Build failed unexpectedly" + expect_log "platform: //plat:platform1" + expect_log "platform: //plat:platform2" +} + +function test_transition_platform_mapping() { + cat > platform_mappings <<EOF +flags: + --cpu=k8 + //plat:platform1 + --cpu=arm64 + //plat:platform2 +EOF + + cat > package/rule.bzl <<EOF +def _my_transition_impl(settings, attrs): + return { + "//command_line_option:cpu": "arm64", + "//command_line_option:copt": ["foo"], + # Platforms *must* be wiped for transitions to correctly participate in + # platform mapping. + "//command_line_option:platforms": [], + } + + +my_transition = transition( + implementation = _my_transition_impl, + inputs = [], + outputs = [ + "//command_line_option:cpu", + "//command_line_option:copt", + "//command_line_option:platforms", + ], +) + + +def _my_rule_impl(ctx): + return [] + + +my_rule = rule( + implementation = _my_rule_impl, + attrs = { + "deps": attr.label_list(cfg = my_transition), + "_whitelist_function_transition": attr.label( + default = "@//tools/whitelists/function_transition_whitelist"), + } +) +EOF + + cat > package/BUILD <<EOF +load("//report:report.bzl", "report_flags") +load("//package:rule.bzl", "my_rule") + +my_rule( + name = "custom", + deps = [ ":report" ] +) + +report_flags(name = "report") +EOF + + bazel build --cpu=k8 package:custom \ + --experimental_starlark_config_transitions &> $TEST_log \ + || fail "Build failed unexpectedly" + expect_not_log "platform: //plat:platform1" + expect_log "platform: //plat:platform2" +} + +run_suite "platform mapping test" +