From e97c5a68f17d901dfcdfc1ac45d73ecc1a5a7e00 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 29 Nov 2025 23:35:31 -0800 Subject: [PATCH 1/4] CMakeLists.txt: We don't need to define `_VCRT_WIN32_WINNT`. Internally, only src/vctools/crt/vcruntime/src/internal/winapi_downlevel.cpp src/vctools/crt/vcstartup/src/utility/initializers.cpp inspect this, and they aren't headers. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d6289e713e6..8ae94074023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,22 +61,22 @@ if("${VCLIBS_TARGET_ARCHITECTURE}" STREQUAL "x86") # Note that we set _WIN32_WINNT to a high level to make declarations available, but still engage downlevel # runtime dynamic linking by setting our own _STL_WIN32_WINNT back to Windows XP. - add_compile_definitions(_X86_ _VCRT_WIN32_WINNT=0x0501 _STL_WIN32_WINNT=0x0501) + add_compile_definitions(_X86_ _STL_WIN32_WINNT=0x0501) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "x64") set(VCLIBS_TARGET_ARCHITECTURE "x64") set(VCLIBS_I386_OR_AMD64 "amd64") set(VCLIBS_X86_OR_X64 "x64") - add_compile_definitions(_AMD64_ _VCRT_WIN32_WINNT=0x0501 _STL_WIN32_WINNT=0x0501) + add_compile_definitions(_AMD64_ _STL_WIN32_WINNT=0x0501) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64") set(VCLIBS_TARGET_ARCHITECTURE "arm64") set(VCLIBS_I386_OR_AMD64 "arm64") set(VCLIBS_X86_OR_X64 "arm64") - add_compile_definitions(_ARM64_ _VCRT_WIN32_WINNT=0x0A00 _STL_WIN32_WINNT=0x0A00) + add_compile_definitions(_ARM64_ _STL_WIN32_WINNT=0x0A00) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64ec") set(VCLIBS_TARGET_ARCHITECTURE "arm64ec") set(VCLIBS_I386_OR_AMD64 "arm64ec") set(VCLIBS_X86_OR_X64 "arm64") # Yes, really: `%VCToolsInstallDir%lib\arm64ec` only contains the Link Options - add_compile_definitions(_AMD64_ _ARM64EC_ _VCRT_WIN32_WINNT=0x0501 _STL_WIN32_WINNT=0x0501) + add_compile_definitions(_AMD64_ _ARM64EC_ _STL_WIN32_WINNT=0x0501) add_compile_options($<$:/arm64EC>) set(VCLIBS_EXPLICIT_MACHINE "/machine:arm64ec") else() From ab2c85f73050314a90409619b4a789cbff24f3ee Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 29 Nov 2025 23:37:28 -0800 Subject: [PATCH 2/4] Include Windows.h instead of synchapi.h, don't define weird platform macros in CMakeLists.txt. We never inspect `_X86_`, `_AMD64_`, `_ARM64_`, or `_ARM64EC_` ourselves. They're needed if we directly include synchapi.h, but not if we include Windows.h (which defines them). [`AcquireSRWLockExclusive`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-acquiresrwlockexclusive) and [`InitOnceBeginInitialize`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initoncebegininitialize) say "Header: synchapi.h (include Windows.h on Windows 7, Windows Server 2008 Windows Server 2008 R2)". --- CMakeLists.txt | 8 ++++---- stl/src/atomic.cpp | 2 +- stl/src/sharedmutex.cpp | 3 ++- stl/src/xonce2.cpp | 3 ++- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ae94074023..73faa12c5f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,22 +61,22 @@ if("${VCLIBS_TARGET_ARCHITECTURE}" STREQUAL "x86") # Note that we set _WIN32_WINNT to a high level to make declarations available, but still engage downlevel # runtime dynamic linking by setting our own _STL_WIN32_WINNT back to Windows XP. - add_compile_definitions(_X86_ _STL_WIN32_WINNT=0x0501) + add_compile_definitions(_STL_WIN32_WINNT=0x0501) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "x64") set(VCLIBS_TARGET_ARCHITECTURE "x64") set(VCLIBS_I386_OR_AMD64 "amd64") set(VCLIBS_X86_OR_X64 "x64") - add_compile_definitions(_AMD64_ _STL_WIN32_WINNT=0x0501) + add_compile_definitions(_STL_WIN32_WINNT=0x0501) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64") set(VCLIBS_TARGET_ARCHITECTURE "arm64") set(VCLIBS_I386_OR_AMD64 "arm64") set(VCLIBS_X86_OR_X64 "arm64") - add_compile_definitions(_ARM64_ _STL_WIN32_WINNT=0x0A00) + add_compile_definitions(_STL_WIN32_WINNT=0x0A00) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64ec") set(VCLIBS_TARGET_ARCHITECTURE "arm64ec") set(VCLIBS_I386_OR_AMD64 "arm64ec") set(VCLIBS_X86_OR_X64 "arm64") # Yes, really: `%VCToolsInstallDir%lib\arm64ec` only contains the Link Options - add_compile_definitions(_AMD64_ _ARM64EC_ _STL_WIN32_WINNT=0x0501) + add_compile_definitions(_STL_WIN32_WINNT=0x0501) add_compile_options($<$:/arm64EC>) set(VCLIBS_EXPLICIT_MACHINE "/machine:arm64ec") else() diff --git a/stl/src/atomic.cpp b/stl/src/atomic.cpp index 367defd27b9..0aab1685960 100644 --- a/stl/src/atomic.cpp +++ b/stl/src/atomic.cpp @@ -5,7 +5,7 @@ #include -#include +#include namespace { SRWLOCK _Shared_ptr_lock = SRWLOCK_INIT; diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index fac73f1e388..5b2f262cd8a 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include <__msvc_threads_core.hpp> -#include + +#include #include "primitives.hpp" diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 70866190367..0e3968f57dd 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -4,7 +4,8 @@ #include #include -#include + +#include // Provides forwarders for InitOnceBeginInitialize and InitOnceComplete for // environments that can't use /ALTERNATENAME. From b3b6c6b92c434f4960212e44a6041ecd00e56fef Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 30 Nov 2025 00:43:57 -0800 Subject: [PATCH 3/4] Simplify away _STL_WIN32_WINNT machinery. [Need internal changes.] src/vctools/crt/crt-common.settings.targets has dead code mentioning CrtOsVersion. It defines _STL_WIN32_WINNT according to the following criteria: * TargetEnclave is never set for the STL, so we can ignore it. * For ARM64 (not ARM64EC, which is treated like x64), it uses 0x0A00, the Win10 value. * Otherwise, for TargetAppFamily (indicated by _CRT_APP defined by src/vctools/crt/crt_build.settings.targets) or for TargetCoreSystem (indicated by _CRT_ONECORE defined by src/vctools/crt/crt_build.settings.targets, but we inspect _ONECORE defined by src/vctools/VCTools.props), it uses 0x0602, the Win8 value. * Otherwise, it uses 0x0501, the WinXP value. We only ever compare _STL_WIN32_WINNT with " < Vista" and " < Win8". Therefore, the distinction between ARM64's Win10 value and _CRT_APP/_ONECORE's Win8 value is not significant; both are "new", and otherwise we are "old". So, we can use `#if !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE))` to guard old bincompat code. src/vctools/crt/vcstartup/build/msvcrt.settings.targets defines _STL_WIN32_WINNT but shouldn't. Validated this by adding the following block to winapisupp.cpp before removing the legacy scheme; x64 and arm64 successfully built internally: #if defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE) static_assert(!(_STL_WIN32_WINNT < _WIN32_WINNT_VISTA), "Modern scheme says we're new, but legacy scheme disagrees."); static_assert(!(_STL_WIN32_WINNT < _WIN32_WINNT_WIN8), "Modern scheme says we're new, but legacy scheme disagrees."); #else // ^^^ new, according to modern scheme / old, according to modern scheme vvv static_assert(_STL_WIN32_WINNT < _WIN32_WINNT_VISTA, "Modern scheme says we're old, but legacy scheme disagrees."); static_assert(_STL_WIN32_WINNT < _WIN32_WINNT_WIN8, "Modern scheme says we're old, but legacy scheme disagrees."); #endif // ^^^ old, according to modern scheme ^^^ Verified that the dllexports are unchanged for x64 and arm64. --- CMakeLists.txt | 8 +------- stl/inc/yvals_core.h | 9 +-------- stl/src/winapinls.cpp | 6 ++---- stl/src/winapisupp.cpp | 7 ++----- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73faa12c5f7..e9af9b3a4fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,25 +58,18 @@ if("${VCLIBS_TARGET_ARCHITECTURE}" STREQUAL "x86") set(VCLIBS_TARGET_ARCHITECTURE "x86") set(VCLIBS_I386_OR_AMD64 "i386") set(VCLIBS_X86_OR_X64 "x86") - - # Note that we set _WIN32_WINNT to a high level to make declarations available, but still engage downlevel - # runtime dynamic linking by setting our own _STL_WIN32_WINNT back to Windows XP. - add_compile_definitions(_STL_WIN32_WINNT=0x0501) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "x64") set(VCLIBS_TARGET_ARCHITECTURE "x64") set(VCLIBS_I386_OR_AMD64 "amd64") set(VCLIBS_X86_OR_X64 "x64") - add_compile_definitions(_STL_WIN32_WINNT=0x0501) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64") set(VCLIBS_TARGET_ARCHITECTURE "arm64") set(VCLIBS_I386_OR_AMD64 "arm64") set(VCLIBS_X86_OR_X64 "arm64") - add_compile_definitions(_STL_WIN32_WINNT=0x0A00) elseif(VCLIBS_TARGET_ARCHITECTURE STREQUAL "arm64ec") set(VCLIBS_TARGET_ARCHITECTURE "arm64ec") set(VCLIBS_I386_OR_AMD64 "arm64ec") set(VCLIBS_X86_OR_X64 "arm64") # Yes, really: `%VCToolsInstallDir%lib\arm64ec` only contains the Link Options - add_compile_definitions(_STL_WIN32_WINNT=0x0501) add_compile_options($<$:/arm64EC>) set(VCLIBS_EXPLICIT_MACHINE "/machine:arm64ec") else() @@ -92,6 +85,7 @@ set(STL_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out/lib/${VCLIBS_I386_OR set(STL_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out/lib/${VCLIBS_I386_OR_AMD64}") set(STL_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out/bin/${VCLIBS_I386_OR_AMD64}") +# Note that we set _WIN32_WINNT to a high level to make declarations available. add_compile_definitions( _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH WIN32_LEAN_AND_MEAN STRICT _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS _WIN32_WINNT=0x0A00 NTDDI_VERSION=NTDDI_WIN11_GE) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 5f9a98b1f8c..9cfc910eea6 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1955,14 +1955,7 @@ _EMIT_STL_ERROR(STL1013, "The STL doesn't support /RTCc because it rejects confo #error In yvals_core.h, defined(MRTDLL) implies defined(_M_CEE_PURE); !defined(_M_CEE_PURE) implies !defined(MRTDLL) #endif // defined(MRTDLL) && !defined(_M_CEE_PURE) -#define _STL_WIN32_WINNT_VISTA 0x0600 // _WIN32_WINNT_VISTA from sdkddkver.h -#define _STL_WIN32_WINNT_WIN10 0x0A00 // _WIN32_WINNT_WIN10 from sdkddkver.h - -// Note that the STL DLL builds will set this to XP for ABI compatibility with VS2015 which supported XP. -#ifndef _STL_WIN32_WINNT -// The earliest Windows supported by this implementation is Windows 10 -#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN10 -#endif // !defined(_STL_WIN32_WINNT) +// The earliest Windows supported by this implementation is Windows 10. #ifdef __cpp_noexcept_function_type #define _NOEXCEPT_FNPTR noexcept diff --git a/stl/src/winapinls.cpp b/stl/src/winapinls.cpp index e118cf604ce..b3c90890891 100644 --- a/stl/src/winapinls.cpp +++ b/stl/src/winapinls.cpp @@ -1,9 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include - -#if _STL_WIN32_WINNT < _STL_WIN32_WINNT_VISTA +#if !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE)) #include @@ -29,4 +27,4 @@ extern "C" _CRTIMP2 int __cdecl __crtGetLocaleInfoEx(_In_opt_ LPCWSTR const lpLo return GetLocaleInfoEx(lpLocaleName, LCType, lpLCData, cchData); } -#endif // _STL_WIN32_WINNT < _STL_WIN32_WINNT_VISTA +#endif // ^^^ !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE)) ^^^ diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index de6f6ae4d29..1d190af598c 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -35,7 +35,7 @@ extern "C" _CRTIMP2 BOOL __cdecl __crtIsPackagedApp() noexcept { #endif // !defined(_CRT_WINDOWS) && !defined(UNDOCKED_WINDOWS_UCRT) -#if _STL_WIN32_WINNT < _WIN32_WINNT_VISTA +#if !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE)) // TRANSITION, ABI: preserved for binary compatibility extern "C" _CRTIMP2 ULONGLONG __cdecl __crtGetTickCount64() noexcept { @@ -150,16 +150,13 @@ extern "C" _CRTIMP2 BOOL __cdecl __crtSetFileInformationByHandle(_In_ HANDLE con _In_reads_bytes_(dwBufferSize) LPVOID const lpFileInformation, _In_ DWORD const dwBufferSize) noexcept { return SetFileInformationByHandle(hFile, FileInformationClass, lpFileInformation, dwBufferSize); } -#endif // _STL_WIN32_WINNT < _WIN32_WINNT_VISTA - -#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 // TRANSITION, ABI: preserved for binary compatibility extern "C" _CRTIMP2 void __cdecl __crtGetSystemTimePreciseAsFileTime(_Out_ LPFILETIME lpSystemTimeAsFileTime) noexcept { GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime); } -#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 +#endif // ^^^ !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE)) ^^^ extern "C" _Success_(return > 0 && return < BufferLength) DWORD __stdcall __crtGetTempPath2W( _In_ DWORD BufferLength, _Out_writes_to_opt_(BufferLength, return +1) LPWSTR Buffer) noexcept { From c5773b3df7dd00d378abdeaae28f1687fe9b94ee Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 1 Dec 2025 03:35:21 -0800 Subject: [PATCH 4/4] Comment why ARM64, App, and OneCore are special. --- stl/src/winapinls.cpp | 4 ++++ stl/src/winapisupp.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/stl/src/winapinls.cpp b/stl/src/winapinls.cpp index b3c90890891..9d8227c2855 100644 --- a/stl/src/winapinls.cpp +++ b/stl/src/winapinls.cpp @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// Previously, x64/x86 Desktop builds had to support targeting old versions of Windows, so we dllexported functions to +// dynamically load new Windows APIs. Now, we directly call those Windows APIs, and the dllexported functions have +// become simple wrappers, but they still need to be preserved for binary compatibility. The ARM64, App, and OneCore +// builds never supported targeting old versions of Windows, so they never provided these dllexported functions. #if !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE)) #include diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index 1d190af598c..fa6b46c53aa 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -35,6 +35,10 @@ extern "C" _CRTIMP2 BOOL __cdecl __crtIsPackagedApp() noexcept { #endif // !defined(_CRT_WINDOWS) && !defined(UNDOCKED_WINDOWS_UCRT) +// Previously, x64/x86 Desktop builds had to support targeting old versions of Windows, so we dllexported functions to +// dynamically load new Windows APIs. Now, we directly call those Windows APIs, and the dllexported functions have +// become simple wrappers, but they still need to be preserved for binary compatibility. The ARM64, App, and OneCore +// builds never supported targeting old versions of Windows, so they never provided these dllexported functions. #if !(defined(_M_ARM64) || defined(_CRT_APP) || defined(_ONECORE)) // TRANSITION, ABI: preserved for binary compatibility