cmake:msvc分别对不同的target使用不同的运行库选项(/MT或/MD)
程序员文章站
2022-05-06 19:21:33
...
很久以前写过一篇关于cmake下为msvc设置/MT
的文章:
当时是为了解决用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