#31507 build: Use clang-cl to build on Windows natively

ReviewabilityReviewsAgreementSize
#31507 hebasto build: Use clang-cl to build on Windows nativelyReady1 (+1)Strong222
  • Eliminate MSVC-specific compiler bugs and workaround maintenance on native Windows builds
  • Speed up native Windows CI runs and produce substantially faster Windows binaries
  • Ready for review
  • Strong support with no open objections (maflcko, hodlinator)
  • Support for better compiler compatibility and potential codegen gains (maflcko)
  • Verified native Windows builds and binary execution on Visual Studio 18.7.0 (hodlinator)
  • Maintenance objection resolved by dropping MSVC support entirely instead of adding a second compiler (fanquake)
  • Concept approval without stated reasons (sedited)
  • 222 lines added or modified outside tests
  • 0 lines added or modified in tests
  • 241 lines removed in total
  • 22 files, 14 commits
Build and CI#5 of 56
P2 · platform fix
  • P2 because native Windows CI build times drop by 38% while fixing multiple compiler bugs
  • Significantly improves generated Windows binary performance, raising block connection throughput by 55-60%
  • Unblocks future hardware-accelerated inline assembly optimizations on Windows
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Switches native Windows builds and CI from MSVC (`cl.exe`) to Clang (`clang-cl.exe`), completely dropping support for compiling with `cl.exe`. CMake presets, compiler flags, and feature introspection tests are updated for Clang's MSVC-compatible frontend, including linking Clang's runtime builtins library for 128-bit operations. Several MSVC-specific workarounds (such as non-`constexpr` byte swaps and requires-expression limitations) are removed, and the minimum Visual Studio version is bumped to 18.7.

Problem: Native Windows compilation with `cl.exe` lacks inline assembly support on x64 and ARM64, runs slower on CI, generates slower binaries, and creates maintenance burden due to MSVC-specific compiler bugs and internal compiler errors (#31456, #36153).

Evidence of importance:

  • Author benchmarks report block connection throughput increasing from ~7.4 to ~11.5–11.8 block/s (~55–60% speedup) and deserialization tests improving by ~55% when switching from MSVC to clang-cl.
  • Author CI timing demonstrates a 38% reduction in Windows CI build times (from 20m 35s with MSVC to 12m 43s with clang-cl).
  • PR description notes closing #31456 and #36153, and addressing #14118.

Scope: Changes build flags across CMake files, alters introspection tests to be warning-free under -Werror, and renames build documentation from build-windows-msvc.md to build-windows-native.md.

Risk of a mistake: medium (build, tests). Changing the Windows compiler toolchain could break native Windows developer builds or introduce compiler-specific code generation regressions.

Changed since the previous assessment: No conceptual change to the toolchain switch; refines warning cleanups in CMake introspection tests so they pass with strict `-Werror` enforcement, and renames the Windows build documentation.

Reviewability

Ready

Nothing known that would invalidate a review now.

Waiting on (from the thread read):

  • reviewer: fanquake to follow up on CRT diagnostics explanation 2026-10-25

Agreement

Strong

substantive support, no open objection (maflcko, hodlinator, hodlinator)

Thread notes: hodlinator tested Visual Studio 18.7.0 and confirmed functioning manifests, dropped the suggestion to specify clang-cl versions directly, verified the byteswap and TryAppendCXXFlags cleanups, and gave a full ACK.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
theuni (member)suggestion, approachtest against CMAKE_CXX_COMPILER_FRONTEND_VARIANT instead of if(MSVC)answered · author explained CMake version compatibility issueansweredyes2024-12-16: 'it seems like maybe CMAKE_CXX_COMPILER_FRONTEND_VARIANT is what we should be testing against?'
Status from: 2024-12-17: hebasto: 'It doesn't seem reliable, as it might not be set at all for CMake versions < 3.26.'
theuni (member)question, approachwhether if(MSVC) can be eliminated in favor of CMAKE_CXX_COMPILER_ID or compiler frontend variant tests in CMakeanswered · author explained MSVC checks are needed to distinguish syntax flags and frontend variant is unreliable on older CMakeansweredyes2024-12-16: 'Can't the `if(MSVC)` go away and we just rely on the `CMAKE_CXX_COMPILER_ID` test?'
Status from: 2024-12-17: hebasto: 'In this case, I think we do want to check `MSVC`, as it separates MSVC specific syntax `/WX` from GCC syntax `-Werror`.'
fanquake (member)objection, maintenanceincreases CI and maintenance burden by adding another compiler for Windows without improving shipped binaries or replacing MSVCfixed · fix pushed · author removed MSVC supportchangedyes2025-05-21: 'It seems like this is just adding even more ways to compile for Windows, which we have to add more CI / and more work arounds for, but doesn't actually improve the Windows binaries we are shipping to'
Status from: 2026-02-19: hebasto: 'The support for MSVC has been removed.'
hodlinator (member)question, maintenancewhether the #elif branch in byteswap.h should be removed since MSVC support is droppedfixed · fix pushed · author removed the #elif branch in byteswap.hansweredyes2026-08-13: 'Should this #elif-branch be removed in the commit dropping support for MSVC?'
Status from: 2026-10-14: hebasto: 'Thanks! Removed.'
maflcko (member)objection, correctnesssuppressing -Wno-return-type in CI may hide C++ standard violations or potential undefined behavioraccepted · reviewer confirmed the warning is not a blocker and approved the PRansweredyes2026-08-18: 'Is this a violation of the C++26 standard? ... If not, it should not be hidden, to be able to confirm it.'
Status from: 2026-10-14: maflcko: 'But not a blocker. Seems fine to progress here.'
maflcko (member)question, scopewhether the PR description should note that this closes issue 36153answered · author added the issue reference to the PR descriptionansweredyes2026-09-29: 'Missing "closes https://github.com/bitcoin/bitcoin/issues/36153" in pull description?'
Status from: 2026-10-14: hebasto: 'Thanks! Added.'
maflcko (member)suggestion, maintenanceremove the #if !defined(_MSC_VER) workaround on next rebasefixed · fix pushed · author removed the workaroundansweredyes2026-10-07: 'Also, could remove on the next rebase: #if !defined(_MSC_VER)'
Status from: 2026-10-14: hebasto: 'Removed.'
maflcko (member)question, maintenancewhether cmake -E env was left unaddressedanswered · author explained cmake -E env usageansweredyes2026-10-14: 'forgot to address this?'
Status from: 2026-10-14: hebasto: '`cmake -E env` is a CMake's multi-platform [analogue](https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-'
maflcko (member)suggestion, correctnessrevisit leveldb cmake changes in commit e0a2429ee007122e61238953c15ecdeddda2e42d to match 4d58c3271c0500a1294237e4d099ed769a59f7c0fixed · fix pushed · author fixed the leveldb cmake changesansweredyes2026-10-14: 'This is wrong, see 4d58c3271c0500a1294237e4d099ed769a59f7c0'
Status from: 2026-10-15: hebasto: 'Thanks! Fixed.'
maflcko (member)suggestion, maintenanceinline identical environment variables or flatten the map to a single array in ci-windows.pyfixed · fix pushed · author reworked the env vars in ci-windows.pyansweredyes2026-10-14: 'Is there value in having different env vars here? They look the same, so maybe just inline them once here? Or at least flatten the map to a single array?'
Status from: 2026-10-15: hebasto: 'Thanks! Reworked.'
maflcko (member)question, approachwhether the issue is still reproducible even after removing boost signals2answered · fanquake and author confirmed the build error is still reproducibleansweredyes2026-10-14: 'Is this still reproducible even after removing boost signals2, ref comment from the issue: https://github.com/bitcoin/bitcoin/issues/28109#issuecomment-1662256481'
Status from: 2026-10-15: hebasto: 'It is: cmake --build build ... src/wallet/CMakeFiles/bitcoin_wallet.dir/wallet.cpp.obj: too many sections (34047)'
maflcko (member)question, maintenancewhether the comment can be removed if it works fine locally with clang-clfixed · fix pushed · author reworked the sectionansweredyes2026-10-14: 'I don't understand this comment. It works fine locally with clang-cl, so this can be removed?'
Status from: 2026-10-15: hebasto: 'Reworked.'
maflcko (member)suggestion, maintenancedrop the rename commit or adjust doc/dependencies.mdfixed · fix pushed · author adopted the suggested documentation adjustmentansweredyes2026-10-14: 'is the rename 9ad9186387c6f9db8559966abcc7d32d5cef4c8e commit really needed? MSVC seems the internal name in cmake and is still used in the docs here. Either drop the commit or adjust this line?'
Status from: 2026-10-16: hebasto: 'Taken.'
maflcko (member)objection, correctnessclang-cl can miss Minisketch's CLMUL fast path due to cmake/minisketch.cmake leaving CLMUL_CXXFLAGS empty under MSVC branch and probing without -mpclmulfixed · fix pushed · author addressed feedback in a new pushchangedyes2026-10-15: 'clang-cl can miss Minisketch's CLMUL fast path (CMakePresets.json:12, head)'
Status from: 2026-10-16: hebasto: 'Most of the recent feedback has been addressed.'
hodlinator (member)question, maintenancewhether ccache can be enabled on Windows with clang-cl and whether remaining if(MSVC) checks in crc32c, introspection, minisketch, and kernel CMake files are still requiredanswered · author replied deferring ccache to a follow-up and demonstrated compiler ID checksansweredyes2026-10-15: '/cmake/ccache.cmake has `if(NOT MSVC)` - Maybe we can enable ccache on Windows with clang-cl? :) /cmake/crc32c.cmake still uses `if(MSVC)`'
Status from: 2026-10-16: hebasto: 'In my experience, this can have non-obvious pitfalls and requires extensive testing, so I'd rather leave it for a follow'
fanquake (member)question, approachwhether the large object file issue in wallet.cpp is back againanswered · author showed compiler output reproducing the error and reworked itansweredyes2026-10-15: 'Looks like its back again?'
Status from: 2026-10-15: hebasto: 'It is: cmake --build build ... too many sections (34047)'
hodlinator (member)suggestion, maintenancesimplify TryAppendCXXFlags.cmake by removing the if(MSVC) check when dropping MSVC supportfixed · fix pushed · author pushed the requested simplification after hodlinator noted it was missing in earlier pushansweredyes2026-10-19: 'Could simplify to this when dropping support for MSVC?'
Status from: 2026-10-26: hebasto: 'All the changes you requested were already done locally but somehow didn’t make it into my previous push. Should be fine now.'
hodlinator (member)suggestion, maintenanceremove BSWAP_CONSTEXPR entirely from src/compat/byteswap.h since it is never definedfixed · fix pushed · author pushed the change replacing inline BSWAP_CONSTEXPR with constexpransweredyes2026-10-19: 'Seems like we can remove `BSWAP_CONSTEXPR` from the code entirely in the commit "cmake: Drop support for MSVC" since it's never defined above?'
Status from: 2026-10-26: hebasto: 'All the changes you requested were already done locally but somehow didn’t make it into my previous push. Should be fine now.'
hodlinator (member)question, maintenancewhether Visual Studio 17.14 is sufficient given that older clang-cl versions produce binaries that fail to start due to manifest errorsanswered · author helped with installation steps and hodlinator confirmed VS 18.7.0 works whereas 18.6 failsansweredyes2026-10-19: 'I'm not sure Visual Studio 17.14 is sufficient. This PR seems to require something fairly recent.'
Status from: 2026-10-26: hodlinator: 'Rebuilt Bitcoin Core binaries & confirmed they had *functioning* manifests, allowing them to execute. ✅'
hodlinator (member)suggestion, maintenanceswitch to specifying the Clang-CL version rather than VS version, or both, in doc/dependencies.mdaccepted · reviewer dropped the suggestion after finding version catalogues hard to map and being satisfied with VS version documentationansweredyes2026-10-20: 'maybe we should switch to specifying the Clang-CL version rather than VS version, or both?'
Status from: 2026-10-26: hodlinator: 'I'm okay with trusting that for now. If a user is running an older version it's trivial for them to upgrade and report an issue.'
maflcko (member)suggestion, maintenancespecify 18.11 in doc/dependencies.md if prior versions are known not to workfixed · fix pushed · author updated the dependencies documentation after confirming VS 18.7.0 is the minimum working versionansweredyes2026-10-22: 'If 18.11 is known to work, and prior versions are know to not work, the docs should say so? Unless someone has tested a prior version and it is known to work, the docs shouldn't claim so?'
Status from: 2026-10-24: hebasto: 'The docs have been updated.'
fanquake (member)suggestion, maintenancedrop the additions from the PR if unrelated to the compiler switch, or document why they are neededanswered · author explained that while the CRT peculiarities predate the PR, the compiler diagnostics differ and require -Wno-return-type in CIansweredyes2026-10-25: 'If these additions are unrelated to the compiler switch, can you drop them from the PR? Otherwise, it would seem like they are related, and we could document why they are needed?'
Status from: 2026-10-25: hebasto: 'I mean, MS CRT peculiarities, such as the absence of the `[[noreturn]]` attribute on `std::abort()`, predate this PR. Ho'

Support:

  • maflcko (member) (2024-12-16): Seems fine to add this, because it is easy to remove and can increase the build compatibly in the meantime. Also, it allows to evaluate the codegen, which could be substantially better than msvc
  • hodlinator (member) (Concept ACK, 2026-08-20) [both]: tested native Windows build and verified CMake flags
  • sedited (member) (Concept ACK, 2026-10-07): (no reason given) [not substantive]
  • maflcko (member) (ACK, 2026-10-14): (no reason given) [not substantive]
  • maflcko (member) (ACK, 2026-10-15): lgtm. Only change is addressing the small nits. [not substantive]
  • hodlinator (member) (ACK, 2026-10-26) [read]: ACK dc230de70c88c2be1d9b828cdcf64f1dff738d7b Performed range-diff to confirm initial 7 commits match #36554, only rebased (`git range-diff 5bb7c564...b471c3f7`, already ACKed).

Participants:

  • fanquake (member, objection, 25 statements 2024-12-16 to 2026-10-25): objected to adding clang-cl without dropping MSVC; asked about wallet.cpp large object files and CRT diagnostic suppressions
  • maflcko (member, support, 29 statements 2024-12-16 to 2026-10-22): reviewed and gave ACK; raised comments and suggestions on CMake, LevelDB, CI, and dependency docs
  • theuni (member, question, 3 statements 2024-12-16 to 2024-12-16): asked about using compiler ID or frontend variant checks in CMake instead of MSVC
  • hodlinator (member, support, 21 statements 2026-08-13 to 2026-10-26): gave ACK after verifying CMake cleanups and testing native Windows builds with older VS versions
  • sedited (member, support, 1 statements 2026-10-07 to 2026-10-07): gave Concept ACK

Dependencies

Enables:

  • Hardware-accelerated inline assembly optimizations on Windows (e.g., secp256k1 #1681)

Files

4 lines under test/bench/ci.

  • CMakeLists.txt +76/-69
  • cmake/introspection.cmake +65/-67
  • doc/{build-windows-msvc.md => build-windows-native.md} +14/-11
  • src/compat/endian.h +12/-12
  • cmake/minisketch.cmake +3/-19
  • src/compat/byteswap.h +3/-15
  • cmake/crc32c.cmake +6/-10
  • doc/release-notes-31507.md +15/-0
  • CMakePresets.json +6/-8
  • cmake/leveldb.cmake +3/-7
  • .github/ci-windows.py +5/-1
  • cmake/module/CheckSourceCompilesWithFlags.cmake +4/-2
  • cmake/module/TryAppendCXXFlags.cmake +1/-5
  • .github/workflows/ci.yml +2/-2
  • src/kernel/CMakeLists.txt +1/-3
  • src/test/util_not_null_tests.cpp +0/-4
  • cmake/module/TestAppendRequiredLibraries.cmake +1/-1
  • doc/README.md +1/-1
  • doc/build-windows.md +1/-1
  • doc/dependencies.md +1/-1
  • src/qt/CMakeLists.txt +1/-1
  • src/qt/README.md +1/-1

Card

The short text the ranking pass compares across PRs.

Switches native Windows builds and CI from MSVC (cl.exe) to clang-cl, dropping support for cl.exe. Native builds with cl.exe lacked inline assembly support on x64/ARM64 and regularly required workarounds for compiler bugs and internal errors (#31456, #36153). Author benchmarks report block connection throughput increasing by ~55–60% and Windows CI build time dropping by 38%. Developers building natively on Windows must install the Clang C++ tools and use Visual Studio 18.7 or newer.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-28T01:21, confidence high, input hash 43c5509c30fceb73
thread read through 2026-10-26 (148 statements), head dc230de70c
labels: Windows, Build system

Categories

Build and CI

P2 · platform fix

Switches native Windows builds to clang-cl, eliminating MSVC-specific compiler bugs and yielding major build and codegen speedups. The author reports a 38% reduction in Windows CI build times (from 20m 35s to 12m 43s), closes compiler bug issues #31456 and #36153, and measures block connection throughput improvements of ~55–60% over MSVC codegen.

Membership: Labeled 'Build system' and 'Windows'; switches native Windows builds and CI from cl.exe to clang-cl across CMake configurations and GitHub Actions workflows.

Factors: security/stability 1, bug 0, performance 2, user value 1, leverage 1