diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java index 2633d473afdea4..bb0446dba09d9b 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java @@ -36,6 +36,7 @@ import com.google.devtools.build.lib.analysis.DependencyKind; import com.google.devtools.build.lib.analysis.DuplicateException; import com.google.devtools.build.lib.analysis.ExecGroupCollection.InvalidExecGroupException; +import com.google.devtools.build.lib.analysis.IncompatiblePlatformProvider; import com.google.devtools.build.lib.analysis.InconsistentAspectOrderException; import com.google.devtools.build.lib.analysis.PlatformOptions; import com.google.devtools.build.lib.analysis.ResolvedToolchainContext; @@ -292,6 +293,20 @@ public SkyValue compute(SkyKey skyKey, Environment env) throw new IllegalStateException("Name already verified", e); } + // If the target is incompatible, then there's not much to do. The intent here is to create an + // AspectValue that doesn't trigger any of the associated target's dependencies to be evaluated + // against this aspect. + if (associatedTarget.get(IncompatiblePlatformProvider.PROVIDER) != null) { + return new AspectValue( + key, + aspect, + target.getLocation(), + ConfiguredAspect.forNonapplicableTarget(), + /*transitivePackagesForPackageRootResolution=*/ NestedSetBuilder + .stableOrder() + .build()); + } + if (AliasProvider.isAlias(associatedTarget)) { return createAliasAspect( env, diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD index 468b1290e45e5b..e8b8287413765d 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD @@ -258,6 +258,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib/analysis:duplicate_exception", "//src/main/java/com/google/devtools/build/lib/analysis:exec_group_collection", "//src/main/java/com/google/devtools/build/lib/analysis:extra_action_artifacts_provider", + "//src/main/java/com/google/devtools/build/lib/analysis:incompatible_platform_provider", "//src/main/java/com/google/devtools/build/lib/analysis:inconsistent_aspect_order_exception", "//src/main/java/com/google/devtools/build/lib/analysis:platform_configuration", "//src/main/java/com/google/devtools/build/lib/analysis:platform_options", diff --git a/src/test/shell/integration/target_compatible_with_test.sh b/src/test/shell/integration/target_compatible_with_test.sh index fd432689c736be..d00895b6e302e4 100755 --- a/src/test/shell/integration/target_compatible_with_test.sh +++ b/src/test/shell/integration/target_compatible_with_test.sh @@ -1066,4 +1066,163 @@ function test_aquery_incompatible_target() { expect_log "target platform (//target_skipping:foo3_platform) didn't satisfy constraint //target_skipping:foo1" } +# Use aspects to interact with incompatible targets and validate the behaviour. +function test_aspect_skipping() { + cat >> target_skipping/BUILD < target_skipping/defs.bzl < "${TEST_log}" \ + || fail "Bazel failed unexpectedly." + expect_log "${debug_message1}" + expect_log "${debug_message2}" + expect_log "${debug_message3}" + expect_log "${debug_message4}" + expect_not_log "${debug_message5}" + # Invert the compatibility and validate that aspects run on the other targets + # now. + bazel build \ + --show_result=10 \ + --host_platform=@//target_skipping:foo1_bar1_platform \ + --platforms=@//target_skipping:foo1_bar1_platform \ + //target_skipping:all &> "${TEST_log}" \ + || fail "Bazel failed unexpectedly." + expect_not_log "${debug_message1}" + expect_not_log "${debug_message2}" + expect_not_log "${debug_message3}" + expect_not_log "${debug_message4}" + expect_log "${debug_message5}" + # Validate that explicitly trying to build a target with an aspect against an + # incompatible target produces the normal error message. + bazel build \ + --show_result=10 \ + --host_platform=@//target_skipping:foo1_bar1_platform \ + --platforms=@//target_skipping:foo1_bar1_platform \ + //target_skipping:twice_inspected_foo3_target &> "${TEST_log}" \ + && fail "Bazel passed unexpectedly." + # TODO(#15427): Should use expect_log_once here when the issue is fixed. + expect_log 'ERROR: Target //target_skipping:twice_inspected_foo3_target is incompatible and cannot be built, but was explicitly requested.' + expect_log '^Dependency chain:$' + expect_log '^ //target_skipping:twice_inspected_foo3_target$' + expect_log '^ //target_skipping:previously_inspected_basic_target$' + expect_log '^ //target_skipping:inspected_foo3_target$' + expect_log '^ //target_skipping:aliased_other_basic_target$' + expect_log '^ //target_skipping:other_basic_target$' + expect_log " //target_skipping:basic_foo3_target <-- target platform (//target_skipping:foo1_bar1_platform) didn't satisfy constraint //target_skipping:foo3$" + expect_log 'FAILED: Build did NOT complete successfully' + expect_not_log "${debug_message1}" + expect_not_log "${debug_message2}" + expect_not_log "${debug_message3}" + expect_not_log "${debug_message4}" + expect_not_log "${debug_message5}" +} + run_suite "target_compatible_with tests"