Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Visual studio 在CMake中设置MSVC运行时_Visual Studio_Cmake - Fatal编程技术网

Visual studio 在CMake中设置MSVC运行时

Visual studio 在CMake中设置MSVC运行时,visual-studio,cmake,Visual Studio,Cmake,我遵循CMake FAQ条目中的说明,集中选择一系列嵌套CMake项目的MSVC运行时(它们作为Git子模块拉入,并使用CMake的find_package()指令添加到主项目中) 所以,我写了这个CMake宏: macro(configure_msvc_runtime) if(MSVC) # Default to statically-linked runtime. if("${MSVC_RUNTIME}" STREQUAL "") set(MSVC_RUNT

我遵循CMake FAQ条目中的说明,集中选择一系列嵌套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
的开头调用此宏(在进行任何
add\u library()
add\u 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
-- 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
现在,当我启动VisualStudio并检查“C/C++,代码生成”下的项目属性时,我发现“运行时库”设置与shell中打印的选项不一致。在“Release”、“MinSizeRel”和“RelWithDebInfo”配置下,我得到了预期的结果(“多线程DLL/MD”,但“Debug”配置仍然显示“多线程/MT”)

另外,当我强制使用静态链接的运行时时,我会得到类似的结果。如果我跑

cmake -G "Visual Studio 9 2008" ..\.. -DMSVC_RUNTIME=static
我得到以下输出:

-- 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
-- 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还是什么


值得一提的是,如果我生成VisualStudio2010项目文件,我会为“调试”配置获得不同的值,但仍然不是我选择的值


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

似乎在我处理这个问题的过程中,我忘记删除我试图替换的坏CMake配置

在构建脚本的后面,我留下了一个小错误:

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

基本上,我使用未设置msvc运行时的生成标志覆盖了by
configure\u msvc\u runtime()
宏的结果。

我使用了您的代码,并将其推广为适用于所有现有配置,而不仅仅适用于Debug/Release/RelWithDebInfo/MinSizeRel


此外,我还使其与gcc一起工作-查看它

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

应该设置
CMAKE_MSVC_RUNTIME_LIBRARY
,例如(从文档中)设置“多线程静态链接运行库,根据配置有无调试信息”:

set(CMAKE\u MSVC\u RUNTIME\u库“多线程$”)

我提出了一个解决方案,它适用于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()
#在项目()之前需要考虑此逻辑
设置(_change_MSVC_flags FALSE)
如果(WIN32)
如果(CMAKE_版本小于3.15.0)
设置(_change_MSVC_flags TRUE)
else()
#将MSVC运行时设置为多线程(/MT)
cmake_策略(设置CMP0091新)
设置(CMAKE\U MSVC\U运行时\U库“多线程$”)
endif()
endif()
项目(MyProj…)
如果(更改MSVC标志)
#修改编译标志以将MSVC运行时从/MD更改为/MT
集合(【重新匹配】([\\/\\-]M)D)
设置(替换“\\1T”)
字符串(REGEX REPLACE${u re_match}${{u re_REPLACE}
CMAKE_CXX_标志“${CMAKE_CXX_标志}”)
字符串(REGEX REPLACE${u re_match}${{u re_REPLACE}
CMAKE_CXX_FLAGS_DEBUG“${CMAKE_CXX_FLAGS_DEBUG}”)
字符串(REGEX REPLACE${u re_match}${{u re_REPLACE}
CMAKE_CXX_FLAGS_RELEASE“${CMAKE_CXX_FLAGS_RELEASE}”)
字符串(REGEX REPLACE${u re_match}${{u re_REPLACE}
CMAKE_CXX_FLAGS_MINSIZEREL“${CMAKE_CXX_FLAGS_MINSIZEREL}”)
字符串(REGEX REPLACE${u re_match}${{u re_REPLACE}
CMAKE_CXX_FLAGS_RELWITHDEBINFO“${CMAKE_CXX_FLAGS_RELWITHDEBINFO}”)
endif()

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

您的解决方案真的为我节省了强制静态运行库的时间!是否可以从命令行指定(或重写,如果已经指定)静态或动态CRT链接?只是为了避免修改第三方libs构建scripts@AndyT您可以创建一个代理CMakeLists.txt,该代理
add_subdirectory
可以设置第三方库-您可以在那里设置运行时-但是如果第三方库自己设置运行时,那么它应该有一个选项…对此不确定!我有cmake版本3.17.3!你所描述的方式是行不通的!