当前位置: 首页 > news >正文

CMake指令:add_library()

目录

1.简介

2.库类型详解

3.高级用法

4.库属性配置

5.安装规则

6.总结


1.简介

add_library 是 CMake 中用于定义库目标的核心命令,可创建多种类型的库。以下是其详细用法、参数和应用场景:

add_library(<name> [STATIC | SHARED | MODULE | OBJECT | INTERFACE][EXCLUDE_FROM_ALL][source1] [source2 ...])
  • <name>:库的逻辑名称(如 mylib),生成的文件名为 libmylib.a(静态库)或 libmylib.so(共享库)。
  • 库类型(可选):
    • STATIC:静态库(.a/.lib)。
    • SHARED:共享库(.so/.dll)。
    • MODULE:模块库(动态加载,类似共享库但不链接)。
    • OBJECT:目标文件集合(.o/.obj,不生成库文件)。
    • INTERFACE:接口库(无编译产物,仅传递编译信息)。
  • EXCLUDE_FROM_ALL:可选参数,使该库不参与默认构建。
  • [source1] [source2] [...]:指定生成库的源文件

2.库类型详解

1. 静态库(STATIC)

add_library(mylib STATIC src/file1.cpp src/file2.cpp)
  • 特点
    • 编译为 .a(Linux)或 .lib(Windows)文件。
    • 链接时被完整复制到可执行文件中,导致文件体积增大,但运行时无需依赖外部库。
  • 适用场景:封闭系统、嵌入式开发、需要简化依赖的场景。

2.共享库(SHARED)

add_library(mylib SHARED src/file1.cpp src/file2.cpp)
  • 特点
    • 编译为 .so(Linux)或 .dll(Windows)文件。
    • 运行时动态加载,多个程序可共享同一个库,减少内存占用。
  • 适用场景:大型项目、需要动态更新库的场景。

3.模块库(MODULE)

add_library(mymodule MODULE src/module.cpp)
  • 特点
    • 类似共享库,但不直接链接到可执行文件,而是通过 dlopen()(Linux)或 LoadLibrary()(Windows)动态加载。
  • 适用场景:插件系统、动态加载扩展功能。

4.目标文件集合(OBJECT)

add_library(myobjects OBJECT src/file1.cpp src/file2.cpp)
add_executable(myapp $<TARGET_OBJECTS:myobjects> src/main.cpp)
  • 特点
    • 不生成库文件,仅编译源文件为 .o/.obj 文件。
    • 可被多个目标重复使用,减少重复编译。
  • 适用场景:大型项目中共享公共代码、优化编译时间。

5.接口库(INTERFACE)

add_library(myinterface INTERFACE)
target_include_directories(myinterface INTERFACE include/)
  • 特点
    • 无编译产物,仅用于传递编译信息(如头文件路径、编译定义)。
  • 适用场景:头文件仅库(如 Eigen)、抽象依赖关系。

3.高级用法

1. 导入现有库(IMPORTED)

add_library(external_lib SHARED IMPORTED)
set_target_properties(external_lib PROPERTIESIMPORTED_LOCATION "/path/to/libexternal.so"INTERFACE_INCLUDE_DIRECTORIES "/path/to/include"
)
  • 作用:引用外部已存在的库,避免重新编译。

2.ALIAS 别名

add_library(myproject::mylib ALIAS mylib)
  • 作用:为库创建别名,便于在子项目或导出时使用。

3.条件编译

if(WIN32)add_library(mylib STATIC src/win/file.cpp)
else()add_library(mylib STATIC src/unix/file.cpp)
endif()

4.库属性配置

使用 set_target_properties 或 target_* 命令配置库属性:

add_library(mylib SHARED src/file.cpp)# 设置版本信息
set_target_properties(mylib PROPERTIESVERSION "1.2.3"SOVERSION "1"
)# 添加头文件路径
target_include_directories(mylibPUBLIC include/       # 公开头文件(供依赖者使用)PRIVATE src/internal/ # 私有头文件(仅库内部使用)
)# 链接其他库
target_link_libraries(mylib PUBLIC pthread)

可见性控制:

  • PUBLIC:传递给链接此库的目标,并继承给依赖该目标的其他目标。
  • PRIVATE:仅用于此库自身,不传递给其他目标。
  • INTERFACE:仅用于接口库,定义使用该库所需的配置,仅传递给链接此库的目标。

示例如下:

set(THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty" CACHE PATH "third-party")
set(MINIZ_DIR "${THIRD_PARTY_DIR}/miniz-3.0.2" CACHE PATH "miniz")add_library(miniz INTERFACE)
set_target_properties(miniz PROPERTIESINTERFACE_INCLUDE_DIRECTORIES "${MINIZ_DIR}"
)

INTERFACE_INCLUDE_DIRECTORIES:

这是一个特殊的属性,用于定义使用该库时需要包含的头文件路径

  • INTERFACE 表示这些路径只传递给依赖该库的目标(即 “使用者”),而不影响库本身的编译。
  • 相比之下,PUBLIC 和 PRIVATE 属性会同时影响库本身和依赖它的目标。

与其他命令的对比,这行代码等价于:

target_include_directories(miniz INTERFACE "${MINIZ_DIR}")

两者的区别在于:

  • target_include_directories 是现代 CMake 推荐的方式,语法更简洁。
  • set_target_properties 更适合一次性设置多个属性(见下方示例)。

实际应用场景

假设 miniz 是一个头文件仅库(Header-only Library),其他模块需要包含它的头文件才能使用。通过设置 INTERFACE_INCLUDE_DIRECTORIES,可以让依赖 miniz 的目标自动获得正确的头文件路径:

# 设置 miniz 库的接口属性
add_library(miniz INTERFACE)
set_target_properties(miniz PROPERTIESINTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/third_party/miniz/include"
)# 其他目标链接 miniz 时,自动包含上述目录
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE miniz)  # 无需再手动添加 include 目录

多属性设置示例

set_target_properties 更常用于一次性设置多个属性:

set_target_properties(miniz PROPERTIESINTERFACE_INCLUDE_DIRECTORIES "${MINIZ_DIR}"  # 头文件路径INTERFACE_COMPILE_DEFINITIONS "USE_MINIZ=1"   # 编译定义INTERFACE_COMPILE_FEATURES "cxx_std_11"       # C++ 标准要求
)

5.安装规则

install(TARGETS mylibARCHIVE DESTINATION lib  # 静态库安装路径LIBRARY DESTINATION lib  # 共享库安装路径RUNTIME DESTINATION bin  # 可执行文件安装路径(仅适用于 MODULE)
)install(DIRECTORY include/ DESTINATION include)  # 安装头文件

6.总结

add_library 是 CMake 构建系统的核心命令之一,通过灵活选择库类型和配置属性,可满足各种项目的需求。合理设计库结构和依赖关系,能显著提升项目的可维护性和跨平台兼容性。

http://www.xdnf.cn/news/627985.html

相关文章:

  • 主从复制启动
  • 二叉树层序遍历6
  • C++--auto详解
  • 2025家政预约小程序开发:功能模块解析与行业解决方案
  • Cookie 与 Session
  • Adminer 连接mssql sqlserver
  • SEO长尾词优化精准布局
  • 构建Harbor私有镜像库(详细版)
  • 《BI 展示:从核心目标到未来趋势》
  • 『uniapp』uni-share 分享功能 使用例子(保姆级图文)
  • STM32上配置图像处理库时常见错误总结
  • 【IEEE 2025】低光增强KANT(使用KAN代替MLP)----论文详解与代码解析
  • Java——设计模式(Design Pattern)
  • DAY 35
  • Shell三剑客之awk
  • 全球化 2.0 | 云轴科技ZStack助力中东智慧城市高性能智能安防云平台
  • TypeScript小技巧使用as const:让类型推断更精准。
  • exti line2 interrupt 如何写中断回调
  • 数据库中表的设计规范
  • 【软考】【信息系统项目管理师】2025年5月24日考试回忆版,祝明天考试的兄弟们顺利
  • maxkey单点登录系统
  • Neo4j(二) - 使用Cypher操作Neo4j
  • iOS 直播特殊礼物特效实现方案(Swift实现,超详细!)
  • STM32F446主时钟失效时DAC输出异常现象解析与解决方案
  • AtCoder AT_abc407_d [ABC407D] Domino Covering XOR
  • 【Web前端】jQuery入门与基础(二)
  • 免费PDF工具-PDF24V9.16.0【win7专用版】
  • TypeScript基础数据类型详解总结
  • 常见的图像生成模型
  • 嵌入式开发学习日志(linux系统编程--进程(1))Day27