diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisOptions.java index 2a7c75b4b4ee73..95256a0549fd24 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisOptions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisOptions.java @@ -90,16 +90,6 @@ public class AnalysisOptions extends OptionsBase { help = "Deprecated. No-op.") public boolean skyframePrepareAnalysis; - @Option( - name = "experimental_strict_conflict_checks", - defaultValue = "false", - documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, - metadataTags = OptionMetadataTag.INCOMPATIBLE_CHANGE, - effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION}, - help = - "Check for action prefix file path conflicts, regardless of action-specific overrides.") - public boolean strictConflictChecks; - @Option( name = "experimental_skyframe_cpu_heavy_skykeys_thread_pool_size", defaultValue = "HOST_CPUS", diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/BUILD index 350541aee2ad63..31f80abf04d4d5 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BUILD +++ b/src/main/java/com/google/devtools/build/lib/analysis/BUILD @@ -610,6 +610,7 @@ java_library( ":blaze_directories", ":config/build_configuration", ":config/build_options", + ":config/core_options", ":config/invalid_configuration_exception", ":configured_target", ":constraints/platform_restrictions_result", 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 e3a43f6f611467..267196f682b3ae 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 @@ -43,6 +43,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.ConfigurationResolver.TopLevelTargetsAndConfigsResult; +import com.google.devtools.build.lib.analysis.config.CoreOptions; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.constraints.PlatformRestrictionsResult; import com.google.devtools.build.lib.analysis.constraints.RuleContextConstraintSemantics; @@ -426,7 +427,7 @@ public AnalysisResult update( Preconditions.checkNotNull(resourceManager), // non-null for skymeld. Preconditions.checkNotNull(buildResultListener), // non-null for skymeld. keepGoing, - viewOptions.strictConflictChecks, + targetOptions.get(CoreOptions.class).strictConflictChecks, checkForActionConflicts, loadingPhaseThreads, viewOptions.cpuHeavySkyKeysThreadPoolSize, diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java index 3a75df94bfc999..d028ad81e253a9 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/CoreOptions.java @@ -170,6 +170,17 @@ public class CoreOptions extends FragmentOptions implements Cloneable { + "disabled.") public boolean strictFilesets; + @Option( + name = "incompatible_strict_conflict_checks", + oldName = "experimental_strict_conflict_checks", + defaultValue = "false", + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + metadataTags = OptionMetadataTag.INCOMPATIBLE_CHANGE, + effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION}, + help = + "Check for action prefix file path conflicts, regardless of action-specific overrides.") + public boolean strictConflictChecks; + @Option( name = "experimental_strict_fileset_output", defaultValue = "false", @@ -959,6 +970,7 @@ public FragmentOptions getHost() { host.includeRequiredConfigFragmentsProvider = includeRequiredConfigFragmentsProvider; host.debugSelectsAlwaysSucceed = debugSelectsAlwaysSucceed; host.checkTestonlyForOutputFiles = checkTestonlyForOutputFiles; + host.strictConflictChecks = strictConflictChecks; // === Runfiles === host.buildRunfilesManifests = buildRunfilesManifests; diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/OutputArtifactConflictTest.java b/src/test/java/com/google/devtools/build/lib/buildtool/OutputArtifactConflictTest.java index 3112cf56f248b6..1144dfdbb137bd 100644 --- a/src/test/java/com/google/devtools/build/lib/buildtool/OutputArtifactConflictTest.java +++ b/src/test/java/com/google/devtools/build/lib/buildtool/OutputArtifactConflictTest.java @@ -734,4 +734,54 @@ public void dependencyHasConflict_keepGoing_bothTopLevelTargetsFail( assertThat(eventListener.failedTargetNames) .containsExactly("//foo:top_level_a", "//foo:top_level_b"); } + + private void setupStrictConflictChecksTest() throws IOException { + write( + "foo/conflict.bzl", + "def _impl(ctx):", + " dir = ctx.actions.declare_directory(ctx.label.name + '.dir')", + " file = ctx.actions.declare_file(ctx.label.name + '.dir/file.txt')", + " ctx.actions.run_shell(", + " outputs = [dir, file],", + " command = 'mkdir -p $1 && touch $2',", + " arguments = [dir.path, file.path],", + " )", + " return [DefaultInfo(files = depset([dir, file]))]", + "", + "my_rule = rule(implementation = _impl)"); + write("foo/BUILD", "load(':conflict.bzl', 'my_rule')", "my_rule(name = 'bar')"); + } + + @Test + public void laxFollowedByStrictConflictChecks(@TestParameter boolean mergedAnalysisExecution) + throws Exception { + setupStrictConflictChecksTest(); + addOptions("--experimental_merged_skyframe_analysis_execution=" + mergedAnalysisExecution); + + addOptions("--noincompatible_strict_conflict_checks"); + buildTarget("//foo:bar"); + assertNoEvents(events.errors()); + + addOptions("--incompatible_strict_conflict_checks"); + assertThrows(ViewCreationFailedException.class, () -> buildTarget("//foo:bar")); + events.assertContainsError("One of the output paths"); + events.assertContainsError("is a prefix of the other"); + } + + @Test + public void strictFollowedByLaxConflictChecks(@TestParameter boolean mergedAnalysisExecution) + throws Exception { + setupStrictConflictChecksTest(); + addOptions("--experimental_merged_skyframe_analysis_execution=" + mergedAnalysisExecution); + + addOptions("--incompatible_strict_conflict_checks"); + assertThrows(ViewCreationFailedException.class, () -> buildTarget("//foo:bar")); + events.assertContainsError("One of the output paths"); + events.assertContainsError("is a prefix of the other"); + + events.clear(); + addOptions("--noincompatible_strict_conflict_checks"); + buildTarget("//foo:bar"); + assertNoEvents(events.errors()); + } }