CMake 教程(二)添加库

目录

  • 一、实例一——创建库
    • 1、add_library
    • 2、target_include_directories()、target_link_libraries()
      • 2.1 target_include_directories()
      • 2.2 target_link_libraries()
    • 3、实例操作
  • 二、实例二——添加选项
    • 1、option()
    • 2、实例操作


在第一节 CMake 教程(一)初识 CMake 中,我们已经了解和实现了通过 CMake 来创建一个基本项目。本节我们将通过两个实例来学习如何在项目中创建和使用库。

一、实例一——创建库

1、add_library

要在 CMake 中添加库,就需要使用 add_library 命令来指定哪些源文件应组成库。

add_library(<name> [<type>] [EXCLUDE_FROM_ALL] <sources>...)

其作用为:添加一个名为 <name> 的库目标,该目标要从命令调用中列出的源文件构建。

参数说明:

  • <name> 对应于逻辑目标名称,并且在项目中必须是全局唯一的。构建的库的实际文件名是根据本机平台的约定(例如 lib<name>.a<name>.lib)构建的。
  • 可选的 <type> 指定要创建的库的类型:
    • STATIC:链接其他目标时使用的目标文件存档。
    • SHARED:一个动态库,可以由其他目标链接并在运行时加载。
    • MODULE:一个插件,它不能被其他目标链接,但可以在运行时使用类似 dlopen 的功能动态加载。

如果未给出 <type>,则默认值为 STATICSHARED

2、target_include_directories()、target_link_libraries()

我们可以使用一个或多个子目录来组织项目,而不是将所有源文件放在一个目录中。在这种情况下,我们将专门为我们的库创建一个子目录。在这里,我们可以添加新的 CMakeLists.txt 文件和一个或多个源文件。在顶级 CMakeLists.txt 文件中,我们将使用 add_subdirectory() 命令将子目录添加到构建中。

创建库后,它通过 target_include_directories()target_link_libraries() 连接到我们的可执行目标。

2.1 target_include_directories()

target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]<INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

指定编译给定目标(例如可执行文件、库等)时要使用的包含目录。命名的 <target> 必须由 add_executable()add_library() 等命令创建,并且不能是 ALIAS 目标。

  • target:目标名称,可以是一个可执行文件、静态库或动态库的名称。
  • SYSTEM:可选参数,指定包含目录是否应被视为系统目录。表示编译器不会产生警告。
  • [AFTER|BEFORE]:可选参数:
    • BEFORE:参数用于将包含目录添加到已有的包含目录之前,即在搜索其他包含目录之前搜索指定的目录。
    • AFTER:参数用于将包含目录添加到已有的包含目录之后,即在搜索其他包含目录之后搜索指定的目录。
  • <INTERFACE|PUBLIC|PRIVATE>:可选参数,指定添加的包含目录的属性。
    • INTERFACE:目标的接口包含目录,这意味着只有依赖该目标的其他目标才能看到这个包含目录。对于依赖该目标的目标来说,这个包含目录会像是它自己的接口一样可见。
    • PUBLIC:目标的公共包含目录,这意味着该目标及依赖它的其他目标都可以看到这个包含目录。
    • PRIVATE:目标的私有包含目录,只有该目标自身才可见这个包含目录。
  • item1...:需要添加的包含目录。

2.2 target_link_libraries()

target_link_libraries(<target> ... <item>... ...)

target_link_libraries() 命令用于为目标添加链接的库。

  • <target>:表示要添加库的目标,可以是一个目标名称或者一个目标别名。
  • <item>:表示要链接的库的名称,可以是一个目标名称、一个目标别名、一个链接库或者一个链接库的路径。

target_link_libraries 命令将目标与指定的库进行链接。链接库可以是静态库(.a.lib 等)或者动态库(.so.dll 等)。这个命令还可以用于链接其他目标,将目标与目标进行依赖关系的建立。

CMake 会自动获取库的路径和链接依赖关系,因此在使用 target_link_libraries() 命令时,不需要完整的库文件路径。

3、实例操作

接下来,我们尝试向项目中添加一个库,库中包含我们自己实现的用于计算平方的的实现。然后,让可执行文件可以使用这个库,而不是使用编译器提供的标准库函数。

我们把将要实现的库放在 lib 目录下的 my_sqrt.cmy_sqrt.h,并实现一个简单的平方函数:

// my_sqrt.h
#ifndef __MY_SQRT_H
#define __MY_SQRT_Hint my_sqrt(int a);#endif /* __MY_SQRT_H */// my_sqrt.c
#include <stdio.h>
#include "my_sqrt.h"int my_sqrt(int a)
{return (a * a);
}

然后在 math_func.cmath_func.h 文件中封装一下:

// math_func.c
#include <stdio.h>
#include "math_func.h"
#include "my_sqrt.h"int m_sqrt(int a)
{return my_sqrt(a);
}// math_func.h
#ifndef __MATH_FUNC_H
#define __MATH_FUNC_Hint m_func(int a);#endif

然后实现这个子目录下的 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.16)project(my_lib)add_library(MYSQRT math_func.c my_sqrt.c)

然后执行命令 cmake .

子目录的工作就完成了。然后是主目录:

main.c 文件中简单地调用刚才我们实现的函数:

// main.c
#include <stdio.h>
#include <stdlib.h>
#include "my_sqrt.h"int main(int argc, char *argv[])
{if (argc < 1 || argc > 3) {perror("argument err!");exit(-1);}int a = atoi(argv[1]);int b = m_sqrt(a);printf("result is %d\n", b);return 0;
}

然后完成 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.16)add_executable(test02 main.c)project(test02 VERSION 1.1)add_subdirectory(lib)target_link_libraries(test02 PUBLIC MYSQRT)target_include_directories(test02 PUBLIC"${PROJECT_BINARY_DIR}""${PROJECT_SOURCE_DIR}/lib")

注意,对应的库名和目录名一定要对应,否则会找不到库

然后执行 cmake --build .

大功告成:

二、实例二——添加选项

现在让我们在 MYSQRT 库中添加一个选项,允许开发人员选择自定义平方根实现或内置标准实现。虽然对于本教程来说,确实没有必要这样做,但对于较大的项目来说,这种情况很常见。

1、option()

CMake 可以使用 option() 命令来做到这一点。这为用户提供了一个变量,他们可以在配置 cmake 版本时更改该变量。此设置将存储在缓存中,因此用户无需在每次在 build 目录上运行 CMake 时都设置该值。

option(<variable> "<help_text>" [value])

作用:提供用户可以选择选择的布尔选项。

如果未提供初始 <value>,则布尔值 OFF 为默认值。如果 <variable> 已设置为普通变量或缓存变量,则该命令不执行任何操作。

2、实例操作

首先修改 lib 子目录下的 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.16)project(my_lib)LINK_LIBRARIES(m)add_library(MYSQRT math_func.c)option(USE_MYMATH "Use projectsauron provided math implementation" ON)if (USE_MYMATH)target_compile_definitions(MYSQRT PRIVATE "USE_MYMATH")add_library(SqrtLibrary STATICmy_sqrt.c)target_link_libraries(MYSQRT PRIVATE SqrtLibrary)
endif()

注意,因为待会儿的 C 文件中要使用到 C 标准库中的 math.h 头文件,所以要连接 math 库:LINK_LIBRARIES(m)

option 添加一个选项 USE_MYMATH。此选项将显示在 cmake-guiccmake 中,默认值为 ON,用户可以更改该默认值。

至于下面的语句,请看:如果 USE_MYMATH 为 OFF,则不会使用 mysqrt.c,但仍会对其进行编译,因为 MYSQRT 目标在源下列出了 mysqrt.c

有几种方法可以解决这个问题。第一个选项是使用 target_sources()USE_MYMATH 块中添加 mysqrt.c。另一种选择是在 USE_MYMATH 块中创建一个额外的库,该库负责编译 mysqrt.c。在这里中,我们采取的是后面那种方法。

math_func.c 文件修改如下:

#include <stdio.h>
#include "math_func.h"#ifdef USE_MYMATH#include "my_sqrt.h"
#else#include "math.h"
#endifint m_sqrt(int a)
{
#ifdef USE_MYMATHprintf("use my sqrt!\n");return my_sqrt(a);
#elseprintf("use std sqrt!\n");return sqrt(a);
#endif
}

这里通过 printf,可以验证我们的结果是否正确。

因为 USE_MYMATH 默认是 ON,所以编译好后,使用的仍是我们自己实现的函数:

重新执行下面的语句即可:

cmake ../test02 -DUSE_MYMATH=OFF
cmake --build .


现在使用的是标准库。

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

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

相关文章

学习笔记(202410)

课程&#xff1a;Generative AI for Software Development 链接&#xff1a;吴恩达同步最新AI专业课&#xff0c;第54讲&#xff1a;用人工智能做软件开发--Generative AI for Software Development_哔哩哔哩_bilibili 时间&#xff1a;2024-10-12 至 概述&#xff1a;使用C…

ES-入门-javaApi-文档-新增-删除

新增指定索引的文档数据的代码如下&#xff1a; package com.atgulgu.es.test;import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.HttpHost; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRe…

学习笔记——交换——STP(生成树)简介

一、技术背景 1、生成树技术背景 交换机单线路组网&#xff0c;存在单点故障(上左图)&#xff0c;上行线路及设备都不具备冗余性&#xff0c;一旦链路或上行设备发生故障&#xff0c;业务将会中断。 为了使得网络更加健壮、更具有冗余性&#xff0c;将拓扑修改为(上右图)接入…

网络学习笔记

一、网络的结构与功能 网络的鲁棒性与抗毁性 如果在移走少量节点后网络中的绝大部分节点仍然是连通的&#xff0c;那么就该网络的连通性对节点故障具有鲁棒性 网络上的动力学 动力系统&#xff1a;自旋、振子或混沌的同步、可激发系统 传播过程&#xff1a;信息传播与拥堵…

ChatGPT01-preivew体验报告:内置思维链和多个llm组合出的COT有啥区别呢?丹田与练气+中学生物理奥赛题测试,名不虚传还是名副其实?

一个月前&#xff0c;o1发布的时候&#xff0c;我写了篇文章介绍 逻辑推理能力堪比博士生&#xff0c;OpenAI发布全新AI模型系列&#xff1a; o1 - 大模型或许进入新阶段&#xff0c;还翻译了官方的介绍 解密OpenAI o1是如何让LLMs获得逻辑推理能力的 - CoT * RL&#xff0c;也…

代码复现(五):GCPANet

文章目录 net.py1.class Bottleneck&#xff1a;残差块2.class ResNet&#xff1a;特征提取3.class SRM&#xff1a;SR模块4.class FAM&#xff1a;FIA模块5.class CA&#xff1a;GCF模块6.class SA&#xff1a;HA模块7.class GCPANet&#xff1a;网络架构 train.pytest.py 论文…

快速上手C语言【下】(非常详细!!!)

目录 1. 指针 1.1 指针是什么 1.2 指针类型 1.2.1 指针-整数 1.2.2 指针解引用 1.3 const修饰 1.4 字符指针 1.5 指针-指针 1.6 二级指针 2. 数组 2.1 定义和初始化 2.2 下标引用操作符[ ] 2.3 二维数组 2.4 终极测试 3. 函数 3.1 声明和定义 3.2 传值调用…

【Python爬虫实战】深入解析BeautifulSoup4的强大功能与用法

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、BeautifulSoup4的介绍和安装 &#xff08;一&#xff09;基本功能和特点…

Servlet[springmvc]的Servlet.init()引发异常

报错&#xff1a; 原因之一&#xff1a; web.xml配置文件中监听器导入依赖项错误

新颖的 setTimeout() 替代方案

在前端开发中&#xff0c;长时间运行的JavaScript任务一直是一个棘手的问题。它们会导致页面无响应&#xff0c;影响用户体验。传统上&#xff0c;开发者使用setTimeout()来分割长任务&#xff0c;但这种方法存在明显的缺陷。最近&#xff0c;Chrome 129引入了一种新的、更高效…

如何搭建激光稳频的闭环控制系统

半导体激光器稳频简介 简介 窄线宽连续激光器广泛应用于原子、分子以及物理光学领域&#xff0c;在精密测量设备中有着举足轻重的作用。那些并不带有波长稳频技术的激光器&#xff0c;其短时间稳定性不适合很多应用。本文档将会给您介绍一种简单而强大的主动稳频技术&#xff0…

不收费的数据恢复工具有哪些好用?快来看这五款:

大家好&#xff0c;今天我来跟大家分享一下使用不收费数据恢复软件的一些心得和体验&#xff1b;数据丢失是一件非常让人头疼的事情&#xff0c;尤其是对于那些重要文件来说&#xff1b;幸好&#xff0c;现在市面上有不少不收费的数据恢复软件可以帮助我们找回丢失的数据。接下…

【C++笔试强训】如何成为算法糕手Day11

学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 目录 游游的水果大礼包 思路 代码实现&#xff1a; 买卖股票的最好时机(二) 思路&#xff1a; 代码实现&#xff1a; 倒置字符串 思路&#xff1a; 代码实现&#xf…

101、QT摄像头录制视频问题

视频和音频录制类QMediaRecorder QMediaRecorder 通过摄像头和音频输入设备进行录像。 注意: 使用Qt多媒体模块的摄像头相关类无法在Windows平台上进行视频录制&#xff0c;只能进行静态图片抓取但是在Linux平台上可以实现静态图片抓取和视频录制。 Qt多媒体模块的功能实现是依…

React远程组件

什么是远程组件&#xff1f; 远程组件指的是从远程服务器动态加载的组件&#xff0c;这些组件可以是React、Vue等框架的组件。 为什么需要远程组件 本质上就是为了解决复用问题&#xff0c;那引出新的问题有几种公共项目代码复用方式&#xff1f; Git仓库 将公共代码单独抽…

CTFHUB技能树之XSS——DOM反射

开启靶场&#xff0c;打开链接&#xff1a; 直接指明是DOM反射型的XSS漏洞 右键查看页面源代码&#xff0c;Ctrl F关键词”CTFHub is very“&#xff1a; 可以看到存在xss漏洞 不过得先闭合一下&#xff1a; 闭合例子如下&#xff1a; ;</sCrIpT><sCRiPt sRC//xs.pe/…

YOLOv11改进-卷积-空间和通道重构卷积SCConv

本篇文章将介绍一个新的改进模块——SCConv&#xff08;小波空间和通道重构卷积&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。为了减少YOLOv11模型的空间和通道维度上的冗余&#xff0c;我们引入空间和通道重构卷积。首先&#xff0c;…

Java 入门基础篇15 - java构造方法以及认识新的关键字

一 今日目标 构造方法static关键字代码块math类package关键字import关键字 二 构造方法概述 2.1 构造方法描述 构造方法是一个特殊方法&#xff0c;作用是创建对象&#xff0c;对对象进行初始化。 ​ 如&#xff1a; 对对象中的成员进行初始化值 2.1 构造方法的特征 1、方…

【C语言】循环结构-for循环

循环结构&#xff1a;计算机最擅长的事情就是做简单重复的工作 通过控制循环变量&#xff0c;是否满足循环条件来调整循环次数。 for(初始化;循环条件;循环控制) {循环体; }#include <stdio.h> #include <math.h> /* 功能&#xff1a;循环结构&#xff08;for&…

前端开发攻略---使用ocr识别图片进行文字提取功能

1、引入资源 通过链接引用 <script src"https://cdn.bootcdn.net/ajax/libs/tesseract.js/5.1.0/tesseract.min.js"></script> npm或其他方式下载 npm i tesseract 2、示例 <!DOCTYPE html> <html lang"en"><head><meta…