diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java index 81621b7aed0e3a..b5888a78359264 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java @@ -560,21 +560,31 @@ public Label getFdoPrefetchHintsLabel() { + "except bar.o.") public List perFileLtoBackendOpts; + /** + * The value of "--crosstool_top" to use for building tools. + * + *

We want to make sure this stays bound to the top-level configuration when not explicitly set + * (as opposed to a configuration that comes out of a transition). Otherwise we risk using the + * wrong crosstool (i.e., trying to build tools with an Android-specific crosstool). + * + *

To accomplish this, we initialize this to null and, if it isn't explicitly set, use {@link + * #getNormalized} to rewrite it to {@link #crosstoolTop}. Blaze always evaluates top-level + * configurations first, so they'll trigger this. But no followup transitions can. + */ @Option( - name = "host_crosstool_top", - defaultValue = "null", - converter = LabelConverter.class, - documentationCategory = OptionDocumentationCategory.TOOLCHAIN, - effectTags = { - OptionEffectTag.LOADING_AND_ANALYSIS, - OptionEffectTag.CHANGES_INPUTS, - OptionEffectTag.AFFECTS_OUTPUTS - }, - help = - "By default, the --crosstool_top and --compiler options are also used " - + "for the host configuration. If this flag is provided, Bazel uses the default libc " - + "and compiler for the given crosstool_top." - ) + name = "host_crosstool_top", + defaultValue = "null", + converter = LabelConverter.class, + documentationCategory = OptionDocumentationCategory.TOOLCHAIN, + effectTags = { + OptionEffectTag.LOADING_AND_ANALYSIS, + OptionEffectTag.CHANGES_INPUTS, + OptionEffectTag.AFFECTS_OUTPUTS + }, + help = + "By default, the --crosstool_top and --compiler options are also used " + + "for the host configuration. If this flag is provided, Bazel uses the default libc " + + "and compiler for the given crosstool_top.") public Label hostCrosstoolTop; @Option( @@ -1004,10 +1014,22 @@ public Label getFdoPrefetchHintsLabel() { /** See {@link #targetLibcTopLabel} documentation. * */ @Override public FragmentOptions getNormalized() { + CppOptions newOptions = (CppOptions) this.clone(); + boolean changed = false; if (targetLibcTopLabel != null && targetLibcTopLabel.getName().equals(TARGET_LIBC_TOP_NOT_YET_SET)) { - CppOptions newOptions = (CppOptions) this.clone(); newOptions.targetLibcTopLabel = libcTopLabel; + changed = true; + } + if (hostCrosstoolTop == null) { + // Default to the initial target crosstoolTop. + newOptions.hostCrosstoolTop = crosstoolTop; + // Reset this, also, to maintain the invariant that host_compiler is ignored if + // host_crosstool_top is unset. + newOptions.hostCppCompiler = cppCompiler; + changed = true; + } + if (changed) { return newOptions; } return this; @@ -1017,14 +1039,8 @@ public FragmentOptions getNormalized() { public FragmentOptions getHost() { CppOptions host = (CppOptions) getDefault(); - // The crosstool options are partially copied from the target configuration. - if (hostCrosstoolTop == null) { - host.cppCompiler = cppCompiler; - host.crosstoolTop = crosstoolTop; - } else { - host.crosstoolTop = hostCrosstoolTop; - host.cppCompiler = hostCppCompiler; - } + host.crosstoolTop = hostCrosstoolTop; + host.cppCompiler = hostCppCompiler; // hostLibcTop doesn't default to the target's libcTop. // Only an explicit command-line option will change it. diff --git a/src/test/shell/integration/cpp_test.sh b/src/test/shell/integration/cpp_test.sh index 0f58c30351fe35..743b2d9de51a2a 100755 --- a/src/test/shell/integration/cpp_test.sh +++ b/src/test/shell/integration/cpp_test.sh @@ -156,4 +156,218 @@ EOF expect_not_log "Compiling $pkg/a.cc" } +# host_crosstool_top should default to the initial value of crosstool_top, +# not the value after a transition. +function test_default_host_crosstool_top() { + local -r pkg=$FUNCNAME + + # Define two different toolchain suites to use with crosstool_top. + mkdir -p $pkg/toolchain + cat >> $pkg/toolchain/BUILD <> $pkg/toolchain/toolchain.bzl <inner dependency changes the value of crosstool_top, + # the tool should use the initial crosstool. + cat >> $pkg/BUILD <> $pkg/display.bzl <& $TEST_log || fail "build failed" + expect_log "Outer //$pkg:outer found cc toolchain toolchain-alpha" + expect_log "Inner //$pkg:inner found cc toolchain toolchain-beta" + expect_log "Tool //$pkg:tool found cc toolchain toolchain-alpha" +} + run_suite "Tests for Bazel's C++ rules"