CMake Debug后缀
set_target_properties(liba PROPERTIES DEBUG_POSTFIX "d") 或者 set(CMAKE_DEBUG_POSTFIX "d") 这样生成的库或者exe程序名会多一个d字符。如下
链接 vc++ 运行时库
通过/MD、/MT 可以改变MSVC运行库,
- /MD代表使用动态运行时库,程序运行时需要有MSVCRversionnumber.DLL,这些库是通过安装Download Microsoft Visual C++ Redistributables 获得。例如msvcp140.dll就是在 Microsoft Visual C++ Redistributable for Visual Studio 2015中。
- /MT会使用静态运行时库,MSVC库会编译链接到exe程序中,所以系统不安装VC++库也可以正常运行,但是这会增加exe的大小,且由于不能共享使用公用的DLL也会消耗更多内存。
- /MD、/MT都有对应的debug版,/MDd、/MTd,链接时使用的库也是对应的Debug版,例如msvcp140d.dll则是VC++ 2015的Debug版库。这种库需要安装Visual studio 20xx时才能获得,非开发设备一般都没有这种库。
MSVC 链接动态库
对于动态库都有对应的DLL,DLL本身就是可以执行文件,系统可以直接读取并执行,其内部已经包含了所有运行时的函数或符号。所以动态库生成后其已经可以与编译环境分离,也就是说如果你编译了一个动态库,不管程序时Debug还是Release都可以链接这个库,这个库也不会受编译器版本的限制,大部分情况下不同VS版本都可以通用。
MSVC 链接静态库
静态库只是一个中间编译状态,并不能直接运行,还需要与调用者编译链接才能运行。应为是中间状态所以在VS2015之前,不同版本VS编译的静态库都不能通用,必须要相同版本才能编译链接。VS2015以后微软队各个版本的静态库abi做了兼容,所以VS2015后大部分静态库可以通用。
如果Debug版C++程序链接Release版静态库时,链接会报错,以下是VS2022的报错:
liba.lib(a.cpp.obj) : error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”(main.cpp.obj 中)
liba.lib(a.cpp.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MDd_DynamicDebug”(main.cpp.obj 中)
LINK : warning LNK4098: 默认库“MSVCRT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
E:\Study\StudyProject\cmake\lib_debug_release\main.exe : fatal error LNK1319: 检测到 2 个不匹配项
这是因为Debug版和Release版默认使用的vc++ 运行时库不相同,默认情况下Debug版使用/MDd,Release版使用/MD,两者不相同导致报错。
所以在链接库时需要区分Debug版和Release版。在CMake可以如下设置:
target_link_libraries(target $<$<CONFIG:Release>:liba.lib> $<$<CONFIG:Debug>:libad.lib>)
C语言静态库
上面说的都是关于C++的,实际上如果一个库是使用C开发的,那么这个库不会受VC++运行库的影响,也就是说你可以在Debug程序中链接一个C开发的Release的静态库。
很多开源库都是使用C开发的,所以在编译这些库的静态库时,只需要编译一个Release版。