【CMake基础入门教程】第六课:构建静态库 / 动态库 与安装规则(install)

太棒了,我们进入 第六课:构建静态库 / 动态库 与安装规则(install)

这是模块化项目真正进入“可复用组件”的关键阶段:
你不仅能在项目里用库,还能编译出 .lib.dll 文件用于发布、安装、共享。


🎯 本课目标

  1. 学会构建 静态库(.lib/.a)动态库(.dll/.so)

  2. 区分 STATIC / SHARED 的区别

  3. 使用 install() 安装头文件和库文件

  4. 了解导出宏(Windows 动态库中必要)


一、什么是静态库与动态库?

类型文件扩展名链接方式使用场景
静态库.lib(Windows) / .a(Linux)编译时直接打包进程序单一程序使用
动态库.dll(Windows) / .so(Linux)编译时链接,运行时加载模块插件、共享使用

二、构建静态库的写法(默认就是 STATIC)

add_library(math_lib STATIC add.cpp)

表示编译出 math_lib.lib(或 .a),链接后合并进主程序

🔍 补充说明:

  • add_library(math_lib STATIC add.cpp)add_library(math_lib add.cpp) 是等价的,因为 CMake 默认库类型就是 STATIC

  • 为了提高可读性,建议只写一次;

  • 如果未来你想改成动态库,只需改为 SHARED 即可。


三、构建动态库的写法

add_library(math_lib SHARED add.cpp)

表示编译出:

  • Windows: math_lib.dll + math_lib.lib

  • Linux: libmath_lib.so

主程序运行时要能找到动态库文件才不会报错。


⚠️ Windows 下写 DLL 要加“导出宏”

✅ 修改 add.h
#pragma once

// __declspec(dllexport) / __declspec(dllimport)
#ifdef _WIN32
#  ifdef MATH_LIB_EXPORTS
#    define MATH_API __declspec(dllexport)
#  else
#    define MATH_API __declspec(dllimport)
#  endif
#else
#  define MATH_API
#endif

MATH_API int add(int a, int b);
✅ 修改 math/CMakeLists.txt
add_library(math_lib SHARED add.cpp)

target_include_directories(math_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# 告诉编译器定义 MATH_LIB_EXPORTS(用于导出符号)
target_compile_definitions(math_lib PRIVATE MATH_LIB_EXPORTS)

四、安装库和头文件(install)

你可以让项目支持:

cmake --install .

添加到 math/CMakeLists.txt

install(TARGETS math_lib
    RUNTIME DESTINATION bin     # .exe, .dll
    LIBRARY DESTINATION lib     # .so
    ARCHIVE DESTINATION lib     # .lib, .a
)

install(FILES add.h DESTINATION include)

运行安装命令:

cmake --install . --config Release

安装结果目录结构(默认 build/):

build/
└── install/
    ├── bin/
    │   └── math_lib.dll
    ├── lib/
    │   └── math_lib.lib
    └── include/
        └── add.h

你也可以设置安装目录:

cmake .. -DCMAKE_INSTALL_PREFIX=D:/MyLibs

五、主程序如何使用你安装的库?

在其他项目中你可以这样使用:

include_directories(D:/MyLibs/include)
link_directories(D:/MyLibs/lib)
target_link_libraries(app math_lib)

(更推荐方法我们后面会用 find_package() 实现)


✅ 小测验

  1. STATIC vs SHARED 区别是?

    ✅ 静态库会被编译进程序,动态库需要运行时加载

  2. Windows 下写 DLL 为什么要加宏?

    ✅ 因为导出/导入函数需要 __declspec(dllexport/import) 来告诉链接器

  3. install() 的作用是?

    ✅ 把库、头文件、执行文件拷贝到标准结构,供后续其他项目复用

以下是一个完整演示项目,包含:

  • 静态库和动态库的构建;

  • 安装规则(头文件、库);

  • 主程序调用库;

  • 所有文件都加上详细注释。


✅ 项目结构如下(推荐创建名为 math_demo_project):

math_demo_project/
├── CMakeLists.txt             # 主工程
├── main.cpp                   # 主程序
└── math/                      # 子模块(库)
    ├── CMakeLists.txt
    ├── add.h
    └── add.cpp

📄 main.cpp(主程序)

#include <iostream>
#include "add.h"

int main() {
    int x = 10, y = 20;
    std::cout << x << " + " << y << " = " << add(x, y) << std::endl;
    return 0;
}

📄 math/add.h(头文件,带导出宏)

#pragma once

// 支持 Windows 动态库导入导出
#ifdef _WIN32
#  ifdef MATH_LIB_EXPORTS
#    define MATH_API __declspec(dllexport)
#  else
#    define MATH_API __declspec(dllimport)
#  endif
#else
#  define MATH_API
#endif

// 导出函数
MATH_API int add(int a, int b);

📄 math/add.cpp(库实现)

#include "add.h"

int add(int a, int b) {
    return a + b;
}

📘 math/CMakeLists.txt(构建静态库和动态库)

# 构建一个动态库
add_library(math_shared SHARED add.cpp)
target_include_directories(math_shared PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(math_shared PRIVATE MATH_LIB_EXPORTS)

# 构建一个静态库
add_library(math_static STATIC add.cpp)
target_include_directories(math_static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

# 安装规则(头文件 + 库文件)
install(TARGETS math_shared math_static
    RUNTIME DESTINATION bin         # .dll/.exe (Windows)
    LIBRARY DESTINATION lib         # .so       (Linux/macOS)
    ARCHIVE DESTINATION lib         # .lib/.a   (Windows, Linux)
)

install(FILES add.h DESTINATION include)

📘 顶层 CMakeLists.txt(主项目)

cmake_minimum_required(VERSION 3.10)
project(MathDemo LANGUAGES CXX)

# 添加子模块(库)
add_subdirectory(math)

# 创建主程序
add_executable(main_app main.cpp)
target_compile_features(main_app PRIVATE cxx_std_17)

# 使用静态库或动态库:
# 任选一个链接(不建议两个都连)

target_link_libraries(main_app PRIVATE math_shared)
# target_link_libraries(main_app PRIVATE math_static)

🔨 编译 + 安装流程(命令行)

# Step 1: 创建构建目录
mkdir build
cd build

# Step 2: 配置项目(推荐使用 VS 或者 MinGW)
cmake .. -G "Visual Studio 17 2022" -DCMAKE_INSTALL_PREFIX=install

# Step 3: 构建 Release 模式
cmake --build . --config Release

# Step 4: 安装库文件和头文件
cmake --install . --config Release

✅ 安装结果目录(build/install):

install/
├── bin/
│   └── math_shared.dll
├── lib/
│   ├── math_shared.lib
│   └── math_static.lib
└── include/
    └── add.h

💡 使用建议

  • 默认链接动态库 math_shared(你也可以切换到 math_static

  • 若用的是 math_shared.dll程序运行时要和 .dll 在同目录

  • 使用 install() 后,可以在其他项目中方便复用这个库


⏮️ 上一课回顾:【CMake基础入门】第五课:拆分模块与使用 add_subdirectory() 构建子目录项目

⏭️ 下一课预告:【CMake基础入门】第七课:查找并使用第三方库(以 find_package() 为核心)

下一课将非常关键,我们将讲解:

  • 如何使用系统或 vcpkg / conan 安装的库

  • 使用 find_package() 找到并连接这些库

  • target 方式的现代写法(target_link_libraries

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奇异果冻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值