From 4a6f40d8ced5b2fc1555a1536b0eb4d8570faacc Mon Sep 17 00:00:00 2001 From: Philipp Schrader Date: Tue, 10 Mar 2020 21:23:40 -0700 Subject: [PATCH] Add basic incompatible target skipping This patch aims to implement a basic version of incompatible target skipping outlined here: https://docs.google.com/document/d/12n5QNHmFSkuh5yAbdEex64ot4hRgR-moL1zRimU7wHQ/edit?usp=sharing The implementation in this patch supports only "top level" target skipping. In other words we only filter out targets if they are globbed as part of an invocation like "bazel build //...". The following features are not yet implemented: - Filtering targets based on transitive dependencies. For example, if //a:b depends on //c:d an invocation of "bazel build //a/..." will still build //c:d even if it is incompatible with the current platform. - Being able to select() on constraint values. For example, it's not possible to select() based on whether or not GCC is being used. Discussion of this aspect of the proposal is ongoing: https://groups.google.com/d/msg/bazel-dev/xK7diubpljQ/s3KSRwTWAQAJ The goal is to implement the missing features in follow-up patches. Austin Schuh (austin.linux@gmail.com) provided me with the majority of the logic in TopLevelConstraintSemantics.java. I added the remaining error reporting logic and the tests. The patch largely re-uses the existing support for skipping targets based on incompatible CPU constraints. There are a few enhancements to the error reporting so that it's a little more obvious on the command line when a target was skipped. To a lesser extent the Build Event Stream should also contain less misleading information now. I did have to introduce the notion of to-be-failed targets determined during the analysis phase. For now these are targets that are incompatible with the current platform, but were explicitly requested on the command line. The list of targets ("targetsToFail" in AnalysisResult) is used to affect the outcome of the build. I.e. if the list is non-empty, then the build is considered to have failed. --- .../build/lib/analysis/AnalysisResult.java | 12 + .../build/lib/analysis/BaseRuleClasses.java | 10 + .../build/lib/analysis/BuildView.java | 43 ++- .../TopLevelConstraintSemantics.java | 102 +++++- .../proto/build_event_stream.proto | 1 + .../lib/buildtool/AnalysisPhaseRunner.java | 25 +- .../lib/buildtool/BuildResultPrinter.java | 15 +- .../build/lib/buildtool/ExecutionTool.java | 21 +- .../build/lib/packages/RuleClass.java | 4 + .../lib/rules/platform/ToolchainRule.java | 9 - .../lib/runtime/AggregatingTestListener.java | 22 +- .../lib/runtime/BuildEventStreamerUtils.java | 2 + .../runtime/TerminalTestResultNotifier.java | 5 +- .../lib/runtime/TestResultAggregator.java | 18 +- .../build/lib/runtime/UiEventHandler.java | 3 +- src/main/protobuf/test_status.proto | 1 + src/test/shell/bazel/BUILD | 7 + .../bazel/target_compatible_with_test.sh | 299 ++++++++++++++++++ 18 files changed, 557 insertions(+), 42 deletions(-) create mode 100755 src/test/shell/bazel/target_compatible_with_test.sh diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisResult.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisResult.java index c4aedce9ab7525..e7ecc37766aa2c 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisResult.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisResult.java @@ -33,6 +33,7 @@ public final class AnalysisResult { private final ImmutableSet targetsToBuild; @Nullable private final ImmutableList targetsToTest; private final ImmutableSet targetsToSkip; + private final ImmutableSet targetsToFail; @Nullable private final String error; private final ActionGraph actionGraph; private final ArtifactsToOwnerLabels topLevelArtifactsToOwnerLabels; @@ -51,6 +52,7 @@ public final class AnalysisResult { ImmutableSet aspects, @Nullable ImmutableList targetsToTest, ImmutableSet targetsToSkip, + ImmutableSet targetsToFail, @Nullable String error, ActionGraph actionGraph, ArtifactsToOwnerLabels topLevelArtifactsToOwnerLabels, @@ -66,6 +68,7 @@ public final class AnalysisResult { this.aspects = aspects; this.targetsToTest = targetsToTest; this.targetsToSkip = targetsToSkip; + this.targetsToFail = targetsToFail; this.error = error; this.actionGraph = actionGraph; this.topLevelArtifactsToOwnerLabels = topLevelArtifactsToOwnerLabels; @@ -123,6 +126,14 @@ public ImmutableSet getTargetsToSkip() { return targetsToSkip; } + /** + * Returns the incompatible targets that were explicitly requested on the command line. + */ + // TODO(phil): Document this properly. + public ImmutableSet getTargetsToFail() { + return targetsToFail; + } + public ArtifactsToOwnerLabels getTopLevelArtifactsToOwnerLabels() { return topLevelArtifactsToOwnerLabels; } @@ -180,6 +191,7 @@ public AnalysisResult withExclusiveTestsAsParallelTests() { aspects, targetsToTest, targetsToSkip, + targetsToFail, error, actionGraph, topLevelArtifactsToOwnerLabels, diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java index b7ffed1e55052a..af8ea819321ab5 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java @@ -34,6 +34,7 @@ import com.google.devtools.build.lib.analysis.config.HostTransition; import com.google.devtools.build.lib.analysis.config.RunUnder; import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule; +import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo; import com.google.devtools.build.lib.analysis.test.TestConfiguration; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.Attribute; @@ -329,6 +330,15 @@ public static RuleClass.Builder commonCoreAndSkylarkAttributes(RuleClass.Builder .dontCheckConstraints() .nonconfigurable( "special logic for constraints and select: see ConstraintSemantics")) + /* + A list of constraint_values that must be satisfied by the target platform in + order for this toolchain to be selected for a target building for that platform. + */ + .add( + attr("target_compatible_with", LABEL_LIST) + .mandatoryProviders(ConstraintValueInfo.PROVIDER.id()) + .allowedFileTypes() + .nonconfigurable("Logic for target compatibility")) .add( attr(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE, LABEL_LIST) .nonconfigurable("stores configurability keys")) diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index f2ff1980590576..1f025322f6350e 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -206,6 +206,7 @@ public AnalysisResult update( TargetPatternPhaseValue loadingResult, BuildOptions targetOptions, Set multiCpu, + List requestedTargets, List aspects, AnalysisOptions viewOptions, boolean keepGoing, @@ -388,18 +389,18 @@ public AnalysisResult update( getArtifactFactory().noteAnalysisStarting(); SkyframeAnalysisResult skyframeAnalysisResult; - try { - Supplier> configurationLookupSupplier = - () -> { - Map result = new HashMap<>(); - for (TargetAndConfiguration node : topLevelTargetsWithConfigs) { - if (node.getConfiguration() != null) { - result.put( - BuildConfigurationValue.key(node.getConfiguration()), node.getConfiguration()); - } + Supplier> configurationLookupSupplier = + () -> { + Map result = new HashMap<>(); + for (TargetAndConfiguration node : topLevelTargetsWithConfigs) { + if (node.getConfiguration() != null) { + result.put( + BuildConfigurationValue.key(node.getConfiguration()), node.getConfiguration()); } - return result; - }; + } + return result; + }; + try { skyframeAnalysisResult = skyframeBuildView.configureTargets( eventHandler, @@ -425,10 +426,16 @@ public AnalysisResult update( Set targetsToSkip = new TopLevelConstraintSemantics( + skyframeBuildView, skyframeExecutor.getPackageManager(), input -> skyframeExecutor.getConfiguration(eventHandler, input), eventHandler) - .checkTargetEnvironmentRestrictions(skyframeAnalysisResult.getConfiguredTargets()); + .checkTargetEnvironmentRestrictions( + configurationLookupSupplier, + keepGoing, + loadingPhaseThreads, + eventBus, + skyframeAnalysisResult.getConfiguredTargets()); AnalysisResult result = createResult( @@ -440,6 +447,7 @@ public AnalysisResult update( viewOptions, skyframeAnalysisResult, targetsToSkip, + requestedTargets, topLevelTargetsWithConfigsResult); logger.atInfo().log("Finished analysis"); return result; @@ -454,6 +462,7 @@ private AnalysisResult createResult( AnalysisOptions viewOptions, SkyframeAnalysisResult skyframeAnalysisResult, Set targetsToSkip, + List requestedTargets, TopLevelTargetsAndConfigsResult topLevelTargetsWithConfigs) throws InterruptedException { Set