Skip to content

Reconfigure native CMake builds from scratch when the compiler inputs change - #135028

Open
lewing wants to merge 4 commits into
dotnet:mainfrom
lewing:lewing-cmake-toolchain-change-reconfigure
Open

lewing wants to merge 4 commits into
dotnet:mainfrom
lewing:lewing-cmake-toolchain-change-reconfigure

Conversation

@lewing

@lewing lewing commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

CMake detects the compiler only on a build directory's first configure, so later changes to the toolchain file, CC/CXX or emcmake are ignored. Since the WASI SDK and emsdk moved to versioned tool cache directories, every SDK bump leaves existing local build directories using the old compiler. After #134992 that caused link errors like undefined symbol: __wasilibc_descriptor_deallocate. CI configures fresh and is unaffected.

gen-buildsys.sh/.cmd now record the inputs that select the compiler in <build dir>/cmake_compiler_inputs.txt: the toolchain file (environment variable and -DCMAKE_TOOLCHAIN_FILE arguments), CC, CXX, the first line of $CC --version (catches an Xcode update or package upgrade behind the same path), the resolved cmake command including wrappers like emcmake, and on Windows VCToolsInstallDir. If a build directory's record is missing or differs, CMake runs with --fresh. That keeps object files, so ninja only rebuilds what changed. Existing build directories reconfigure once, the first time they're built with this change.

Validated locally on macOS. WASI SDK 33.0 → 34.0 (native libraries and CoreCLR), a CLR_CC host compiler switch, an Xcode → Command Line Tools switch, and an emsdk version change all reconfigured with the new compiler, and unchanged builds stayed incremental. gen-buildsys.cmd wasn't run (no Windows host).

Note

This PR description was generated with GitHub Copilot.

…changes

CMake detects the compiler only on a build directory's first configure, so
an existing build directory keeps using the old compiler when a different
CMAKE_TOOLCHAIN_FILE is passed. The WASI SDK and emscripten live in
versioned tool cache directories, so every SDK bump left incremental local
builds compiling and linking with the previous SDK.

When the existing CMakeCache.txt records a CMAKE_TOOLCHAIN_FILE different
from the requested one, configure with --fresh. Applies to
eng/native/gen-buildsys.sh and gen-buildsys.cmd (CoreCLR, native libraries,
corehost) and to the Mono configure steps in mono.proj, wasi.proj and
browser.proj.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

…nges

Instead of comparing CMAKE_TOOLCHAIN_FILE against CMakeCache.txt (which
needed per-SDK knowledge of the toolchain emcmake injects, plus path
normalization), gen-buildsys.sh/.cmd now record the inputs that select
the compiler in <build dir>/cmake_compiler_inputs.txt after a successful
configure: the CMAKE_TOOLCHAIN_FILE environment variable, CC, CXX, every
-DCMAKE_TOOLCHAIN_FILE argument, the full path of the cmake command and
any wrapper such as emcmake, and on Windows VCToolsInstallDir. CMake is
run with --fresh when an existing build directory's record is missing or
differs. This covers WASI SDK and emsdk bumps as well as host compiler
changes such as a new clang-N or CLR_CC.

On Windows, emcmake is now invoked with `call` so control returns to the
script when the launcher is a batch file.

Revert the Mono configure changes (mono.proj, wasi.proj, browser.proj).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lewing lewing changed the title Reconfigure native CMake builds from scratch when the toolchain file changes Reconfigure native CMake builds from scratch when the compiler inputs change Oct 1, 2026
Comment thread eng/native/gen-buildsys.sh
Comment thread eng/native/gen-buildsys.sh Outdated
Comment thread eng/native/gen-buildsys.cmd Outdated
Comment thread eng/native/gen-buildsys.cmd
Log a single message when the recorded compiler inputs are missing or
differ, without printing a diff. In gen-buildsys.sh, keep the cmake
invocation last (writing the record with `&&`) and restore the comment
about exit code propagation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…path

/usr/bin/clang on macOS is a shim, so an Xcode update or a DEVELOPER_DIR
switch replaces the compiler without changing CC. Record the first line
of `$CC --version` too.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jkotas

jkotas commented Oct 2, 2026

Copy link
Copy Markdown
Member

If a build directory's record is missing or differs, CMake runs with --fresh. That keeps object files, so ninja only rebuilds what changed.

Is keeping the object files the desired behavior? I would expect that you want to wipe all object files when the compiler changes.


set __ExtraCmakeParams="-DCMAKE_INSTALL_PREFIX=%__CMakeBinDir%" "-DCLR_CMAKE_HOST_ARCH=%__Arch%" %__ExtraCmakeParams%

rem CMake detects the compiler only on a build directory's first configure. Later configures keep the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, cmake is adding the first-class way to solve this problem: https://cmake.org/cmake/help/git-stage/envvar/CMAKE_SYSTEM_ENVIRONMENT_ACTION.html . Once we can depend on cmake 4.5 for day-to-day development, this open coded workaround can be simplified a lot.

cc @jkoritzinsky

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants