CMake设置MSVC工程MT/MTd/MD/MDd

本文详细介绍了如何在MSVC工程中通过CMakeLists.txt设置CMAKE_POLICY CMP0091以管理MT/MD运行库标志,并使用set_property设置MSVC_RUNTIME_LIBRARY属性,解决混合使用MT/MD库导致的LNK2038错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


0. 前言

MSVC工程上右键->属性,找到配置属性->C/C++->代码生成->运行库,会发现有好几种选项:MT MTd MD MDd
在这里插入图片描述
这是对于多线程程序生成对象链接内容的控制。

先理解一下这四个有什么不同:

  1. 首先后面带d表示Debug,生成对象(exe、lib都行)是带有调试信息的,生成对象占用空间相比不带d的会更大一些;
  2. MTMD区别:前者是静态链接,将有关依赖库都打包进生成对象了,所以占用空间更大;后者是动态链接,运行时依赖电脑环境,容易出现换个电脑报错dll的现象。

这个出问题常见于依赖某个lib文件时,弹出LNK2038错误:
在这里插入图片描述
一般因为VS工程默认是MD/MDd,即动态链接方式,而一些库在生成时采用的是MT/MTd方式(如GoogleTest),整个项目混合使用二者产生的报错。


1. 如何设置

1.1 CMakeLists代码

先直接上代码,随后讲解要点:

# 设置策略CMP0091为NEW,新策略
if (POLICY CMP0091)
  cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)

# 声明一个工程
project(TestpyTest)

# 添加一个exe
add_executable(test test.cpp)

# 设置MT/MTd
set_property(TARGET test PROPERTY
  MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
	

1.2 要点1:POLICY

首先是设置POLICY CMP0091,通过cmake_policy(SET policy NEW)进行设置;

策略大概可以理解为:cmake通过选择策略的NEWOLD,可以使用不同的语法,来实现同样的功能。详情可看cmake_policy

CMP0091策略是用来控制MSVC运行库标志位flags如何设置的。就拿现在要设置的MT/MD而言,cmake 3.14及以前的版本是通过CMAKE_<LANG>_FLAGS_<CONFIG>变量进行设置的,所以网上会有很多博客说设置MT的办法大概是:

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

cmake官方说了,这种字符串的形式不太方便,所以有了新方式,详情可看CMP0091

关于POLICY设置还有一点需要注意:要在project()之前设置,另外,子项目想要使用,也需要在父项目中设置,否则cmake之后用VS打开工程,依然会LNK2038

笔者在使用GoogleTest时(GoogleTest库是MTd),把Test项目作为子项目,仅在父项目或子项目中添加POLICY不行,需要都添加CMP0091

1.3 要点2:set_property

首先记住MSVC_RUNTIME_LIBRARY属性,它的取值可以是:

  • MultiThreaded :对应MT
  • MultiThreadedDLL :对应MD
  • MultiThreadedDebug:对应MTd
  • MultiThreadedDebugDLL:对应MDd

这几个取值通过字符串形式设置给MSVC_RUNTIME_LIBRARY属性,但官方给的字符串是:

"MultiThreaded$<$<CONFIG:Debug>:Debug>"

这用到了cmake的生成表达式(generator expression)功能,使得当ConfigDebug时,自动添加Debug。使用到了嵌套表达式:

  1. $<CONFIG:Debug>使用了变量查询的语句,当处于Debug模式时,该表达式为1
    在这里插入图片描述
  2. 知道上一条之后,<$<$<CONFIG:Debug>: Debug>就变成了$<1或0:Debug>,使用的是条件表达式,当前部分为1是该表达式为Debug,否则为空:
    在这里插入图片描述

生成表达式可以参考官方:cmake-generator-expressions(7)

在不设置MSVC_RUNTIME_LIBRARY属性时,它默认值为MultiThreaded$<$<CONFIG:Debug>:Debug>DLL,是MDMDd

更多细节参见官方教程:MSVC_RUNTIME_LIBRARY

C:\Qt\Tools\CMake_64\share\cmake-3.30\Modules\CMakeTestCXXCompiler.cmake:73: error: The C++ compiler "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/HostX64/x64/cl.exe" is not able to compile a simple test program. It fails with the following output: Change Dir: 'C:/Qt/Examples/Qt-6.6.3/demos/calqlatr/build/Desktop_Qt_6_6_3_MSVC2019_64bit-Debug/CMakeFiles/CMakeScratch/TryCompile-p6qlk1' Run Build Command(s): C:/Qt/Tools/Ninja/ninja.exe -v cmTC_4f979 [1/2] "C:\PROGRA~1\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\HostX64\x64\cl.exe" /nologo /TP -DQT_QML_DEBUG /DWIN32 /D_WINDOWS /GR /EHsc /Zi /Ob0 /Od /RTC1 -MDd /showIncludes /FoCMakeFiles\cmTC_4f979.dir\testCXXCompiler.cxx.obj /FdCMakeFiles\cmTC_4f979.dir\ /FS -c C:\Qt\Examples\Qt-6.6.3\demos\calqlatr\build\Desktop_Qt_6_6_3_MSVC2019_64bit-Debug\CMakeFiles\CMakeScratch\TryCompile-p6qlk1\testCXXCompiler.cxx [2/2] C:\Windows\system32\cmd.exe /C "cd . && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\cmTC_4f979.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- "C:\PROGRA~1\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\link.exe" /nologo CMakeFiles\cmTC_4f979.dir\testCXXCompiler.cxx.obj /out:cmTC_4f979.exe /implib:cmTC_4f979.lib /pdb:cmTC_4f979.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." FAILED: cmTC_4f979.exe C:\Windows\system32\cmd.exe /C "cd . && C:\Qt\Tools\CMake_64\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\cmTC_4f979.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- "C:\PROGRA~1\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\link.exe" /nologo CMakeFiles\cmTC_4f979.dir\testCXXCompiler.cxx.obj /out:cmTC_4f979.exe /implib:cmTC_4f979.lib /pdb:cmTC_4f979.pdb /version:0.0 /machine:x64 /d
03-26
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值