Setting the MSVC runtime in CMake

匿名 (未验证) 提交于 2019-12-03 09:13:36

问题:

I'm following the instructions in the CMake FAQ entry "How can I build my MSVC application with a static runtime?" to centralize selection of the MSVC runtime for a bunch of nested CMake projects (they are pulled in as Git submodules and added to the master project using CMake's find_package() directive).

So, I wrote this CMake macro:

macro(configure_msvc_runtime)   if(MSVC)     # Default to statically-linked runtime.     if("${MSVC_RUNTIME}" STREQUAL "")       set(MSVC_RUNTIME "static")     endif()     # Set compiler options.     set(variables       CMAKE_C_FLAGS_DEBUG       CMAKE_C_FLAGS_MINSIZEREL       CMAKE_C_FLAGS_RELEASE       CMAKE_C_FLAGS_RELWITHDEBINFO       CMAKE_CXX_FLAGS_DEBUG       CMAKE_CXX_FLAGS_MINSIZEREL       CMAKE_CXX_FLAGS_RELEASE       CMAKE_CXX_FLAGS_RELWITHDEBINFO     )     if(${MSVC_RUNTIME} STREQUAL "static")       message(STATUS         "MSVC -> forcing use of statically-linked runtime."       )       foreach(variable ${variables})         if(${variable} MATCHES "/MD")           string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}")         endif()       endforeach()     else()       message(STATUS         "MSVC -> forcing use of dynamically-linked runtime."       )       foreach(variable ${variables})         if(${variable} MATCHES "/MT")           string(REGEX REPLACE "/MT" "/MD" ${variable} "${${variable}}")         endif()       endforeach()     endif()   endif() endmacro() 

I call this macro at the beginning of my root CMakeLists.txt (before any add_library() or add_executable() call is made) and add a little bit of debugging prints:

configure_msvc_runtime() set(variables   CMAKE_C_FLAGS_DEBUG   CMAKE_C_FLAGS_MINSIZEREL   CMAKE_C_FLAGS_RELEASE   CMAKE_C_FLAGS_RELWITHDEBINFO   CMAKE_CXX_FLAGS_DEBUG   CMAKE_CXX_FLAGS_MINSIZEREL   CMAKE_CXX_FLAGS_RELEASE   CMAKE_CXX_FLAGS_RELWITHDEBINFO ) message(STATUS "Initial build flags:") foreach(variable ${variables})   message(STATUS "  '${variable}': ${${variable}}") endforeach() message(STATUS "") 

Then, I run CMake to generate a Visual Studio solution like so:

cmake -G "Visual Studio 9 2008" ..\.. -DMSVC_RUNTIME=dynamic 

and I get the following outputs:

-- MSVC -> forcing use of dynamically-linked runtime. -- Initial build flags: --   'CMAKE_C_FLAGS_DEBUG': /D_DEBUG /MDd /Zi  /Ob0 /Od /RTC1 --   'CMAKE_C_FLAGS_MINSIZEREL': /MD /O1 /Ob1 /D NDEBUG --   'CMAKE_C_FLAGS_RELEASE': /MD /O2 /Ob2 /D NDEBUG --   'CMAKE_C_FLAGS_RELWITHDEBINFO': /MD /Zi /O2 /Ob1 /D NDEBUG --   'CMAKE_CXX_FLAGS_DEBUG': /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1 --   'CMAKE_CXX_FLAGS_MINSIZEREL': /MD /O1 /Ob1 /D NDEBUG --   'CMAKE_CXX_FLAGS_RELEASE': /MD /O2 /Ob2 /D NDEBUG --   'CMAKE_CXX_FLAGS_RELWITHDEBINFO': /MD /Zi /O2 /Ob1 /D NDEBUG 

Now, the thing is that when I start Visual Studio and examine the project properties under "C/C++, Code Generation", I see that the "Runtime Library" setting is not consistent with the options printed in the shell. Under the "Release", "MinSizeRel" and "RelWithDebInfo" configurations, I get the expected results ("Multi-threaded DLL /MD", but the "Debug" configuration still displays "Multi-threaded /MT".

Also, when I force use of the statically-linked runtime, I get similar results. If I run

cmake -G "Visual Studio 9 2008" ..\.. -DMSVC_RUNTIME=static 

I get the following outputs:

-- MSVC -> forcing use of statically-linked runtime. -- Initial build flags: --   'CMAKE_C_FLAGS_DEBUG': /D_DEBUG /MTd /Zi  /Ob0 /Od /RTC1 --   'CMAKE_C_FLAGS_MINSIZEREL': /MT /O1 /Ob1 /D NDEBUG --   'CMAKE_C_FLAGS_RELEASE': /MT /O2 /Ob2 /D NDEBUG --   'CMAKE_C_FLAGS_RELWITHDEBINFO': /MT /Zi /O2 /Ob1 /D NDEBUG --   'CMAKE_CXX_FLAGS_DEBUG': /D_DEBUG /MTd /Zi /Ob0 /Od /RTC1 --   'CMAKE_CXX_FLAGS_MINSIZEREL': /MT /O1 /Ob1 /D NDEBUG --   'CMAKE_CXX_FLAGS_RELEASE': /MT /O2 /Ob2 /D NDEBUG --   'CMAKE_CXX_FLAGS_RELWITHDEBINFO': /MT /Zi /O2 /Ob1 /D NDEBUG 

And yet all configurations produce the "Multi-threaded /MT" value for the "Runtime Library" setting.

Can someone tell me what I'm doing wrong, or if this is a bug in CMake (2.8.7) or something ?


For what it's worth, If I generate Visual Studio 2010 project files, I get a different value for the "Debug" configuration, but still not the one I selected. In all cases, the setting appears in regular font for the "Debug" configuration whereas it appears in bolded font for the other configurations, hinting that those are overrides. Moreover, if I open the XML project files, I find that the "Debug" configuration has no setting for the "RuntimeLibrary" attribute of the "Tool" element with the "Name=VCCLCompilerTool" attribute. All other configurations have an explicit setting.

回答1:

It seems all the while I was working on this, I forgot to remove the bad CMake configuration I'm trying to replace.

Further down the build script, I had left this little bugger:

set(CMAKE_CXX_FLAGS_DEBUG   "/DWIN32 /D_WINDOWS /EHsc /WX /wd4355 /wd4251 /wd4250 /wd4996"   CACHE STRING "Debug compiler flags" FORCE ) 

Basically, I was overriding the results of by configure_msvc_runtime() macro with build flags that did not set the MSVC runtime.

Sorry for the trouble!



回答2:

I took your code and generalized it to work for every existing configuration and not just for Debug/Release/RelWithDebInfo/MinSizeRel.

Also I made it to work with gcc too - check it out here



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!