当前位置: 首页 > 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 构建系统的核心命令之一,通过灵活选择库类型和配置属性,可满足各种项目的需求。合理设计库结构和依赖关系,能显著提升项目的可维护性和跨平台兼容性。

相关文章:

  • 单例模式总结
  • Python训练营---Day35
  • 【笔记】OpenCV的学习(未完)
  • 开发者工具箱-鸿蒙颜色转换器开发笔记
  • React Native 拼音及拼音首字母搜索组件开发
  • LLM Tuning
  • OpenLayers 开发环境搭建
  • 每日c/c++题 备战蓝桥杯(洛谷P3382 三分法求极值详解)
  • 模型参数详细介绍--Profiler
  • Python如何赋能自动驾驶地图构建?从点云处理到实时导航
  • Redis持久化机制:AOF与RDB深度解析
  • 电机控制储备知识学习(五) 三项直流无刷电机(BLDC)学习(四)
  • NetSuite Emoji的应用
  • JavaScript 文件类型识别与状态图片返回系统
  • [AI]主流大模型、ChatGPTDeepseek、国内免费大模型API服务推荐(支持LangChain.js集成)
  • 开发者工具箱-鸿蒙DNS查询工具开发笔记
  • vue3 发票税率 计算
  • 汉字不仅是一种语言 还是当作艺术形式来展现
  • Python 基础语法速查手册:从入门到精通
  • 怎么开发一个网络协议模块(C语言框架)之(四) 信号量初始化
  • 做群头像的网站在线/百度24小时客服电话136
  • django网站开发视频/小红书推广方式
  • 新疆生产建设兵团教育局官方网站/目前搜索引擎排名
  • 个人网站的基本风格是/网络营销的营销策略
  • 网站建设管理制度/餐饮品牌全案策划
  • 长春网站建设机构/淘宝关键词指数查询