Loading

【编译与代码分析记录】03 · CMake 链接静态库与动态库

CMake 链接静态库与动态库

整理自博客园旧笔记:《cmake链接静态库&动态库》(原发布于 2022-09-13)

一、项目结构

./sample7
  +-- CMakeLists.txt          # 顶层
  +-- build/
  +-- src/
        +-- CMakeLists.txt
        +-- main.cpp
  +-- lib/
        +-- libmath.a         # 静态库(macOS/Windows 为 .a/.lib)
        +-- libmath.dylib     # 动态库(Linux 为 .so,Windows 为 .dll)
        +-- Math.h

main.cpp 中引用外部 math 库:

#include <stdio.h>
#include <stdlib.h>
#include "Math.h"

int main(int argc, char *argv[])
{
    double base = atof(argv[1]);
    return 0;
}

二、引入外部静态库

src/CMakeLists.txt:

# 打印信息
message(STATUS "src This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "src This is SOURCE dir " ${PROJECT_SOURCE_DIR})

# 定义工程根目录;CMAKE_SOURCE_DIR 为内建变量,表示工程根目录的 CMakeLists.txt 路径
SET(ROOT_DIR ${CMAKE_SOURCE_DIR})

# 指定头文件搜索路径
INCLUDE_DIRECTORIES(${ROOT_DIR}/lib)

# 指定引用的外部库的搜索路径
LINK_DIRECTORIES(${ROOT_DIR}/lib)

# 指定可执行文件存放目录
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

# 构建可执行程序
ADD_EXECUTABLE(sample7 main.cpp)
TARGET_LINK_LIBRARIES(sample7 libmath.a)

三、引入外部动态库

结构与上面完全一致,只把链接目标换成动态库:

INCLUDE_DIRECTORIES(${ROOT_DIR}/lib)
LINK_DIRECTORIES(${ROOT_DIR}/lib)
ADD_EXECUTABLE(sample7 main.cpp)
TARGET_LINK_LIBRARIES(sample7 libmath.dylib)   # Linux 下为 libmath.so

四、静态库 vs 动态库

静态库(.a/.lib) 动态库(.so/.dylib/.dll)
链接时机 链接阶段整体拷贝进最终目标(如可执行程序) 链接阶段不拷贝,运行时按搜索规则找到后加载
内存 被多个程序引用时,各程序各存一份函数拷贝 多个程序共享同一份库代码
分发 可执行文件自包含、无依赖 目标机器上必须有该库(或随程序分发)
升级 重新链接 替换库文件即可(注意 ABI 兼容与 soname)
体积 可执行文件更大 可执行文件小

4.1、现代 CMake 推荐写法

INCLUDE_DIRECTORIES + LINK_DIRECTORIES 是"全局式"老写法,容易污染其他 target。现代写法把依赖挂在具体 target 上:

# 链接已有库
target_link_libraries(sample7 PRIVATE ${ROOT_DIR}/lib/libmath.a)
target_include_directories(sample7 PRIVATE ${ROOT_DIR}/lib)

# 项目内生成库再链接
add_library(math STATIC src/math.cpp)      # 或 SHARED
target_link_libraries(sample7 PRIVATE math)

4.2、动态库运行时找不到怎么办

链接通过 ≠ 运行能跑。动态库运行时按以下顺序搜索:

  1. 可执行文件的 RPATH/RUNPATH(链接时 -Wl,-rpath,/path 写入)
  2. 环境变量 LD_LIBRARY_PATH(Linux)/ DYLD_LIBRARY_PATH(macOS)
  3. 系统配置 /etc/ld.so.conf + ldconfig 缓存

排查工具:ldd a.out(Linux)看依赖解析;otool -L a.out(macOS)。

五、常用内建变量速查

变量 含义
CMAKE_SOURCE_DIR 顶层 CMakeLists.txt 所在目录
PROJECT_BINARY_DIR 构建目录
CMAKE_BUILD_TYPE Debug/Release/RelWithDebInfo
EXECUTABLE_OUTPUT_PATH 可执行文件输出目录(现代用 RUNTIME_OUTPUT_DIRECTORY)

构建命令:

mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
posted @ 2026-09-19 05:45  Stellan7  阅读(8)  评论(0)    收藏  举报