最直接确认生成静态库的方法是检查输出文件后缀及用file命令验证:linux/macos下libxxx.a为ar归档即静态库,libxxx.so/.dylib为共享对象即动态库;若出现动态库,说明add_library未写static或被build_shared_libs=on覆盖。

怎么确认生成的是静态库而不是动态库
最直接的办法是进 build/lib/(或你指定的输出目录)看文件后缀和格式。Linux/macOS 下用 file 命令一眼就能分辨:
-
file libxlog.a输出current ar archive→ 是静态库 ✅ -
file libxlog.so或libxlog.dylib输出ELF shared object或Mach-O dynamically linked shared library→ 是动态库 ❌
如果看到的是动态库,说明 add_library(xlog STATIC ...) 没写 STATIC,或者被 -DBUILD_SHARED_LIBS=ON 覆盖了。
头文件路径是否暴露成功
静态库本身不带头文件,调用方必须能 #include "xlog.h" 且编译通过。验证方式很简单:写个最小测试程序,只包含头、不链接库,看预处理是否报错:
Clang 22.1.3 Windows 64 位历史版本安装包,适合旧项目兼容、LLVM/Clang 工具链回退、编译行为对比、链接问题复现和 C/C++ 构建环境维护。
- 新建
test_include.cpp:#include "xlog.h"
- 用相同编译器和包含路径尝试预处理:
clang++ -I/path/to/your/include -E test_include.cpp > /dev/null - 若无报错,说明
target_include_directories(xlog PUBLIC ...)配对正确;若报xlog.h: No such file or directory,大概率漏了PUBLIC或路径写错了(比如写成${CMAKE_CURRENT_SOURCE_DIR}/include/xlog却在代码里写了#include "xlog.h")
链接时能否找到符号
建一个最简可执行目标,只调用静态库里的一个函数,然后链接:
add_executable(test_xlog test_xlog.cpp)target_link_libraries(test_xlog xlog)- 构建后运行
nm -C build/test_xlog | grep xlog_init(假设你有个xlog_init()),如果能看到T xlog_init(T 表示定义在本文件),说明符号已正确合并进可执行体 - 如果链接时报
undefined reference to 'xlog_init',常见原因是:库目标定义在可执行目标之后、target_link_libraries写错名字、或函数声明/定义不一致(比如头文件里是void xlog_init();,实现却是int xlog_init())
运行时是否真能用(避免隐式依赖)
静态库理论上不依赖运行时共享库,但如果你的静态库代码里调用了 std::string、std::vector 或其他 STL 组件,而没加 -static-libstdc++,最终可执行文件仍会依赖 libstdc++.so。验证方法:
- 构建完可执行文件后,运行
ldd build/test_xlog - 理想情况是只列出系统基础库(
linux-vdso.so.1、libc.so.6等),**不应出现libstdc++.so或libgcc_s.so** - 若出现了,得在 CMake 中加:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc"),否则“静态库”只是表面静态,实际仍带动态依赖
真正麻烦的不是构建成功,而是构建成功却在另一台机器上跑不起来——因为漏掉了 -static-libstdc++ 或头文件路径没透出,这类问题往往要等部署才暴露。










