diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java index a8511246b9807f..6835ba2bfe6291 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java @@ -36,6 +36,7 @@ import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.concurrent.BlazeInterners; +import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.skyframe.BuildConfigurationKey; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; @@ -139,6 +140,12 @@ public void reportInvalidOptions(EventHandler reporter) { for (Fragment fragment : fragments.values()) { fragment.reportInvalidOptions(reporter, this.buildOptions); } + + if (options.outputDirectoryName != null) { + reporter.handle( + Event.error( + "The internal '--output directory name' option cannot be used on the command line")); + } } /** 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 2fc7ee409cc986..5458c198b64577 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 @@ -245,6 +245,23 @@ public class CoreOptions extends FragmentOptions implements Cloneable { + "'fastbuild', 'dbg', 'opt'.") public CompilationMode hostCompilationMode; + /** + * This option is used internally to set output directory name of the host configuration to + * a constant, so that the output files for the host are completely independent of those for the + * target, no matter what options are in force (k8/piii, opt/dbg, etc). + */ + @Option( + name = "output directory name", + defaultValue = "null", + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + effectTags = { + OptionEffectTag.LOSES_INCREMENTAL_STATE, + OptionEffectTag.AFFECTS_OUTPUTS, + OptionEffectTag.LOADING_AND_ANALYSIS + }, + metadataTags = {OptionMetadataTag.INTERNAL}) + public String outputDirectoryName; + @Option( name = "experimental_enable_aspect_hints", defaultValue = "false", @@ -919,6 +936,7 @@ public IncludeConfigFragmentsEnumConverter() { public FragmentOptions getHost() { CoreOptions host = (CoreOptions) getDefault(); + host.outputDirectoryName = "host"; host.affectedByStarlarkTransition = affectedByStarlarkTransition; host.outputDirectoryNamingScheme = outputDirectoryNamingScheme; host.compilationMode = hostCompilationMode; diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java index 0ff96d0a655b1f..10dcf59e794a30 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ExecutionTransitionFactory.java @@ -128,8 +128,10 @@ private static BuildOptions transitionImpl(BuildOptionsView options, Label execu CoreOptions coreOptions = checkNotNull(execOptions.get(CoreOptions.class)); coreOptions.isHost = false; coreOptions.isExec = true; + // Disable extra actions coreOptions.actionListeners = null; + coreOptions.outputDirectoryName = null; // Then set the target to the saved execution platform if there is one. PlatformOptions platformOptions = execOptions.get(PlatformOptions.class); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java b/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java index 5d565a8a69aa23..57e95bb2b88517 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java @@ -142,7 +142,8 @@ public ArtifactRoot getRoot( this.directories = directories; this.mnemonic = buildMnemonic(options, platformOptions, fragments, transitionDirectoryNameFragment); - this.outputDirName = options.isHost ? "host" : mnemonic; + this.outputDirName = + (options.outputDirectoryName != null) ? options.outputDirectoryName : (options.isHost ? "host" : mnemonic); this.outputDirectory = OutputDirectory.OUTPUT.getRoot(outputDirName, directories, mainRepositoryName); diff --git a/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java b/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java index ad0bb8ac6e75a7..960445b48f6e6d 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java @@ -28,6 +28,7 @@ import com.google.devtools.build.lib.actions.Actions; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.FailAction; +import com.google.devtools.build.lib.analysis.config.CoreOptions; 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.configuredtargets.InputFileConfiguredTarget; @@ -52,6 +53,8 @@ import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.skyframe.NotifyingHelper.Listener; +import com.google.devtools.common.options.Options; +import com.google.devtools.common.options.OptionsParsingException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; @@ -542,6 +545,23 @@ reporter, top, getBuildConfigurationCollection(), /* toolchainContexts= */ null) assertThat(targets).containsExactly(innerDependency, fileDependency); } + /** Tests that the {@code --output directory name} option cannot be used on the command line. */ + @Test + public void testConfigurationShortName() { + // Check that output directory name is still the name, otherwise this test is not testing what + // we expect. + CoreOptions options = Options.getDefaults(CoreOptions.class); + options.outputDirectoryName = "/home/wonkaw/wonka_chocolate/factory/out"; + assertWithMessage("The flag's name may have been changed; this test may need to be updated.") + .that(options.asMap().get("output directory name")) + .isEqualTo("/home/wonkaw/wonka_chocolate/factory/out"); + + OptionsParsingException e = + assertThrows( + OptionsParsingException.class, () -> useConfiguration("--output directory name=foo")); + assertThat(e).hasMessageThat().isEqualTo("Unrecognized option: --output directory name=foo"); + } + // Regression test: "output_filter broken (but in a different way)" @Test @Ignore("b/182560362 Starlark java_library can't output warnings") 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 a6804ba0148917..16e9c1594feb64 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 @@ -210,7 +210,7 @@ public void multiplePackagePathsFirstWins() throws Exception { assertThat(mapped.getOptions().get(CoreOptions.class).cpu).isEqualTo("one"); } - // Internal flags (OptionMetadataTag.INTERNAL) cannot be set from the command-line, but + // Internal flags, such as "output directory name", cannot be set from the command-line, but // platform mapping needs to access them. @Test public void ableToChangeInternalOption() throws Exception { @@ -218,7 +218,8 @@ public void ableToChangeInternalOption() throws Exception { "my_mapping_file", "platforms:", // Force line break " //platforms:one", // Force line break - " --internal foo=something_new"); + " --internal foo=something_new", + " --output directory name=updated_output_dir"); PlatformMappingValue platformMappingValue = executeFunction(PlatformMappingValue.Key.create(PathFragment.create("my_mapping_file"))); @@ -230,6 +231,8 @@ public void ableToChangeInternalOption() throws Exception { assertThat(mapped.getOptions().get(DummyTestFragment.DummyTestOptions.class).internalFoo) .isEqualTo("something_new"); + assertThat(mapped.getOptions().get(CoreOptions.class).outputDirectoryName) + .isEqualTo("updated_output_dir"); } private PlatformMappingValue executeFunction(PlatformMappingValue.Key key) throws Exception {