6

I'm building a file using the CMake Build System and Microsoft's Visual C++ compiler. When I have CMake generate the visual studio project, the project contains the commandline to build a "Multi Threaded DLL" type of runtime -- one which depends on msvcrt.dll. For various reasons I'm not going into right now, I cannot depend on msvcrt.

Is there a way to tell CMake to modify this option in it's construction process?

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552

2 Answers2

12

I use the following piece of code to link to the static CRT:

if(MSVC)
# We statically link to reduce dependencies
foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
    if(${flag_var} MATCHES "/MD")
        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
    endif(${flag_var} MATCHES "/MD")
    if(${flag_var} MATCHES "/MDd")
        string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
    endif(${flag_var} MATCHES "/MDd")
endforeach(flag_var)
endif(MSVC)
0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
SteveL
  • 1,811
  • 1
  • 13
  • 23
  • 3
    This is overkill isn't it? Wouldn't "foreach() string(replace, /md, /mt) endforeach()" work just as well? (i.e. get rid of the if() and the /MDd). The first replace will match the second one anyway, and there is no point searching for a match before you just do the replacement. – brofield Mar 27 '10 at 23:25
  • Works for me, inside the foreach(flag_var...): `string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")` – Graham Perks Jul 27 '11 at 20:09
  • 1
    The options for doing this are documented under "How can I build my MSVC application with a static runtime" at http://www.cmake.org/Wiki/CMake_FAQ#Out-of-source_build_trees – javacavaj Sep 04 '14 at 20:03
  • 1
    More correct link to official documentation how to build with MSVC with static link to CRT: http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F – Sergey May 27 '15 at 16:00
  • I had some trouble implementing this. No matter where I had put this, the resulting projects ended up still using /MD or /MDd. I eventually realized that the /MD or /MT flag was never being set at all, and it was defaulting to /MD. Adding an else ... string(CONCAT ...) part to the code fixed my issue. – LRFLEW Oct 14 '16 at 23:31
2

I replace the dynamic flags (/MD and /MDd) with static flags (/MT and /MTd). Also, I found that I needed to cache the flag variables in order for it to stick.

if(MSVC)
    foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO) 
        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
        string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
    endforeach(flag_var)
    SET (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "MSVC C Debug MT flags " FORCE)    
    SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "MSVC CXX Debug MT flags " FORCE)
    SET (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "MSVC C Release MT flags " FORCE)
    SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "MSVC CXX Release MT flags " FORCE)
    SET (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}" CACHE STRING "MSVC C Debug MT flags " FORCE)    
    SET (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}" CACHE STRING "MSVC C Release MT flags " FORCE)
    SET (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}" CACHE STRING "MSVC CXX Debug MT flags " FORCE)    
    SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "MSVC CXX Release MT flags " FORCE)
endif()
papahabla
  • 1,448
  • 18
  • 18