CMake writes the compiler paths verbatim into CMakeRCCompiler.cmake and
friends, where a backslash starts an escape sequence, so %ProgramFiles%
arrived as "C:\Program Files/LLVM/..." and tripped on \P. Same trap
waits for the Python root at C:\hostedtoolcache.
CMake wires up C++20 module scanning for Clang only when the frontend
variant is GNU; for clang-cl it sets nothing and refuses to generate:
"the compiler does not provide a way to discover the import graph
dependencies". Not a missing tool, a hard gap - Compiler/Clang-CXX.cmake
guards the whole scandep block on the GNU variant.
clang++ on Windows still targets x86_64-pc-windows-msvc, so the ABI, the
SDK, the vcpkg packages and D3D12 are unchanged. CMake then takes the
GNU path and leaves MSVC false, which is what the /MD /Zi /O2 block wants
anyway; the version resource had to move to a WIN32 guard to survive.
clang-cl keeps the MSVC ABI, so the Windows SDK, the vcpkg packages and
D3D12 all still link; only the front end changes. That front end is the
one whose module support has been giving way - global module fragment
merging and type completeness at a template's instantiation point.
Switches the job to Ninja, which is where CMake's module scanning is best
supported, with vcvars64 for the SDK paths. Ninja is single-config, so
the artifacts move from build/bin/<config>/ to build/bin/.
CMakeLists: the MSVC-only blocks tested CMAKE_CXX_COMPILER_ID, which
clang-cl reports as Clang, so the version resource, the icon and /utf-8
would have been dropped silently. They test MSVC now, which is true for
both. /MAP and /MP stay behind a real-MSVC check - the first is a
link.exe spelling, the second clang-cl rejects.
Linux CI switches to clang 22; fixes what that exposed - export on
out-of-line member definitions, missing std includes, missing glm
imports. GCC 16 still builds.