add_library默认行为由build_shared_libs决定:on时生成动态库,off时生成静态库;建议显式声明static或shared;头文件可加入源列表以建立依赖但不编译;同名目标不能同时定义static和shared;exclude_from_all使目标不参与默认构建且install需显式声明。

add_library没加类型参数,结果生成了动态库?
默认行为取决于 BUILD_SHARED_LIBS 变量值:如果它是 ON,add_library(mylib src.cpp) 就生成 .so 或 .dll;如果是 OFF(CMake 默认),才生成静态库。很多人没改这个变量,又没显式写 STATIC,结果在 CI 上编译出动态库,本地却一直是静态的——环境不一致导致链接失败。
建议始终显式声明类型:
- 要静态库,就写
add_library(mylib STATIC src.cpp) - 要动态库,就写
add_library(mylib SHARED src.cpp) - 别依赖全局变量,尤其当项目要跨团队、跨平台交付时
头文件要不要放进 add_library 的源文件列表?
可以放,但不是为了“编译”,而是为了建立依赖关系。比如 add_library(mylib STATIC src.cpp include/mylib.h),这样当 mylib.h 被修改,CMake 会触发 mylib 重编译——否则只改头文件,库可能不重建,导致符号不一致或 ODR 错误。
注意两点:
-
.h文件不会被编译,只是作为依赖项参与构建图 - 真正让其他目标能 #include 到它的路径,得靠
target_include_directories(mylib PUBLIC include) - 别把无关头文件(比如第三方库头)塞进去,会污染依赖判断
同一个名字,想同时生成静态和动态版本?
不能用同一个 target_name,因为 CMake 要求目标名全局唯一。add_library(utils STATIC ...) 和 add_library(utils SHARED ...) 会报错:add_library cannot create target "utils" because another target with the same name already exists。
正确做法是起不同名字:
add_library(utils_static STATIC src/utils.cpp)add_library(utils_shared SHARED src/utils.cpp)- 再用
set_target_properties统一输出名(如都叫utils),避免下游硬编码文件名 - 若需自动选择,可用
if(BUILD_SHARED_LIBS)分支控制,但目标名仍不能重复
EXCLUDE_FROM_ALL 是干啥的,什么时候该用?
加上它,这个库就不会被 make 或 ninja 默认构建——除非别的目标(比如可执行文件)明确依赖它,或者你手动 make mylib。
典型场景:
- 提供给外部项目使用的 SDK 库,内部构建时不希望每次都编译
- 测试专用的 mock 库,主构建流程里不需要
- 正在开发中的实验性模块,还不稳定,先隔离出来
容易忽略的是:一旦用了 EXCLUDE_FROM_ALL,install() 目标也不会自动包含它,必须显式 install(TARGETS mylib ...),否则 install 后目录里根本没有这个库。











