在CMake中设置MSVC运行时

tzdcorbm  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(274)

我按照CMake常见问题解答条目“如何使用静态运行时构建MSVC应用程序?”中的说明,为一堆嵌套的CMake项目集中选择MSVC运行时(它们作为Git子模块被拉入,并使用CMake的find_package()指令添加到主项目中)。
所以,我写了这个CMake宏:

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()

我在根CMakeLists.txt的开头调用这个宏(在 anyadd_library()add_executable()调用之前),并添加一些调试打印:

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 "")

然后,我运行CMake生成一个Visual Studio解决方案,如下所示:

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

我得到了以下输出:

-- 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

现在,问题是,当我启动Visual Studio并检查“C/C++,代码生成”下的项目属性时,我看到“运行时库”设置与shell中打印的选项不一致。在“Release”、“MinSizeRel”和“RelWithDebInfo”配置下,我得到了预期的结果(“多线程DLL /MD”,但“调试”配置仍显示“多线程/MT”)。
此外,当我强制使用静态链接运行时,我得到了类似的结果。

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

我得到以下输出:

-- 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

然而,所有配置都会为“运行时库”设置生成“多线程/MT”值。
我做错了什么,或者这是CMake(2.8.7)中的一个bug还是什么?
值得注意的是,如果我生成Visual Studio 2010项目文件,我会得到一个不同的“调试”配置值,但仍然不是我选择的值。
在所有情况下,“Debug”配置中的设置都以常规字体显示,而其他配置中的设置则以粗体显示,这暗示这些配置是重写。此外,如果打开XML项目文件,我发现“Debug”配置中没有对具有“Name=VCCLCompilerTool”属性的“Tool”元素的“RuntimeLibrary”属性进行设置。所有其他配置都有显式设置。

cwxwcias

cwxwcias1#

似乎在我做这个的时候,我忘记删除我试图替换的坏的CMake配置。
在构建脚本的后面,我留下了这个小家伙:

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

基本上,我是用构建标志覆盖configure_msvc_runtime()宏的结果,这些标志没有设置MSVC运行时。

e7arh2l6

e7arh2l62#

此功能将在cmake-3.15发行版中得到改进。

这应该是一个设置CMAKE_MSVC_RUNTIME_LIBRARY的问题,例如(来自docs)设置“多线程静态链接运行时库,根据配置有或没有调试信息”:

set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
j8ag8udp

j8ag8udp3#

这是我提出的一个解决方案,它应该适用于CMake 3.15之前和之后的版本。


# This logic needs to be considered before project()

set(_change_MSVC_flags FALSE)
if(WIN32)
  if(CMAKE_VERSION VERSION_LESS 3.15.0)
    set(_change_MSVC_flags TRUE)
  else()
    # Set MSVC runtime to MultiThreaded (/MT)
    cmake_policy(SET CMP0091 NEW)
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
  endif()
endif()

project(MyProj ....)

if(_change_MSVC_flags)
  # Modify compile flags to change MSVC runtime from /MD to /MT
  set(_re_match "([\\/\\-]M)D")
  set(_re_replace "\\1T")
  string(REGEX REPLACE ${_re_match} ${_re_replace}
    CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  string(REGEX REPLACE ${_re_match} ${_re_replace}
    CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
  string(REGEX REPLACE ${_re_match} ${_re_replace}
    CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
  string(REGEX REPLACE ${_re_match} ${_re_replace}
    CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
  string(REGEX REPLACE ${_re_match} ${_re_replace}
    CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
endif()

如果使用其他语言(即C),则也需要添加这些语言。

yeotifhr

yeotifhr4#

我使用了您的代码,并将其推广为适用于所有现有配置,而不仅仅是Debug/Release/RelWithDebInfo/MinSizeRel。
我也做了它的工作与gcc太-检查它在这里

相关问题