欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

cmake:msvc分别对不同的target使用不同的运行库选项(/MT或/MD)

程序员文章站 2022-05-06 19:21:33
...

很久以前写过一篇关于cmake下为msvc设置/MT的文章:

cmake:msvc编译第三方库时使用/MT静态库连接c/c++ runtime library

当时是为了解决用msvc编译时使用/MT连接static c library的问题。CMakeLists.txt中添加如下的代码,即可以将所有默认的C,CXX编译选项中的/MD替换成/MT.

if(MSVC)     
    # Use the static C library for all build types
    foreach(var 
        CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
        CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
      )
      if(${var} MATCHES "/MD")
        # 正则表达式替换/MD为/MT
        string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
      endif()
    endforeach()    
endif(MSVC)

如果你希望CMakeLists.txt中所有的target都使用c/c++静态库,那么上面的做法就完全满足需要。
但如果希望针对CMakeLists.txt中的不同target使用不同的/MT/MD选项,这个办法就不行了。如果希望针对特定的target设置/MT选项,该怎么办呢?

这里就用到了target_compile_options命令还用到了Generator expressions,以下为封装成function的实现代码

# Use the static C library for all build types to a target
# MSVC编译时对指定的target设置'/MT'选项连接static c/c++ library
function (with_mt_if_msvc target )
if(MSVC) 
  # Generator expressions
  set(_mt "/MT$<$<CONFIG:Debug>:d")
  get_target_property(_options ${target} COMPILE_OPTIONS)
  if(_options)
    # message(STATUS "${target} COMPILE_OPTIONS=${_options}")
    if(${_options} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" _options "${_options}")
    else()
      set(_options "${_options} ${_mt}")
    endif()    
  else()
    set(_options "${_mt}")
  endif() 
  get_target_property(_type ${target} TYPE)
  # 判断 ${target}是否为静态库
  if(_type STREQUAL "STATIC_LIBRARY")
    # 静态库将/MT选项加入INTERFACE_COMPILE_OPTIONS
    target_compile_options( ${target} PUBLIC "${_options}")
  else()
    target_compile_options( ${target} PRIVATE "${_options}")
  endif()
  # Cleanup temporary variables.
  unset(_mt)
  unset(_options)
  message(STATUS "target ${target} use static runtime /MT")
endif(MSVC)
endfunction()

有了这个with_mt_if_msvc函数,你可以针对target设置/MT选项,而那些没有指定的target仍使用默认的/MD选项

参考资料

Is it possible, in the same CMakeLists.txt, to setup projects with /MT and others with /MD?
target_compile_options
cmake-generator-expressions

相关标签: cmake msvc