用gcc生成静态库时,cmake必须显式声明static、用target_include_directories(public)设置头路径、确保add_library在add_executable之前且target_link_libraries写在其后,否则链接或头文件包含会失败。

用 GCC 生成静态库,CMake 配置本身比 Clang 更“宽容”,但关键点一个都不能漏:必须显式写 STATIC、头路径要用 target_include_directories(PUBLIC)、链接顺序不能颠倒。否则编译通过,一到链接或包含头文件就报错。
add_library 必须带 STATIC 关键字
这是最常被忽略的硬性要求。CMake 默认不假设你要建什么类型库,BUILD_SHARED_LIBS 全局开关会偷偷覆盖你的意图。
- 正确写法:
add_library(xlog STATIC xlog.cpp xlog.h)——STATIC是必需参数,头文件列进去还能触发依赖重编译 - 错误写法:
add_library(xlog xlog.cpp)—— 如果项目里某处设了-DBUILD_SHARED_LIBS=ON(比如父 CMakeLists.txt 或 CI 脚本),它就会静默生成libxlog.so,不是你要的.a - 验证方法:构建后进
build/lib/,Linux 下执行file libxlog.a,输出应含current ar archive;若出现ELF shared object,说明你被动态库劫持了
头文件路径必须用 target_include_directories(PUBLIC)
静态库不打包头文件,调用方得自己知道接口在哪。用错作用域,下游 #include "xlog.h" 就直接报 No such file or directory。
- 正确写法:
target_include_directories(xlog PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)——PUBLIC表示“我提供头文件,也允许链接我的目标继承这个路径” - 错误写法:
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)—— 全局污染,且无法随目标传递;PRIVATE则下游完全看不到 - 如果头文件在
include/xlog/xlog.h,路径仍写${CMAKE_CURRENT_SOURCE_DIR}/include,使用时写#include "xlog/xlog.h"
target_link_libraries 和定义顺序必须严格匹配
CMake 解析是顺序敏感的:库目标必须在可执行目标之前定义,且 target_link_libraries 的位置决定了能否把头路径和链接信息透传下去。
- 必须先写:
add_library(xlog STATIC ...),再写add_executable(app main.cpp) - 链接必须写在可执行目标定义之后:
target_link_libraries(app PRIVATE xlog) - 如果写成
target_link_libraries(xlog PRIVATE some_dep),那是给库自身加依赖;而target_link_libraries(app PRIVATE xlog)才能把xlog的PUBLIC头路径自动带进app的编译上下文
最容易被忽略的是:即使你所有语法都对,只要 add_library 出现在 add_executable 后面,或者 target_link_libraries 写在目标定义前,CMake 就不会把 PUBLIC 属性透传过去——这时候 #include 报错,但错误信息完全不提示是顺序问题。











