Skip to content

Add hybrid CRT link for Windows binaries - #40890

Merged
JohnMcPMS merged 4 commits into
microsoft:masterfrom
JohnMcPMS:hybrid-static
Aug 24, 2026
Merged

JohnMcPMS merged 4 commits into
microsoft:masterfrom
JohnMcPMS:hybrid-static

Conversation

@JohnMcPMS

Copy link
Copy Markdown
Member

Summary of the Pull Request

Configures hybrid static linkage for Windows binaries in the build. See https://aka.ms/hybridcrt for details on this model.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

The Windows binaries are all already statically linking the runtime. Switching to the hybrid model will cut non-trivial size from every binary, without adding any new dependency requirements.

I also understand if we want to wait on taking this until after a significant release so it may have more time to stabilize.

Validation Steps Performed

Built debug locally, ran an arbitrary test.

@JohnMcPMS
JohnMcPMS requested a review from a team as a code owner June 24, 2026 18:40
Copilot AI review requested due to automatic review settings June 24, 2026 18:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the top-level CMake configuration to adopt the “hybrid CRT” linking model for Windows binaries: keep /MT (static C++ runtime/STL) while forcing the Universal CRT to be dynamically linked (ucrt.dll) via linker default-lib overrides.

Changes:

  • Adds linker flags to suppress libucrt(.lib|d.lib) and explicitly link against ucrt(.lib|d.lib) in Release/Debug builds.
  • Documents the hybrid CRT intent and links to the reference guidance.

Comment thread CMakeLists.txt Resolved

@OneBlue Blue (OneBlue) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this is a great change, and we should definitely merge it.

Agreed that we should wait after the initial release though. One thing that we should validate before merging this is whether this causes us any issues on WS 2022 (specifically on the ServerCore SKU), since we've had runtime dependencies issues in this SKU in the past.

If this runs without issues on WS 2022 ServerCore, I think we should merge it (after the 2.9 release).

Blocking for now, but will unblock after 2.9 is out.

@JohnMcPMS

Copy link
Copy Markdown
Member Author

There is certainly a reduction in size when compared to another build from the same time, but it isn't as much as I would have hoped for.

Comment thread CMakeLists.txt Outdated
# but dynamic-link the Universal CRT (ucrt.dll) which is an OS component on Windows 10+.
# This eliminates the VCRUNTIME/MSVCP redistributable dependency while avoiding the size
# cost of statically linking the UCRT. See https://aka.ms/hybridcrt for details.
foreach(config RELEASE RELWITHDEBINFO MINSIZEREL)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: We don't support RELWITHDEBINFO and MINSIZEREL, so we can probably remove the loop here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Actually we can probably just write to CMAKE_SHARED_LINKER_FLAGS and CMAKE_EXE_LINKER_FLAGS here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also, should we apply this to STATIC_LIBRARY_FLAGS as well ?

@OneBlue
Blue (OneBlue) dismissed their stale review July 9, 2026 19:00

Dismissing review since 2.9.3 has shipped

Copilot AI review requested due to automatic review settings July 31, 2026 17:42
@JohnMcPMS
JohnMcPMS requested a review from a team as a code owner July 31, 2026 17:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (1)

CMakeLists.txt:340

  • CMAKE_STATIC_LINKER_FLAGS_* configures the librarian for .lib creation (lib.exe), not the linker for producing DLL/EXE outputs. /NODEFAULTLIB and /DEFAULTLIB are link.exe options, so applying them via CMAKE_STATIC_LINKER_FLAGS_* is at best ignored and at worst can break static library builds. These flags should only be applied to EXE/SHARED link steps.
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libucrt.lib /defaultlib:ucrt.lib")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG   "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}   /NODEFAULTLIB:libucrtd.lib /defaultlib:ucrtd.lib")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG      "${CMAKE_EXE_LINKER_FLAGS_DEBUG}      /NODEFAULTLIB:libucrtd.lib /defaultlib:ucrtd.lib")
set(CMAKE_STATIC_LINKER_FLAGS_DEBUG   "${CMAKE_STATIC_LINKER_FLAGS_DEBUG}   /NODEFAULTLIB:libucrtd.lib /defaultlib:ucrtd.lib")

Copilot AI review requested due to automatic review settings July 31, 2026 17:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (1)

CMakeLists.txt:338

  • These linker flags are MSVC-specific (/NODEFAULTLIB, /DEFAULTLIB). As written they are set unconditionally, which can break configuring this CMake project with a non-MSVC toolchain (or any future non-Windows build). Also, the comment claims it “eliminates the VCRUNTIME/MSVCP redistributable dependency”, but the project already sets CMAKE_MSVC_RUNTIME_LIBRARY to /MT|/MTd (MultiThreaded*), so the main value here is the binary size reduction from dynamically linking the UCRT.
# Hybrid CRT: static-link the C++ runtime and STL (/MT|/MTd from CMAKE_MSVC_RUNTIME_LIBRARY),
# but dynamic-link the Universal CRT (ucrt.dll) which is an OS component on Windows 10+.
# This eliminates the VCRUNTIME/MSVCP redistributable dependency while avoiding the size
# cost of statically linking the UCRT. See https://aka.ms/hybridcrt for details.
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /NODEFAULTLIB:libucrt.lib /defaultlib:ucrt.lib")

@OneBlue Blue (OneBlue) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, please make sure that this runs on the ServerCore SKU of Windows Server 2019 before merging.

Just validating that a simple container starts should be sufficient

@JohnMcPMS

Copy link
Copy Markdown
Member Author

LGTM, please make sure that this runs on the ServerCore SKU of Windows Server 2019 before merging.

Just validating that a simple container starts should be sufficient

Validated both install and image pull on Windows ServerCore 2022.

@JohnMcPMS
JohnMcPMS merged commit 4e41274 into microsoft:master Aug 24, 2026
9 checks passed
@JohnMcPMS
JohnMcPMS deleted the hybrid-static branch August 24, 2026 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants