必须加static关键字,否则默认生成动态库;正确写法为add_library(mylib static src/a.cpp src/b.cpp),未指定类型时build_shared_libs控制但不可靠。

add_library() 必须加 STATIC 关键字
不加 STATIC 默认生成动态库(.so 或 .dll),哪怕你只传了源文件。CMake 不会根据输出后缀反推类型,它只认关键字。
正确写法:
add_library(mylib STATIC src/a.cpp src/b.cpp)
常见错误:
- 写成
add_library(mylib src/a.cpp src/b.cpp)→ Linux 下默认建libmylib.so - 写成
add_library(mylib SHARED ...)→ 强制动态,和目标相反 - 在
add_library()后用set_target_properties(... PROPERTIES PREFIX "")试图“改成静态” → 无效,类型在定义时已锁定
Windows 上 .lib 和 .a 的区别得看编译器链
MSVC 生成的是 .lib(导入库 + 存档混合体),MinGW-w64 生成的是 .a(标准 GNU ar 归档)。CMake 会自动适配,你不用改后缀名,但得确认工具链。
检查方法:
- 运行
cmake -G "Visual Studio 17 2022" ..→ 输出mylib.lib - 运行
cmake -G "MinGW Makefiles" ..→ 输出libmylib.a - 用
file libmylib.a或dumpbin /headers mylib.lib可验证实际格式
别手动改 SET(CMAKE_STATIC_LIBRARY_SUFFIX ".a") —— 这会破坏 MSVC 工具链的默认行为,导致链接失败。
CMake 4.3.2 Windows x86_64 历史版本安装包,适合旧项目兼容、构建环境回退、CMakeLists.txt 迁移验证、Visual Studio/Ninja/Makefile 生成器测试和 C/C++ 项目维护。
头文件要显式安装,否则别人用不了
静态库只有二进制,调用方必须能 #include 对应头文件。CMake 不会自动把头文件打包或复制过去。
必须加安装规则:
target_include_directories(mylib PUBLIC $<build_interface:>
$<include>)
install(TARGETS mylib
ARCHIVE DESTINATION lib)
install(DIRECTORY include/ DESTINATION include)</include></build_interface:>
否则用户执行 find_package(mylib) 后,target_link_libraries(app PRIVATE mylib) 能连上,但编译时报 “no such file or directory”。
静态库不能有未解决的符号,除非明确允许
静态库本质是目标文件打包,不检查符号是否可解析。但如果你在库里调用了外部函数(比如 pthread_create),而链接时又没传 -lpthread,最终可执行文件会链接失败 —— 错误发生在下游,不是建库时。
规避建议:
- 尽量让静态库自包含:用
target_link_libraries(mylib PRIVATE Threads::Threads)把依赖内联进库属性 - 避免在静态库中直接调用系统 API(如 Windows
LoadLibrary)而不封装;跨平台时尤其容易漏依赖 - 如果真要留空符号(比如插件接口),用
target_link_libraries(mylib INTERFACE "-undefined dynamic_lookup")(macOS)或INTERFACE "-Wl,--allow-multiple-definition"(Linux),但这是例外,不是默认做法
最常被忽略的是:静态库本身 build 成功 ≠ 它能被正常链接使用。真正的问题往往出现在下游项目第一次链接它的时候。










