[clang] [clang][CMake] Auto-detect macOS SDK for DEFAULT_SYSROOT (PR #185986)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 11 14:49:17 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Noah (Noerr)

<details>
<summary>Changes</summary>

On macOS, from-source LLVM/Clang builds fail to compile even trivial programs because `DEFAULT_SYSROOT` is empty and Clang cannot find SDK headers or libraries:

```
$ clang main.c
ld: library 'System' not found
```

This patch auto-detects the macOS SDK using `xcrun --show-sdk-path` at **cmake configure time**, baking the result into `DEFAULT_SYSROOT`. This makes `clang hello.c` work out-of-the-box on macOS, matching other platforms.

### Why cmake-time detection instead of runtime detection?

Runtime `xcrun` detection was previously attempted in ecade80d9396 ([D136315](https://reviews.llvm.org/D136315)) but reverted the next day in a5f446bc4bb1 because it:
- Broke tests on macOS
- Attempted to run `xcrun` even when cross-compiling to macOS from non-Mac hosts
- Added process-spawning overhead to every clang invocation

The cmake-time approach avoids all of these issues:

| Problem with runtime detection | Cmake-time solution |
|-------------------------------|---------------------|
| Process-spawning overhead every compilation | `xcrun` runs once during LLVM build |
| Ran `xcrun` when cross-compiling to macOS from non-Mac hosts | `if(APPLE)` only true when building ON macOS |
| Test failures | Semantically equivalent to `-DDEFAULT_SYSROOT=...` which is already tested |
| Cross-compilation confusion | `NOT CMAKE_CROSSCOMPILING` skips detection for cross-compilers |

### Override behavior preserved

The priority chain in `Darwin.cpp` remains:
1. `--sysroot=` / `-isysroot` CLI flags (highest priority)
2. `SDKROOT` environment variable
3. `DEFAULT_SYSROOT` (this change — lowest priority fallback)

Users can always override the baked-in default.

### Impact beyond command-line builds

This also fixes JIT/runtime compilation scenarios where applications use LLVM as a library:
- POCL OpenCL JIT ([pocl/pocl#<!-- -->2041](https://github.com/pocl/pocl/issues/2041))
- chipStar HIP runtime compilation
- libtooling projects ([confirmed by @<!-- -->planetmarshall](https://github.com/llvm/llvm-project/issues/137352#issuecomment-2713921988))

CMake 4.0 removed its own `CMAKE_OSX_SYSROOT` workaround, stating "compilers are expected to choose a default macOS SDK on their own" ([cmake#<!-- -->26863](https://gitlab.kitware.com/cmake/cmake/-/issues/26863)). CMake 4.0.2 re-added a fallback ([MR 10734](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10734)), but noted this should also be resolved on the LLVM/Clang side.

### Changes

- `clang/CMakeLists.txt` — auto-detect SDK when `DEFAULT_SYSROOT` is empty
- `clang/docs/UsersManual.rst` — document Apple SDK discovery and override precedence
- `clang/test/Driver/darwin-default-sysroot.c` — lit test verifying clang finds the SDK without `SDKROOT`

### Testing

The lit test is a best-effort end-to-end check: it unsets `SDKROOT` and verifies that clang emits `-isysroot` pointing to a macOS SDK. This validates the observable result but not the cmake detection logic itself — a proper test for that would be a cmake-level test (e.g. `cmake --build` with an empty `DEFAULT_SYSROOT` and checking the configure output). The existing `check-clang` suite also provides implicit coverage, since many driver tests would fail if the sysroot were misconfigured.

Fixes #<!-- -->137352
Fixes #<!-- -->45225


---
Full diff: https://github.com/llvm/llvm-project/pull/185986.diff


3 Files Affected:

- (modified) clang/CMakeLists.txt (+17) 
- (modified) clang/docs/UsersManual.rst (+17) 
- (added) clang/test/Driver/darwin-default-sysroot.c (+8) 


``````````diff
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index f0d10603374b9..cc34ceb6ea26f 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -222,6 +222,23 @@ set(USE_DEPRECATED_GCC_INSTALL_PREFIX OFF CACHE BOOL "Temporary workaround befor
 set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." )
 set(DEFAULT_SYSROOT "" CACHE STRING
   "Default <path> to all compiler invocations for --sysroot=<path>." )
+
+# On macOS, auto-detect SDK so that 'clang hello.c' works out-of-the-box.
+if(APPLE AND NOT CMAKE_CROSSCOMPILING AND DEFAULT_SYSROOT STREQUAL "")
+  execute_process(
+    COMMAND xcrun --show-sdk-path
+    OUTPUT_VARIABLE _detected_sysroot
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+    ERROR_QUIET
+    RESULT_VARIABLE _xcrun_result
+  )
+  if(_xcrun_result EQUAL 0 AND EXISTS "${_detected_sysroot}")
+    set(DEFAULT_SYSROOT "${_detected_sysroot}" CACHE STRING
+      "Default <path> to all compiler invocations for --sysroot=<path>." FORCE)
+    message(STATUS "Auto-detected macOS SDK for DEFAULT_SYSROOT: ${DEFAULT_SYSROOT}")
+  endif()
+endif()
+
 if(GCC_INSTALL_PREFIX AND NOT USE_DEPRECATED_GCC_INSTALL_PREFIX)
   message(FATAL_ERROR "GCC_INSTALL_PREFIX is deprecated and will be removed. Use "
     "configuration files (https://clang.llvm.org/docs/UsersManual.html#configuration-files)"
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 5d7a124679d87..f77b80aa28b50 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -4786,6 +4786,23 @@ backend.
 Operating System Features and Limitations
 -----------------------------------------
 
+Apple
+^^^^^
+
+On Apple platforms, standard headers and libraries are not provided by
+the base system. Instead, they are part of the Xcode SDK. When building
+LLVM from source on macOS, the SDK location is auto-detected at cmake
+configure time and baked into Clang as the default sysroot.
+
+The SDK location can be overridden in the following ways (highest priority
+first):
+
+- The ``-isysroot`` or ``--sysroot=`` command-line option.
+- The ``SDKROOT`` environment variable, which is set automatically by
+  Xcode tools such as ``xcrun``.
+- The ``DEFAULT_SYSROOT`` cmake option, which can be set explicitly at
+  LLVM build time with ``-DDEFAULT_SYSROOT=/path/to/sdk``.
+
 Windows
 ^^^^^^^
 
diff --git a/clang/test/Driver/darwin-default-sysroot.c b/clang/test/Driver/darwin-default-sysroot.c
new file mode 100644
index 0000000000000..726fe063fd7d6
--- /dev/null
+++ b/clang/test/Driver/darwin-default-sysroot.c
@@ -0,0 +1,8 @@
+// REQUIRES: system-darwin
+
+// Check that clang finds the macOS SDK automatically via DEFAULT_SYSROOT,
+// even when SDKROOT is not set in the environment.
+//
+// RUN: env -u SDKROOT %clang -c %s -### 2>&1 | FileCheck %s
+//
+// CHECK: "-isysroot" "{{.*MacOSX[0-9\.]*\.sdk}}"

``````````

</details>


https://github.com/llvm/llvm-project/pull/185986


More information about the cfe-commits mailing list