add_library生成静态库需显式加static参数,用target_include_directories暴露头文件路径,install时指定archive类型并确保output_name与find_package兼容,三者缺一不可。

add_library 是生成静态库最直接的方式,但光写这行代码往往不够——它能编译出 .a 或 .lib,但名字、路径、头文件暴露方式稍有偏差,下游项目就链接失败或找不到头。
用 add_library 必须带 STATIC 参数
不写类型,默认行为取决于全局变量 BUILD_SHARED_LIBS(若为 ON,add_library(foo ...) 会生成动态库)。所以必须显式声明:
add_library(mathutils STATIC src/vector.cpp src/matrix.cpp)
常见错误是漏掉 STATIC,结果在 Linux 下生成了 libmathutils.so 却以为是静态库,后续 target_link_libraries 链接时静默失败或报 undefined reference。
-
STATIC对应输出:lib<name>.a</name>(Linux/macOS)或<name>.lib</name>(Windows) - 目标名(如
mathutils)只是 CMake 内部标识,和最终文件名无关 - 源文件列表支持
.c、.cpp,也建议把.h加进去(触发依赖重建)
控制输出文件名:用 set_target_properties 改 OUTPUT_NAME
默认输出是 libmathutils.a,但如果你希望下游用 find_package 或手动 -lmathutils,就得去掉 lib 前缀。否则 -lmathutils 会去找 liblibmathutils.a。
add_library(mathutils_static STATIC ${LIB_SOURCES})<br>set_target_properties(mathutils_static PROPERTIES OUTPUT_NAME "mathutils")
注意:目标名 mathutils_static 和输出名 mathutils 是两回事。前者用于 CMake 内部引用(比如 target_link_libraries),后者决定磁盘上文件叫什么。
- 不能对同一个目标名同时定义
STATIC和SHARED——CMake 报错duplicate target - 想共用一个逻辑名(如都叫
mathutils),必须用不同目标名 +OUTPUT_NAME统一输出 - Windows 下
OUTPUT_NAME不影响导入库(.lib)的命名,但影响静态库本身
让别人能正确包含头文件:用 target_include_directories
只生成 .a 文件还不够。如果头文件在 include/mathutils/,而调用方写 #include <mathutils></mathutils>,就必须把 include 目录加进 include path。
target_include_directories(mathutils_static PUBLIC include)
PUBLIC 表示:这个目录既用于编译 mathutils_static 自身,也会“传染”给所有链接它的目标(比如你的 demo 可执行文件)。
- 别用
include_directories()全局设置——它不随目标隔离,易污染其他库 - 如果头文件路径是
include/,但头中写的是#include "vector.h",那就用target_include_directories(... PRIVATE include) - 路径必须是相对于
CMakeLists.txt的,不能用绝对路径或$ENV{...}(除非你明确控制构建环境)
安装时别漏掉头文件和静态库
生成只是第一步,真正交付给别人用,得靠 install()。漏掉头文件,别人 #include 就报错;漏掉 ARCHIVE 类型,libxxx.a 就不会被复制。
install(TARGETS mathutils_static ARCHIVE DESTINATION lib)<br>install(DIRECTORY include/mathutils DESTINATION include)
关键点:
-
ARCHIVE对应静态库(LIBRARY对应动态库,RUNTIME对应可执行文件) -
DESTINATION是相对于CMAKE_INSTALL_PREFIX的路径,默认是/usr/local - 运行
cmake --install build才真正拷贝文件;只cmake --build不会安装
.a 这一步,而是让下游项目能干净地 find_package 或 target_link_libraries 并自动获得头文件路径——这要求 OUTPUT_NAME、PUBLIC include、ARCHIVE install 三者全部到位,缺一不可。











