diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java | 57 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java | 64 |
2 files changed, 104 insertions, 17 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java index b1ec35db8b..87a31e2718 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java @@ -28,6 +28,8 @@ import com.google.devtools.build.lib.actions.Root; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment; import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; +import com.google.devtools.build.lib.analysis.config.PatchTransition; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; @@ -56,10 +58,13 @@ import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.rules.SkylarkRuleConfiguredTargetBuilder; import com.google.devtools.build.lib.rules.fileset.FilesetProvider; +import com.google.devtools.build.lib.skyframe.BuildConfigurationValue; import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; import com.google.devtools.build.lib.util.OrderedSetMultimap; import com.google.devtools.build.lib.util.Preconditions; import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.skyframe.SkyFunction; + import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -142,14 +147,21 @@ public final class ConfiguredTargetFactory { return null; } - private Artifact getOutputArtifact(OutputFile outputFile, BuildConfiguration configuration, - boolean isFileset, ArtifactFactory artifactFactory) { + /** + * Returns the output artifact for the given file, or null if Skyframe deps are missing. + */ + private Artifact getOutputArtifact(AnalysisEnvironment analysisEnvironment, OutputFile outputFile, + BuildConfiguration configuration, boolean isFileset, ArtifactFactory artifactFactory) + throws InterruptedException { Rule rule = outputFile.getAssociatedRule(); Root root = rule.hasBinaryOutput() ? configuration.getBinDirectory(rule.getRepository()) : configuration.getGenfilesDirectory(rule.getRepository()); - ArtifactOwner owner = - new ConfiguredTargetKey(rule.getLabel(), configuration.getArtifactOwnerConfiguration()); + ArtifactOwner owner = new ConfiguredTargetKey(rule.getLabel(), + getArtifactOwnerConfiguration(analysisEnvironment.getSkyframeEnv(), configuration)); + if (analysisEnvironment.getSkyframeEnv().valuesMissing()) { + return null; + } PathFragment rootRelativePath = outputFile.getLabel().getPackageIdentifier().getSourceRoot().getRelative( outputFile.getLabel().getName()); @@ -162,6 +174,37 @@ public final class ConfiguredTargetFactory { } /** + * Returns the configuration's artifact owner (which may be null). Also returns null if the + * owning configuration isn't yet available from Skyframe. + */ + public static BuildConfiguration getArtifactOwnerConfiguration(SkyFunction.Environment env, + BuildConfiguration fromConfig) throws InterruptedException { + if (fromConfig == null) { + return null; + } + if (!fromConfig.useDynamicConfigurations()) { + return fromConfig.getArtifactOwnerConfiguration(); + } + PatchTransition ownerTransition = fromConfig.getArtifactOwnerTransition(); + if (ownerTransition == null) { + return fromConfig; + } + try { + BuildConfigurationValue ownerConfig = (BuildConfigurationValue) env.getValueOrThrow( + BuildConfigurationValue.key( + fromConfig.fragmentClasses(), ownerTransition.apply(fromConfig.getOptions())), + InvalidConfigurationException.class); + return ownerConfig == null ? null : ownerConfig.getConfiguration(); + } catch (InvalidConfigurationException e) { + // We don't expect to have to handle an invalid configuration because in practice the owning + // configuration should already exist. For example, the main user of this feature, the LIPO + // context collector, expects the owning configuration to be the top-level target config. + throw new IllegalStateException( + "this method should only return a pre-existing valid configuration"); + } + } + + /** * Invokes the appropriate constructor to create a {@link ConfiguredTarget} instance. * <p>For use in {@code ConfiguredTargetFunction}. * @@ -187,7 +230,11 @@ public final class ConfiguredTargetFactory { if (target instanceof OutputFile) { OutputFile outputFile = (OutputFile) target; boolean isFileset = outputFile.getGeneratingRule().getRuleClass().equals("Fileset"); - Artifact artifact = getOutputArtifact(outputFile, config, isFileset, artifactFactory); + Artifact artifact = + getOutputArtifact(analysisEnvironment, outputFile, config, isFileset, artifactFactory); + if (analysisEnvironment.getSkyframeEnv().valuesMissing()) { + return null; + } TransitiveInfoCollection rule = targetContext.findDirectPrerequisite( outputFile.getGeneratingRule().getLabel(), config); if (isFileset) { diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java index af68c8b9fa..e942556160 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java @@ -200,6 +200,18 @@ public final class BuildConfiguration { public boolean compatibleWithStrategy(String strategyName) { return true; } + + /** + * Returns the transition that produces the "artifact owner" for this configuration, or null + * if this configuration is its own owner. + * + * <p>If multiple fragments return the same transition, that transition is only applied + * once. Multiple fragments may not return different non-null transitions. + */ + @Nullable + public PatchTransition getArtifactOwnerTransition() { + return null; + } } private static final Label convertLabel(String input) throws OptionsParsingException { @@ -1968,16 +1980,21 @@ public final class BuildConfiguration { if (currentTransition == ConfigurationTransition.NONE) { currentTransition = ruleClassTransition; } else { - currentTransition = new ComposingSplitTransition(ruleClassTransition, - currentTransition); + currentTransition = new ComposingSplitTransition(currentTransition, + ruleClassTransition); } } } - // We don't support rule class configurators (which may need intermediate configurations to - // apply). The only current use of that is LIPO, which can't currently be invoked with dynamic - // configurations (e.g. this code can never get called for LIPO builds). So check that - // if there is a configurator, it's for LIPO, in which case we can ignore it. + /** + * Dynamic configurations don't support rule class configurators (which may need intermediate + * configurations to apply). The only current use of that is LIPO, which dynamic + * configurations have a different code path for: + * {@link com.google.devtools.build.lib.rules.cpp.CppRuleClasses.LIPO_ON_DEMAND}. + * + * So just check that if there is a configurator, it's for LIPO, in which case we can ignore + * it. + */ if (associatedRule != null) { @SuppressWarnings("unchecked") RuleClass.Configurator<?, ?> func = @@ -2606,15 +2623,38 @@ public final class BuildConfiguration { } /** + * Returns the transition that produces the "artifact owner" for this configuration, or null + * if this configuration is its own owner. + * + * <p>This is the dynamic configuration version of {@link #getArtifactOwnerConfiguration}. + */ + @Nullable + public PatchTransition getArtifactOwnerTransition() { + Preconditions.checkState(useDynamicConfigurations()); + PatchTransition ownerTransition = null; + for (Fragment fragment : fragments.values()) { + PatchTransition fragmentTransition = fragment.getArtifactOwnerTransition(); + if (fragmentTransition != null) { + if (ownerTransition != null) { + Verify.verify(ownerTransition == fragmentTransition, + String.format( + "cannot determine owner transition: fragments returning both %s and %s", + ownerTransition.toString(), fragmentTransition.toString())); + } + ownerTransition = fragmentTransition; + } + } + return ownerTransition; + } + + /** * See {@code BuildConfigurationCollection.Transitions.getArtifactOwnerConfiguration()}. + * + * <p>This is the static configuration version of {@link #getArtifactOwnerTransition}. */ public BuildConfiguration getArtifactOwnerConfiguration() { - // Dynamic configurations inherit transitions objects from other configurations exclusively - // for use of Transitions.getDynamicTransition. No other calls to transitions should be - // made for dynamic configurations. - // TODO(bazel-team): enforce the above automatically (without having to explicitly check - // for dynamic configuration mode). - return useDynamicConfigurations() ? this : transitions.getArtifactOwnerConfiguration(); + Preconditions.checkState(!useDynamicConfigurations()); + return transitions.getArtifactOwnerConfiguration(); } /** |