【问题标题】:Setting the MSVC runtime in CMake在 CMake 中设置 MSVC 运行时
【发布时间】:2012-04-24 04:13:15
【问题描述】:

我按照 CMake 常见问题解答条目 "How can I build my MSVC application with a static runtime?" 中的说明为一堆嵌套 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 的开头调用这个宏(在 any add_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”配置下,我得到了预期的结果(“Multi-threaded DLL /MD”,但“Debug”配置仍然显示“Multi-threaded /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) 中的错误还是什么?


不管怎样,如果我生成 Visual Studio 2010 项目文件,我会得到一个不同的“调试”配置值,但仍然不是我选择的那个。

在所有情况下,“调试”配置的设置以常规字体显示,而其他配置以粗体显示,暗示这些是覆盖。此外,如果我打开 XML 项目文件,我发现“Debug”配置没有设置“Tool”元素的“RuntimeLibrary”属性,“Name=VCCLCompilerTool”属性。所有其他配置都有明确的设置。

【问题讨论】:

    标签: visual-studio cmake


    【解决方案1】:

    似乎我一直在处理这个问题,但我忘了删除我要替换的错误 CMake 配置。

    在构建脚本的下方,我留下了这个小虫子:

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

    基本上,我使用未设置 MSVC 运行时的构建标志覆盖了 configure_msvc_runtime() 宏的结果。

    【讨论】:

    • 你用你的强制静态运行时库的解决方案真的救了我!
    【解决方案2】:

    此功能将随着 cmake-3.15 的发布而得到改进。

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

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

    【讨论】:

    • 不确定!我有 cmake 版本 3.17.3!而且你描述的方法不行!
    【解决方案3】:

    我采用了您的代码并将其概括为适用于每个现有配置,而不仅仅是适用于 Debug/Release/RelWithDebInfo/MinSizeRel。

    我也让它与 gcc 一起工作 - 看看here

    【讨论】:

    • 是否可以从命令行指定(如果已经指定,则覆盖)静态或动态 CRT 链接?只是为了避免修改第 3 方库构建脚本
    • @AndyT 您可以创建一个代理 CMakeLists.txt,其中 add_subdirectoryies 第三方库 - 您可以在那里设置运行时 - 但如果第三方库自行设置运行时,那么它应该有一个选项...
    【解决方案4】:

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

    # 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),则也需要添加这些语言。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多