Jens Geyer created THRIFT-6312:
----------------------------------

             Summary: WITH_MT does not select the static runtime any more
                 Key: THRIFT-6312
                 URL: https://issues.apache.org/jira/browse/THRIFT-6312
             Project: Thrift
          Issue Type: Bug
          Components: Build Process
            Reporter: Jens Geyer
             Fix For: 0.26.0


h2. Symptom

A compiler built with {{-DWITH_MT=ON}} - which is how 
{{build/docker/msvc/build-compiler.bat}} and the manual instructions in 
{{doc/ReleaseManagement.md}} build the Windows compiler that ships with a 
release - imports the shared C and C++ runtime:

{noformat}
KERNEL32.dll
ole32.dll
MSVCP140.dll
VCRUNTIME140.dll
VCRUNTIME140_1.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
{noformat}

{{doc/ReleaseManagement.md}} requires the released executable to depend on 
{{kernel32.dll}} only, so that it runs on a machine with no Visual C++ 
redistributable installed. The whole point of {{WITH_MT}} is to produce that.

Observed on a {{windows-2025}} GitHub runner, CMake 3.31.6 with Visual Studio 
2022. The container that builds the release compiler installs CMake 4.1.2.

h2. Cause

{{build/cmake/DefinePlatformSpecifc.cmake}} implements {{WITH_MT}} by rewriting 
the compiler flag variables:

{code}
foreach(CompilerFlag ${CompilerFlags})
  string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
endforeach()
{code}

Policy [CMP0091|https://cmake.org/cmake/help/latest/policy/CMP0091.html] took 
the MSVC runtime selection out of the per configuration compiler flag variables 
({{CMAKE_CXX_FLAGS_RELEASE}} and its siblings, which is exactly the list the 
loop above walks) and moved it to the {{MSVC_RUNTIME_LIBRARY}} target property, 
which the {{CMAKE_MSVC_RUNTIME_LIBRARY}} variable initialises. That policy is 
NEW whenever a project requires CMake 3.15 or newer, and the top level 
{{CMakeLists.txt}} requires 3.16.

So there is no {{/MD}} left in those variables, the replacement matches 
nothing, and {{WITH_MT}} does nothing at all. Neither {{CMP0091}} nor 
{{CMAKE_MSVC_RUNTIME_LIBRARY}} appears anywhere in the tree.

It fails silently. The build succeeds, the configure summary still prints 
{{Using static runtime library: ON}}, and the libraries are still named 
{{thriftmt}} - the name promises a static runtime the binaries do not have.

h2. Fix

Set {{CMAKE_MSVC_RUNTIME_LIBRARY}} to {{MultiThreaded$<$<CONFIG:Debug>:Debug>}} 
when {{WITH_MT}} is on, before any target is created. The flag rewriting stays, 
because it is what still applies to a build that sets {{CMP0091}} to OLD.

h2. Unrelated, but in the same list

{{ole32.dll}} is expected and is not a redistributable: it is a Windows system 
DLL present on every Windows installation, pulled in by the {{CoCreateGuid}} 
call in {{compiler/cpp/src/thrift/generate/t_delphi_generator.cc}}. The "only 
depends on kernel32.dll" wording in {{doc/ReleaseManagement.md}} predates that 
call.

_Drafted with AI assistance (Claude Opus 5); reviewed and posted by Jens Geyer._




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to