何为一个 C++ 项目
TODO
待整理,但是最近发现了一些有趣的东西,先记一下
CMAKE_MSVC_RUNTIME_LIBRARY
用于在 CMakeLists 里指定 MSVC 使用的运行时库。
MultiThreaded
对应MT
MultiThreadedDebug
对应MTd
MultiThreadedDLL
对应MD
MultiThreadedDebugDLL
对应MDd
注意这项功能仅在 CMake 3.15 之后被支持,至少需要 cmake_minimum_required(VERSION 3.15)
。
用法
1 |
|
$<$<CONFIG:Debug>:Debug>
为生成器表达式,意为“如果当前为 Debug,返回 Debug,否则返回空字符串”。
要放在 project
之前才会生效。
在 3.15 以下的版本中要实现相同的功能需要类似于:
1 |
|
详见:
Compile with /MT instead of /MD using CMake
参考
CMAKE_MSVC_RUNTIME_LIBRARY
在 CMake 中设置 MSVC 运行库
使用 dumpbin 查看静态库的依赖
在安装 VS2017 或以上的版本时会自动安装 dumpbin.exe,我的路径在:
1 |
|
将其加入环境变量即可在任意位置调用 dumpbin
。
用法
1 |
|
其中 MT_StaticReleasd
和 LIBCMT
都代表该文件使用的运行时库为 MT
。
剩余对应详见 C 运行时 .lib 文件
其他
dumpbin 看起来还有很多功能,可惜官方文档写的也不是很清楚:
DUMPBIN 选项
使用 depends 查看动态库的依赖
一个开源的 dll 依赖分析软件:
https://github.com/lucasg/Dependencies
打开 GUI 将对应 dll 拖入:
msvcp<version>.dll
对应/MD
msvcp<version>d.dll
对应/MDd
自 VS2017 以后这个 version 应该是 140。
MD:
MT:
ABI
- 体现在跨编译器的 link 大概率是失败的,因为 C++ 编译器会对符号进行一个“名称重整”的行为以满足 C++ 中的多态,而不同编译器名称重整的逻辑完全不同。不过好像 clang 之类的是能够提供对其他编译器的兼容的。
- 另一个方面是混合了同一个编译器不同版本的编译流程,比如 MSVC 自 VS2015 之后说,新的连接器可以混合链接旧版 MSVC 编译出来的库文件。C++ binary compatibility between Visual Studio versions
- 还有就是第三方库只要能保持 ABI 兼容,即可只更新 dll 文件而不用重新编译最终的运行文件。
- 对虚函数表的重排序,添加删除成员变量等都会使 ABI 兼容失效,因为内存排布不一样了,然后有个保持 ABI 兼容的技巧叫做 Pointer to implementation。PImpl