CMake入门教程【核心篇】添加库(add_library)

在这里插入图片描述

😈「CSDN主页」:传送门
😈「Bilibil首页」:传送门
😈「本文的内容」:CMake入门教程
😈「动动你的小手」点赞👍收藏⭐️评论📝


文章目录

  • 1. 基本用法
  • 2.STATIC 、SHARED 、 MODULE基本用法
    • 2.1 创建静态库
    • 2.2 创建共享库
    • 2.3 创建模块库
  • 3. 设置库的属性
    • 4. 安装库
    • 5. 链接其他库
    • 6. 使用别名
    • 7. 管理大型项目
  • 8.代码示例
    • 8.1完整示例MODULE
    • 8.2完整示例SHARED
    • 8.3完整示例STATIC
    • 8.4例子分析STATIC 、SHARED、MODULE分析
  • 9. 结论

在CMake中,add_library命令是用于定义库(library)的关键命令。库可以是静态的(static),动态的(shared),或者是模块库。本节教程将深入探讨如何在CMake中使用add_library命令来创建不同类型的库。

1. 基本用法

add_library命令用于创建一个库。基本语法如下:

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
  • <name>:库的名称。
  • STATICSHAREDMODULE:指定库的类型。如果不指定,默认创建的是静态库(STATIC)。
  • EXCLUDE_FROM_ALL:如果设置,这个库不会被默认构建,除非有其他目标依赖它。
  • source1 [source2 ...]:库的源文件。

2.STATIC 、SHARED 、 MODULE基本用法

2.1 创建静态库

静态库(.a.lib文件)在编译时被完全复制到最终的可执行文件中。

add_library(my_static_lib STATIC source1.cpp source2.cpp)

2.2 创建共享库

共享库(.so.dll.dylib)在运行时被动态加载。

add_library(my_shared_lib SHARED source1.cpp source2.cpp)

2.3 创建模块库

模块库(通常用于插件)在运行时可以被动态加载,但不会被链接到其他目标中。

add_library(my_module_lib MODULE source1.cpp source2.cpp)

3. 设置库的属性

使用target_*命令设置库的属性,例如包含目录、编译定义等。

target_include_directories(my_shared_lib PUBLIC include)
target_compile_definitions(my_shared_lib PRIVATE MY_SHARED_LIB_BUILD)

4. 安装库

使用install命令来指定库安装的规则。

install(TARGETS my_shared_lib DESTINATION lib)

5. 链接其他库

使用target_link_libraries将其他库链接到您创建的库。

target_link_libraries(my_shared_lib another_library)

6. 使用别名

为库创建别名,使其可以在项目中以一致的方式被引用。

add_library(my_lib_alias ALIAS my_shared_lib)

7. 管理大型项目

对于大型项目,合理组织多个库文件可以提高项目的模块化和可维护性。考虑将功能相关的类和函数分组到不同的库中。

8.代码示例

8.1完整示例MODULE

了创建一个跨平台的示例,我们需要编写一个可以在Windows和类Unix系统(如Linux和macOS)上运行的程序。为此,我们将使用预处理器指令来区分平台并使用相应的动态加载库API。下面的示例展示了如何在CMake中创建一个模块库,并在主程序中根据操作系统动态加载这个库。

  • 项目结构
cssCopy codeMyProject/
├── CMakeLists.txt
└── src/├── Plugin.cpp└── main.cpp
  • Plugin.cpp

模块库的实现文件,位于src/目录下。

cppCopy code// Plugin.cpp
#include <iostream>extern "C" void loadPlugin() {std::cout << "Plugin Loaded!" << std::endl;
}
  • main.cpp

主程序的实现文件,用于动态加载模块库。

// main.cpp
#include <iostream>#if defined(_WIN32)#include <windows.h>
#else#include <dlfcn.h>
#endifint main() {#if defined(_WIN32)HMODULE hModule = LoadLibrary(TEXT("MyPlugin.dll"));if (!hModule) {std::cerr << "Cannot load library: " << GetLastError() << '\n';return 1;}typedef void (*Func)();Func loadPlugin = (Func) GetProcAddress(hModule, "loadPlugin");#elsevoid* handle = dlopen("./libMyPlugin.so", RTLD_LAZY);if (!handle) {std::cerr << "Cannot load library: " << dlerror() << '\n';return 1;}typedef void (*Func)();dlerror(); // 清除现有的错误Func loadPlugin = (Func) dlsym(handle, "loadPlugin");const char* dlsym_error = dlerror();if (dlsym_error) {std::cerr << "Cannot load symbol 'loadPlugin': " << dlsym_error << '\n';dlclose(handle);return 1;}#endif// 使用库loadPlugin();// 关闭库#if defined(_WIN32)FreeLibrary(hModule);#elsedlclose(handle);#endifreturn 0;
}
  • CMakeLists.txt

CMake的配置文件,用于构建整个项目。

cmake_minimum_required(VERSION 3.10)project(MyPluginProject)# 创建模块库
add_library(MyPlugin MODULE src/Plugin.cpp)# 创建可执行文件
add_executable(MyExecutable src/main.cpp)# 设置输出目录(可选)
set_target_properties(MyPlugin PROPERTIESLIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
)

在这个示例中,我们首先创建了一个名为MyPlugin的模块库,然后创建了一个名为MyExecutable的可执行文件。main.cpp中的代码根据编译平台选择正确的动态加载方法。

这个跨平台的示例演示了如何在CMake中创建和使用模块库,并展示了如何在Windows和类Unix系统上动态加载和使用这种类型的库

8.2完整示例SHARED

  • 项目结构

设想我们的项目结构如下:

cssCopy codeMyProject/
├── CMakeLists.txt
├── include/
│   └── MySharedLib.h
└── src/├── MySharedLib.cpp└── main.cpp
  • MySharedLib.h

这是共享库的头文件,位于include/目录下。

cppCopy code// MySharedLib.h
#ifndef MYSHAREDLIB_H
#define MYSHAREDLIB_Hvoid printHelloShared();#endif // MYSHAREDLIB_H
  • MySharedLib.cpp

这是共享库的实现文件,位于src/目录下。

cppCopy code// MySharedLib.cpp
#include "MySharedLib.h"
#include <iostream>void printHelloShared() {std::cout << "Hello from MySharedLib!" << std::endl;
}
  • main.cpp

这是主程序的实现文件,也位于src/目录下。

cppCopy code// main.cpp
#include "MySharedLib.h"int main() {printHelloShared();return 0;
}
  • CMakeLists.txt

这是CMake的配置文件,用于构建整个项目。

cmakeCopy codecmake_minimum_required(VERSION 3.10)# 设置项目名称
project(MyProject)# 指定包含目录
include_directories(include)# 添加共享库"MySharedLib"
add_library(MySharedLib SHARED src/MySharedLib.cpp)# 创建可执行文件
add_executable(MyExecutable src/main.cpp)# 链接共享库到可执行文件
target_link_libraries(MyExecutable MySharedLib)

在这个例子中,我们首先设置了项目名称和包含目录。接着,我们使用add_library命令添加了一个名为MySharedLib的共享库,并指定了它的源文件。然后,我们用add_executable命令创建了一个名为MyExecutable的可执行文件,并使用target_link_libraries命令将MySharedLib共享库链接到这个可执行文件上。

这个完整的示例展示了如何在CMake中创建和使用共享库,以及如何在应用程序中链接和使用这种类型的库。

8.3完整示例STATIC

  • 项目结构
MyProject/
├── CMakeLists.txt
├── include/
│   └── MyStaticLib.h
└── src/├── MyStaticLib.cpp└── main.cpp
  • MyStaticLib.h

这是静态库的头文件,位于include/目录下。

cppCopy code// MyStaticLib.h
#ifndef MYSTATICLIB_H
#define MYSTATICLIB_Hvoid printHelloStatic();#endif // MYSTATICLIB_H
  • MyStaticLib.cpp

这是静态库的实现文件,位于src/目录下。

cppCopy code// MyStaticLib.cpp
#include "MyStaticLib.h"
#include <iostream>void printHelloStatic() {std::cout << "Hello from MyStaticLib!" << std::endl;
}
  • main.cpp

这是主程序的实现文件,也位于src/目录下。

cppCopy code// main.cpp
#include "MyStaticLib.h"int main() {printHelloStatic();return 0;
}
  • CMakeLists.txt

这是CMake的配置文件,用于构建整个项目。

 codecmake_minimum_required(VERSION 3.10)# 设置项目名称
project(MyProject)# 指定包含目录
include_directories(include)# 添加静态库"MyStaticLib"
add_library(MyStaticLib STATIC src/MyStaticLib.cpp)# 创建可执行文件
add_executable(MyExecutable src/main.cpp)# 链接静态库到可执行文件
target_link_libraries(MyExecutable MyStaticLib)

在这个示例中,我们首先设置了项目名称和包含目录。接着,我们使用add_library命令添加了一个名为MyStaticLib的静态库,并指定了它的源文件。然后,我们用add_executable命令创建了一个名为MyExecutable的可执行文件,并使用target_link_libraries命令将MyStaticLib静态库链接到这个可执行文件上。

这个完整的示例展示了如何在CMake中创建和使用静态库,以及如何在应用程序中链接和使用这种类型的库。

8.4例子分析STATIC 、SHARED、MODULE分析

创建和使用不同类型的库(静态库、共享库、模块库)是CMake中的一个核心概念。以下是对之前提到的三种类型库的创建和使用的总结:

1. 静态库(STATIC)

  • 定义:静态库是编译时链接到可执行文件中的库,不需要在运行时动态加载。
  • 优点:简化部署(不需要确保共享库在运行时可用),提高运行时性能(减少动态链接的开销)。
  • 使用场景:适用于不需要共享代码的情况,以及对性能有较高要求的场景。

2. 共享库(SHARED)

  • 定义:共享库是在运行时被动态加载的库,允许代码在多个程序之间共享。
  • 优点:节省内存(同一共享库的单个副本可被多个程序使用),易于更新(更新共享库而无需重新编译使用它的程序)。
  • 使用场景:适用于需要跨多个程序共享代码的场景。

3. 模块库(MODULE)

  • 定义:模块库通常用于实现插件或动态加载模块,它们在构建时不链接到其他目标,但可以在运行时动态加载。
  • 优点:灵活性高(可随需加载或卸载),有助于减小应用程序的初始内存占用。
  • 使用场景:适用于插件系统或需要可拓展性的应用程序。

在实际项目中,选择哪种类型的库取决于项目的需求和设计目标。静态库适合内部紧密耦合的组件,共享库适合于需要跨多个应用共享的代码,而模块库则是为动态拓展性而设计。理解这些不同类型的库以及它们的用途和优势,可以帮助开发者更有效地构建和管理CMake项目

9. 结论

通过有效地使用add_library,您可以在CMake项目中灵活地创建和管理各种类型的库。这不仅有助于提高项目的结构清晰度,还可以在不同的场景下为您的应用或库提供适当的链接和加载机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595297.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

印刷企业如何快速上线MES管理系统解决方案

随着科技的不断发展&#xff0c;印刷行业正面临着前所未有的挑战与机遇。为了提高生产效率、降低成本、提升企业竞争力&#xff0c;许多印刷企业开始引入MES管理系统解决方案。然而&#xff0c;对于很多企业来说&#xff0c;如何快速、有效地上线MES管理系统却是一个难题。本文…

从门店客流看全国消费趋势,6张图展现元旦假期客流增长趋势

在刚刚过去的2024年元旦小长假&#xff0c;全国各地迎来了新年的第一波消费热潮。悠络客平台数据显示&#xff0c;2024元旦期间&#xff0c;零售、餐饮、教育等行业门店日均客流均呈现大幅上涨趋势&#xff0c;迎来了客流高峰。 这也是全国消费复苏的缩影&#xff0c;从门店客流…

C++/CLI——3继承与值类型、操作符重载与异常

C/CLI——3继承与值类型、操作符重载与异常 继承 C/cli中的继承用法基本和C#中的用法相同&#xff0c;只不过要注意以下几点&#xff1a; 标准的C在继承符号:之后&#xff0c;基类名称之前添加关键字public/protected/private&#xff0c;但是C/CLI只支持public&#xff0c;…

前端面试--moka

nextTick: 异步渲染&#xff0c;DOM异步渲染完毕后执行。 批量渲染。 vite为什么比webpack快&#xff1f; webpack把所有文件build一次&#xff0c;从入口文件进去&#xff0c;将所有文件编译为一个或多个单独的js文件&#xff0c;无论模块是否执行&#xff0c;都要编译和打…

阿里云服务器地域怎么选择?哪个地域好?

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

基于决策树、随机森林和层次聚类对帕尔默企鹅数据分析

作者&#xff1a;i阿极 作者简介&#xff1a;数据分析领域优质创作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&#x1f4d2;关注哦&#x…

大数据应用安全策略包括什么

大数据应用安全策略是为了保障大数据应用中的数据安全而采取的一系列措施&#xff0c;其重要性不容小觑。以下是大数据应用安全策略所包含的主要内容&#xff1a; 一、数据加密与安全存储 数据加密&#xff1a;对于敏感数据&#xff0c;应采用加密技术进行保护&#xff0c;包括…

Ubuntu22.04配置静态ip

在 Ubuntu 22.04 中配置静态 IP 的步骤如下&#xff1a; 打开终端&#xff0c;并以管理员身份运行。 编辑网络配置文件。输入以下命令并按 Enter 键&#xff1a; sudo nano /etc/netplan/00-installer-config.yaml在打开的文件中&#xff0c;找到与你要设置静态 IP 的网络接口…

普中STM32-PZ6806L开发板(资料收集...)

简介 逐渐收集一些开发过程中使用到的文档资料数据手册 DS18B20 数据手册 DS18B20 Datasheet 开发文档 STM32F1各种文档 https://www.st.com/en/embedded-software/stm32cubef1.html#documentation HAL库文档开发文档 你使用的HAL文档, 在STM32CubeMX生成过程的最下面有…

『开发工具篇』- 配置 gradle 等相关依赖镜像源

『开发工具篇』- 配置 gradle 等相关依赖镜像源 1.更换gradle下载源2. 配置setting.gradlekts文件gradle文件 1.更换gradle下载源 使用腾讯云的镜像库https://mirrors.cloud.tencent.com/gradle/ gradle-x.x-all.zip&#xff1a;编译后的二进制发布版以及源码和文档gradle-x.…

【MySQL】CRUD,常见函数及unionunion

目录 一 CRUD 查询 新增数据 修改数据 删除数据 二 常见函数 ① 字符函数 ② 数字函数 ③ 日期函数 ④ 流程控制函数 ⑤ 聚合函数 三 union&union 含义 语法 一 CRUD 条件查询执行顺序&#xff1a;where(条件) group by(分组) having(筛选) order by(排序)…

chrome面向服务的架构SOA

chrome 浏览器面向服务的架构 原来的各种模块会被重构成独立的服务&#xff0c;每个服务都可以独在独立的进程中运行&#xff0c;可以在浏览器的任务管理器中看到各种服务。 "面向服务的架构"&#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09;…

Kubernetes Gateway API V1.0:您应该切换吗?

自Kubernetes Gateway API 发布 v1.0以来已经过去两个多月了&#xff0c;这标志着其一些关键 API 已经进入普遍可用状态。 去年&#xff0c;当网关 API升级为测试版时&#xff0c;我曾写过有关该 API的文章&#xff0c;但一年后&#xff0c;问题仍然存在。您是否应该从 Ingres…

理德外汇:通胀风险下降,2024年适合降息

新近公布的会议纪要显示&#xff0c;上月的货币政策会议上&#xff0c;美联储决策者对遏制住高通(137.6, -2.63, -1.88%)胀显得更有信心&#xff0c;认为通胀上行的风险削减&#xff0c;预计未来一年可能适合降息&#xff0c;不过&#xff0c;利率路径还很不确定。 美联储货币政…

数据结构OJ实验11-拓扑排序与最短路径

A. DS图—图的最短路径&#xff08;无框架&#xff09; 题目描述 给出一个图的邻接矩阵&#xff0c;输入顶点v&#xff0c;用迪杰斯特拉算法求顶点v到其它顶点的最短路径。 输入 第一行输入t&#xff0c;表示有t个测试实例 第二行输入顶点数n和n个顶点信息 第三行起&…

自由DIY预约小程序源码系统:适用于任何行业+自由DIY你的界面布局+全新升级的UI+多用户系统 带安装部署教程

随着移动互联网的普及&#xff0c;预约服务逐渐成为人们日常生活的一部分。从家政服务、医疗挂号到汽车保养&#xff0c;预约已经渗透到各个行业。然而&#xff0c;市面上的预约小程序大多功能单一&#xff0c;界面老旧&#xff0c;无法满足商家和用户的个性化需求。今天来给大…

ipvsadm命令详解

ipvsadm命令详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨一个在Linux系统网络管理中极具威力的命令——ipvsadm&#xff0c;通过详细解析…

整合【事务】

目录 1、读未提交&#xff08;脏读&#xff09; 2、读已提交&#xff08;不可重复读&#xff09; 3、可重复读&#xff08;幻读&#xff09; 4、Navicat中模拟开启、提交、回滚事务 1、读未提交&#xff08;脏读&#xff09; 允许一个事务读取其他事务未提交的修改 2、读已…

异步优势演员-评论家算法 A3C

异步优势演员-评论家算法 A3C 异步优势演员-评论家算法 A3C网络结构并行步骤 异步优势演员-评论家算法 A3C A3C 在 A2C 基础上&#xff0c;增加了并行训练&#xff08;异步&#xff09;来提高效率。 网络结构 A2C&#xff1a; A3C&#xff1a; 在这两张图之间&#xff0c;…

UI自动化Selenium 页面窗口window定位切换

Selenium自动化&#xff0c;在操作元素时&#xff0c;一定是基于某个窗口这个前提&#xff1b;我们时常在操作时会出现打开新窗口的情况&#xff1b;如点击新增按钮&#xff0c;打开了新增单据的新页面窗口&#xff0c;接下来要录入单据信息时&#xff0c;必须告诉框架切换到新…