From f772d266a48dc670c994eaea3b01e7d7b3aef5b5 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Thu, 22 Jan 2026 10:10:40 -0800 Subject: [PATCH] Add the Clang sysroot to the config output (#6642) --- toolchain/driver/config_subcommand.cpp | 44 +++++++++++--------- toolchain/driver/driver_test.cpp | 5 +++ toolchain/driver/testdata/fail_config.carbon | 8 +++- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/toolchain/driver/config_subcommand.cpp b/toolchain/driver/config_subcommand.cpp index 7744fb5602e0..abcd070d6184 100644 --- a/toolchain/driver/config_subcommand.cpp +++ b/toolchain/driver/config_subcommand.cpp @@ -68,12 +68,17 @@ struct ConfigDataEntry { }; } // namespace -// Creates a Clang invocation and queries it for the include directories -// searched during compilation. If there are any errors setting up Clang, this -// will diagnose them using `driver_env.consumer` and return `std::nullopt`. -static auto ComputeClangIncludeDirs(DriverEnv& driver_env, - llvm::StringRef target_str) - -> std::optional> { +// Creates a Clang invocation and queries it for config data to render. +// +// This includes the sysroot and the include directories searched during +// compilation. +// +// If there are any errors setting up Clang, this will diagnose them using +// `driver_env.consumer` and return `false`. If successful, returns `true`. +static auto ComputeClangConfig(DriverEnv& driver_env, + llvm::StringRef target_str, + llvm::SmallVectorImpl& data) + -> bool { // Build a library invocation of Clang in order to query its header search // paths. std::shared_ptr clang_invocation = @@ -103,7 +108,7 @@ static auto ComputeClangIncludeDirs(DriverEnv& driver_env, "unable to setup the requested target `{0}`", std::string); driver_env.emitter.Emit(ConfigFailedToSetupTarget, target_str.str()); - return std::nullopt; + return false; } auto header_search = std::make_unique( @@ -117,14 +122,20 @@ static auto ComputeClangIncludeDirs(DriverEnv& driver_env, // If we ended up diagnosing any errors, just return. They will have been // converted to Carbon diagnostics. if (error_tracker.seen_error()) { - return std::nullopt; + return false; } + data.push_back({.key = "CLANG_SYSROOT", + .value = clang_instance->getHeaderSearchOpts().Sysroot}); + llvm::SmallVector search_paths; for (const auto& search_dir : header_search->search_dir_range()) { search_paths.push_back(search_dir.getName().str()); } - return search_paths; + data.push_back( + {.key = "CLANG_INCLUDE_DIRS", .value = std::move(search_paths)}); + + return true; } static auto RenderDataAsJson(llvm::ArrayRef data, @@ -200,17 +211,10 @@ auto ConfigSubcommand::Run(DriverEnv& driver_env) -> DriverResult { .value = llvm::StringRef(*read_result).rtrim().str()}); } - // Compute and print Clang's include dirs if we can. - std::optional> clang_include_dirs = - ComputeClangIncludeDirs(driver_env, options_.codegen_options.target); - if (clang_include_dirs) { - data.push_back( - {.key = "CLANG_INCLUDE_DIRS", .value = *std::move(clang_include_dirs)}); - } else { - // This will have been diagnosed while computing, continue with degraded - // data. - result = false; - } + // Compute and print Clang's config entries if we can. This will have been + // diagnosed while computing, so just track if we hit errors. + result &= + ComputeClangConfig(driver_env, options_.codegen_options.target, data); llvm::sort(data, [](const ConfigDataEntry& lhs, const ConfigDataEntry& rhs) { return lhs.key < rhs.key; diff --git a/toolchain/driver/driver_test.cpp b/toolchain/driver/driver_test.cpp index 1579f9c40735..36281e058b99 100644 --- a/toolchain/driver/driver_test.cpp +++ b/toolchain/driver/driver_test.cpp @@ -250,6 +250,11 @@ TEST_F(DriverTest, ConfigJson) { json_obj->getString("INSTALL_ROOT"); ASSERT_THAT(install_root, Ne(std::nullopt)); EXPECT_THAT(Filesystem::Cwd().OpenDir(install_root->str()), IsSuccess(_)); + + std::optional clang_sysroot = + json_obj->getString("CLANG_SYSROOT"); + ASSERT_THAT(clang_sysroot, Ne(std::nullopt)); + EXPECT_THAT(Filesystem::Cwd().OpenDir(clang_sysroot->str()), IsSuccess(_)); } } // namespace diff --git a/toolchain/driver/testdata/fail_config.carbon b/toolchain/driver/testdata/fail_config.carbon index 1018c7a4de82..74e6422312e1 100644 --- a/toolchain/driver/testdata/fail_config.carbon +++ b/toolchain/driver/testdata/fail_config.carbon @@ -14,10 +14,16 @@ // CHECK:STDERR: error: unable to read the installation's digest file: {{.*}} // CHECK:STDERR: -// The rest of the config should still be displayed: +// The rest of the config should still be displayed. +// +// Note that the results here are not "portable", and depend on the `--target` +// argument above. We pass explicit targets to get predictable results in Bazel +// tests. +// // CHECK:STDOUT: CLANG_INCLUDE_DIRS: // CHECK:STDOUT: {{.*}}/toolchain/install/prefix/lib/carbon/llvm/lib/clang/22/include // CHECK:STDOUT: CLANG_RESOURCE_DIR: {{.*}}/toolchain/install/prefix/lib/carbon/llvm/lib/clang/22 +// CHECK:STDOUT: CLANG_SYSROOT: / // CHECK:STDOUT: INSTALL_ROOT: {{.*}}/toolchain/install/prefix/lib/carbon/ // CHECK:STDOUT: LLVM_BINDIR: {{.*}}/toolchain/install/prefix/lib/carbon/llvm/bin // CHECK:STDOUT: VERSION: {{[0-9]+}}.{{[0-9]+}}.{{[0-9]+}}-{{.*}}