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>
#endif

int 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");
    #else
        void* 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);
    #else
        dlclose(handle);
    #endif
    return 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 PROPERTIES
    LIBRARY_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_H

void 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_H

void 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项目中灵活地创建和管理各种类型的库。这不仅有助于提高项目的结构清晰度,还可以在不同的场景下为您的应用或库提供适当的链接和加载机制。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python爬虫实现获取招聘信息

使用的python版本&#xff1a; 3.12.1 selenium版本&#xff1a;4.8.0 urllib版本&#xff1a;1.26.18 from selenium import webdriver from selenium.webdriver import ActionChains import timeimport re import xlwt import urllib.parsedef get_html(url):chrome_drive…

将linux的代码上传至gitte,从创建到linux命令详解

目录 1&#xff1a;创建gitte的代码仓库 1&#xff1a;登录gitte网页 https://gitee.com/ 2&#xff1a;点击导航栏的&#xff0b;号 3&#xff1a;点击新建仓库​编辑4&#xff1a;仓库配置 ​编辑5&#xff1a;复制仓库的路径 linux操作系统命令行 1&#xff1a; linux…

Hadoop集群三节点搭建(一)

一、第一台虚拟机准备 确认是可以上网&#xff0c;方便下载文件和工具&#xff0c;使用ping命令测试下 安装工具 net-tool&#xff1a;工具包集合&#xff0c;包含ifconfig等命令&#xff0c;大家可以根据自己需要按需下载 创建普通用户attest&#xff0c;并修改attest用户的密…

MO 2023 年度回顾

PART-ONE 行业态势 随着供需关系的变化&#xff0c;数据库的竞争在经历了 3 年 “百花齐放” 般的发展后&#xff0c;终于在 2023 年进入到了一个相对收拢的阶段。 2023 年&#xff0c;各个数据库厂商间很有默契地在两个方面达成了一致&#xff1a; HTAP 已经成为新一代数据…

YOLO算法入门指南:了解门槛、学习路径及其易学性

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

基于Segformer实现PCB缺陷检测(步骤 + 代码)

导 读 本文主要介绍基于Segformer实现PCB缺陷检测 &#xff0c;并给出步骤和代码。 背景介绍 PCB缺陷检测是电子制造的一个重要方面。利用Segformer等先进模型不仅可以提高准确性&#xff0c;还可以大大减少检测时间。传统方法涉及手动检查&#xff0c;无法扩展且容易出错…

k8s---声明式资源管理(yml文件)

在k8s当中支持两种声明资源的方式&#xff1a; 1、 yaml格式&#xff1a;主要用于和管理资源对象 2、 json格式&#xff1a;主要用于在API接口之间进行消息传递 声明式管理方法(yaml)文件 1、 适合对资源的修改操作 2、 声明式管理依赖于yaml文件&#xff0c;所有的内容都在y…

webapp下没有蓝点解决

解决方法&#xff1a; File->Project Structure 现在就是一个JavaWeb项目了。

WMS仓储管理系统如何优化急料处理流程

在当今快速发展的商业环境中&#xff0c;企业的运营效率和供应链管理面临着前所未有的挑战。尤其在面对急料处理这一环节时&#xff0c;许多企业都感到力不从心。为了满足生产线的连续运作、确保客户订单的及时交付&#xff0c;WMS仓储管理系统的急料处理流程优化成为了关键。本…

(17)Linux的进程阻塞进程程序替换 exec 函数簇

前言&#xff1a;本章我们讲解它的 options 参数。在讲解之前我们需要理解进程阻塞&#xff0c;然后我们重点讲解二进程程序替换&#xff0c;这是本章的重点&#xff0c;然后介绍一个进程替换函数 execl&#xff0c;通过介绍这个函数来打开突破口&#xff0c;引入进程创建的知识…

【解决复杂链式任务,打造全能助手】LangChain 大模型 打造 钢铁侠的全能助理 Jarvis

LangChain 大模型 结合 做 AutoGPT、ChatPDF 思维链 CoTLangChain模型IO&#xff1a;和大模型交互、提示词模版数据连接&#xff1a;从数据的接入、分割&#xff0c;到向量的构建、存储、搜索链&#xff1a;串联和组织&#xff0c;多个语言模型、组件记忆&#xff1a;灵魂伴侣&…

C#中使用 async await TaskCompletionSource<T>实现异步逻辑同步写

Task、async 和 await 是 C# 中用于处理异步编程的关键概念。它们一起构成了异步编程的基础。 Task Task 是表示异步操作的抽象&#xff0c;它属于 System.Threading.Tasks 命名空间。Task 可以表示已经完成的任务、正在运行的任务或者尚未开始的任务。通过 Task&#xff0c;…

算法导论复习——CHP16 贪心算法

定义 每一步都做出当前看来最优的操作。 问题引入——活动选择问题 问题描述 活动选择问题就是对给定的包含n个活动的集合S&#xff0c;在已知每个活动开始时间和结束时间的条件下&#xff0c;从中选出最多可兼容活动的子集合&#xff0c;称为最大兼容活动集合。 不失一般性&a…

【C++入门】C++内存管理

目录 前言 C/C内存分布 C内存管理方式 1. new和delete操作内置类型 快速了解与使用 2. new和delete操作自定义类型 3. operator new与operator delete 4. operator new [ ] *5.定位new 6. malloc/free和new/delete的区别 总结 前言 C作为一种面向对象的编程语言&#xff…

AI:110-基于深度学习的药物分子结构生成与预测

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

Unity ab包如何加密

「ab包」全称为 AssetBundle &#xff0c;是Unity提供的一种资源存储压缩包。其中储存了游戏的资源&#xff0c;如图片、模型、纹理、音视频、代码等文件。 由于ab包具有灵活储存、支持热更、包体较小且便于管理等优势&#xff0c;已经成为了市面上主流的游戏资源压缩方式。 …

Jmeter(七) - 从入门到精通 - 建立数据库测试计划实战<MySQL数据库>(详解教程)

1.简介 在实际工作中&#xff0c;我们经常会听到数据库的性能和稳定性等等&#xff0c;这些有时候也需要测试工程师去评估和测试&#xff0c;上一篇文章宏哥主要介绍了jmeter连接和创建数据库测试计划的过程,宏哥在文中通过示例和代码非常详细地介绍给大家&#xff0c;希望对各…

【中小型企业网络实战案例 七】配置限速

相关学习文章&#xff1a; 【中小型企业网络实战案例 一】规划、需求和基本配置 【中小型企业网络实战案例 二】配置网络互连互通【中小型企业网络实战案例 三】配置DHCP动态分配地址 【中小型企业网络实战案例 四】配置OSPF动态路由协议【中小型企业网络实战案例 五】配置可…

51单片机(STC8)-- GPIO输入输出

文章目录 I/O口相关寄存器端口数据寄存器端口模式配置寄存器&#xff08;PxM0&#xff0c;PxM1&#xff09;端口上拉电阻控制寄存器(PxPU)关于I/O的注意事项 配置I/O口I/O设置demoI/O端口模式LED控制&#xff08;I/O输出&#xff09;按键检测&#xff08;I/O输入&#xff09; S…

【模拟量采集1.2】电阻信号采集

【模拟量采集1.2】电阻信号采集 1 怎么测&#xff1f;2 测输入电阻电压即转为测模拟电压值&#xff0c;这里需要考虑选用怎样的辅助电阻&#xff1f;3 实际电路分析3.1 在不考虑 VCC-5V 电压的纹波等情况时&#xff08;理想化此时输入的 VCC 就是稳定的 5V&#xff09;3.2 若考…