【问题标题】:Compile with /MT instead of /MD using CMake使用 CMake 编译 /MT 而不是 /MD
【发布时间】:2012-12-19 19:39:33
【问题描述】:

我在带有 Windows SDK 和 NMake Makefiles 的 Windows 上使用 CMake。

默认情况下,它使用/MD 编译器开关进行编译。

如何将其更改为使用/MT 开关进行编译?

【问题讨论】:

    标签: cmake


    【解决方案1】:

    您可以修改CMAKE_CXX_FLAGS_<Build Type> 和/或CMAKE_C_FLAGS_<Build Type> 变量:

    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
    

    如果您的 CMake 标志已经包含 /MD,您可以确保在插入 /MD 的点之后执行上述命令(稍后添加 /MT 会覆盖冲突现有选项),或者您可以从头开始设置标志:

    set(CMAKE_CXX_FLAGS_RELEASE "/MT")
    set(CMAKE_CXX_FLAGS_DEBUG "/MTd")
    

    或者,您可以分别用/MT 和/MTd 替换现有的/MD 和/MDd 值,方法是:

    set(CompilerFlags
            CMAKE_CXX_FLAGS
            CMAKE_CXX_FLAGS_DEBUG
            CMAKE_CXX_FLAGS_RELEASE
            CMAKE_C_FLAGS
            CMAKE_C_FLAGS_DEBUG
            CMAKE_C_FLAGS_RELEASE
            )
    foreach(CompilerFlag ${CompilerFlags})
      string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
    endforeach()
    

    【讨论】:

    • @Josh 我刚刚更新了答案。如果它仍然不是您所追求的,请显示您的 CMakeLists.txt 的相关部分,我相信会有一个简洁的答案。
    • @Josh 我在string(REPLACE...) 命令中犯了一个小错误 - 现在已修复。
    • 这个请求很常见 - 奇怪的是 CMake 仍然没有开箱即用的宏或设置来支持这个。我最终在几乎每个项目中都这样做——尤其是那些具有外部依赖项的项目,例如 GoogleMock,它们对编译器 ABI 有自己的默认意见
    • 谁能告诉我应该在 vcpkg 中的哪个文件中进行此更改?
    • @Fraser 可以通过运行cmake -D CMAKE_CXX_FLAGS="/MT" ..从命令行设置此选项吗?
    【解决方案2】:

    CMake 终于在 3.15 版中通过 MSVC_RUNTIME_LIBRARY 目标属性添加了对此的适当支持:

    cmake_minimum_required(VERSION 3.15)
    cmake_policy(SET CMP0091 NEW)
    project(my_project)
    
    add_executable(foo foo.c)
    set_property(TARGET foo PROPERTY
                 MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
    

    您也可以通过设置CMAKE_MSVC_RUNTIME_LIBRARY 变量来指定全局默认值。

    【讨论】:

    • 它在 3.16.3 上没有 cmake_policy(SET CMP0091 NEW) 以某种方式工作,真的需要吗?
    • @VladimirGamalyan 与策略一样,如果您的cmake_minimum_required 足够新,则无需明确请求新行为。我主要将政策包含在答案中,以便人们知道此功能存在政策并在他们关心兼容性影响时查找它。
    • 这应该是公认的解决方案,至少对于现代 cmake 而言。这远没有破解 CMAKE_CXX_FLAGS 不透明......
    • @DavidKarla 除了这个答案是在提出原始问题六年后给出的,并不是说被问到的人自 2015 年以来就没有登录过。
    • 这行不通。
    【解决方案3】:

    似乎对于 Visual Studio 15 2017 和 CMake 3.12,将 /MD 替换为 /MT 的方法是将此 sn-p 添加到 CMakeLists。 txt 文件:

    if(MSVC)
        add_compile_options(
            $<$<CONFIG:>:/MT> #---------|
            $<$<CONFIG:Debug>:/MTd> #---|-- Statically link the runtime libraries
            $<$<CONFIG:Release>:/MT> #--|
        )
    endif()
    

    我在官方 CMake 存储库中找到了这个解决方案:https://gitlab.kitware.com/cmake/cmake/issues/18390

    【讨论】:

    • 注意:此块应加在add_executable或add_library之前
    【解决方案4】:

    查看 ucm_set_runtime - 此宏将替换静态或动态运行时的标志 - 要查看效果,请使用 ucm_print_flags(也可查看 this Stack 溢出问题)。

    【讨论】:

      【解决方案5】:

      我必须使用set( ... CACHE ... FORCE) 来覆盖 MSVC 的默认缓存。

      如果我不使用这个方法,MSVC 仍然会输出/MD options。

      set(CompilerFlags
              CMAKE_CXX_FLAGS
              CMAKE_CXX_FLAGS_DEBUG
              CMAKE_CXX_FLAGS_RELEASE
              CMAKE_CXX_FLAGS_MINSIZEREL
              CMAKE_CXX_FLAGS_RELWITHDEBINFO
              CMAKE_C_FLAGS
              CMAKE_C_FLAGS_DEBUG
              CMAKE_C_FLAGS_RELEASE
              CMAKE_C_FLAGS_MINSIZEREL
              CMAKE_C_FLAGS_RELWITHDEBINFO
              )
      foreach(CompilerFlag ${CompilerFlags})
          string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
          set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE)
          message("MSVC flags: ${CompilerFlag}:${${CompilerFlag}}")
      endforeach()
      

      【讨论】:

      • 在浪费了数小时之后,这是唯一对我有用的东西。谢谢!
      • 虽然这似乎仍然动态链接一些标准库:MSVCP140.dll、VCRUNTIME140_1.dll、VCRUNTIME140.dll、api-ms-win-crt-string-l1-1-0.dll ...
      • @Miscreant 我唯一能建议的是检查 cmake 缓存中所有生成的命令行参数。 cmake的规则比较复杂,MSVC的系统比较乱。
      【解决方案6】:

      从 cmacke 3.15 开始,您可以使用MSVC_RUNTIME_LIBRARY。 见https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-19
        • 1970-01-01
        • 2011-03-29
        • 2016-12-18
        • 1970-01-01
        • 1970-01-01
        • 2015-04-10
        • 1970-01-01
        相关资源
        最近更新 更多