[C++][CMake][生成可执行文件][下]详细讲解

目录

  • 1.搜索文件
    • 1.aux_source_directory
    • 2.file
  • 2.包含头文件
  • 3.变量操作
    • 1.追加
      • 1.使用set拼接
      • 2.使用list拼接
    • 2.字符串移除
    • 3.list其他操作
  • 4.宏定义
  • 5.预定义宏


1.搜索文件

  • 如果一个项目里边的源文件很多,在编写CMakeLists.txt文件的时候不可能将项目目录的各个文件一一罗列出来,这样太麻烦也不现实
  • CMake提供了搜索文件的命令,可以使用aux_source_directory命令或者file命令

1.aux_source_directory

  • 在CMake中使用aux_source_directory命令可以查找某个路径下的所有源文件
  • 语法
    • dir:要搜索的目录
    • variable:将从dir目录下搜索到的源文件列表存储到该变量中
      aux_source_directory(< dir > < variable >)
      
  • 示例
    aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC)
    

2.file

  • file除了搜索以外还可以做其他事情
  • 语法
    • GLOB:将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中
    • GLOB_RECURSE递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中
      file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
      
  • 示例
    file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
    
  • CMAKE_CURRENT_SOURCE_DIR宏表示当前访问的CMakeLists.txt文件所在的路径

2.包含头文件

  • 在编译项目源文件的时候,很多时候都需要将源文件对应的头文件路径指定出来,这样才能保证在编译过程中编译器能够找到这些头文件,并顺利通过编译
  • 在CMake中设置要包含的目录也很简单,通过include_directories即可
  • 语法
    include_directories(<directory1> [<directory2> ...])
    

3.变量操作

1.追加

  • 有时候项目中的源文件并不一定都在同一个目录中,但是这些源文件最终却需要一起进行编译来生成最终的可执行文件或者库文件,如果通过file命令对各个目录下的源文件进行搜索,最后还需要做一个字符串拼接的操作
  • 关于字符串拼接可以使用set命令也可以使用list命令

1.使用set拼接

  • 语法
    set(变量名1 ${变量名1} ${变量名2} ...)
    
  • 本质:从第二个参数开始往后所有的字符串进行拼接,最后将结果存储到第一个参数中,如果第一个参数中原来有数据会对原数据就行覆盖
  • 示例
    cmake_minimum_required(VERSION 3.0)
    project(TEST)set(TEMP "DieSnowK")
    file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
    file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)# 追加(拼接)
    set(SRC_1 ${SRC_1} ${SRC_2} ${TEMP})
    message(STATUS "message: ${SRC_1}")
    

2.使用list拼接

  • list命令的功能比set要强大,字符串拼接只是它的其中一个功能,所以需要在它第一个参数的位置指定出要做的操作,APPEND表示进行数据追加,后边的参数和set就一样了
  • 语法
    list(APPEND <list> [<element> ...])
    
  • 示例
    cmake_minimum_required(VERSION 3.0)
    project(TEST)set(TEMP "DieSnowK")
    file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
    file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)# 追加(拼接)
    list(APPEND SRC_1 ${SRC_1} ${SRC_2} ${TEMP})
    message(STATUS "message: ${SRC_1}")
    
  • 在CMake中,使用set命令可以创建一个list,一个在list内部是一个由分号;分割的一组字符串
    • 例如:set(var a b c d e)命令将会创建一个list:a;b;c;d;e,但是最终打印变量值的时候得到的是abcde
      set(tmp1 a;b;c;d;e)
      set(tmp2 a b c d e)
      message(${tmp1}) # 输出结果 abcde
      message(${tmp2}) # 输出结果 abcde
      

2.字符串移除

  • 在通过file搜索某个目录就得到了该目录下所有的源文件,但是其中有些源文件并不是所需要的,需要从搜索到的数据中剔除出去,想要实现这个功能,也可以使用list
    • 删除和追加数据类似,只不过是第一个参数变成了REMOVE_ITEM
  • 语法
    list(REMOVE_ITEM <list> <value> [<value> ...])
    
  • 注意:通过file命令搜索源文件的时候得到的是文件的绝对路径(在list中每个文件对应的路径都是一个item,并且都是绝对路径),那么在移除的时候也要将该文件的绝对路径指定出来才可以,否是移除操作不会成功
  • 示例
    cmake_minimum_required(VERSION 3.0)
    project(TEST)file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/*.cpp)
    # 移除前日志
    message(STATUS "message: ${SRC_1}")# 移除 main.cpp
    list(REMOVE_ITEM SRC_1 ${PROJECT_SOURCE_DIR}/main.cpp)
    # 移除后日志
    message(STATUS "message: ${SRC_1}")
    

3.list其他操作

  • 获取list的长度
    • 语法
      list(LENGTH <list> <output variable>)
      
    • 参数
      • LENGTH:子命令LENGTH用于读取列表长度
      • <list>:当前操作的列表
      • <output variable>:新创建的变量,用于存储列表的长度
  • 读取列表中指定索引的的元素,可以指定多个索引
    • 语法
      list(GET <list> <element index> [<element index> ...] <output variable>)
      
    • 参数
      • <list>:当前操作的列表
      • <element index:列表元素的索引
        • 从0开始编号,索引0的元素为列表中的第一个元素
        • 索引也可以是负数,-1表示列表的最后一个元素,-2表示列表倒数第二个元素,以此类推
        • 当索引(不管是正还是负)超过列表的长度,运行会报错
      • <output variable>:新创建的变量,存储指定索引元素的返回结果,也是一个列表
  • 将列表中的元素用连接符(字符串)连接起来组成一个字符串
    • 语法
      list (JOIN <list> <glue> <output variable>)
      
    • 参数
      • <list>:当前操作的列表
      • <glue>:指定的连接符(字符串)
      • <output variable>:新创建的变量,存储返回的字符串
  • 查找列表是否存在指定的元素,若果未找到,返回-1
    • 语法
      list(FIND <list> <value> <output variable>)
      
    • 参数
      • <list>:当前操作的列表
      • <value>:需要在列表中搜索的元素
      • <output variable>:新创建的变量
        • 如果列表<list>中存在<value>,那么返回<value>在列表中的索引
        • 如果未找到则返回-1
  • 将元素追加到列表中
    list (APPEND <list> [<element> ...])
    
  • list中指定的位置插入若干元素
    list(INSERT <list> <element_index> <element> [<element> ...])
    
  • 将元素插入到列表的0索引位置
    list (PREPEND <list> [<element> ...])
    
  • 将列表中最后元素移除
    list (POP_BACK <list> [<out-var>...])
    
  • 将列表中第一个元素移除
    list (POP_FRONT <list> [<out-var>...])
    
  • 指定的元素从列表中移除
    list (REMOVE_ITEM <list> <value> [<value> ...])
    
  • 指定索引的元素从列表中移除
    list (REMOVE_AT <list> <index> [<index> ...])
    
  • 移除列表中的重复元素
    list (REMOVE_DUPLICATES <list>)
    
  • 列表翻转
    list(REVERSE <list>)
    
  • 列表排序
    • 语法
      list (SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
      
    • 参数
      • COMPARE:指定排序方法
        • STRING:按照字典序排序,为默认的排序方法
        • FILE_BASENAME:如果是一系列路径名,会使用basename进行排序
        • NATURAL:使用自然数顺序排序
      • CASE:指明是否大小写铭感
        • SENSITIVE:按照大小写敏感的方式进行排序,为默认值
        • INSENSITIVE:按照大小写不敏感的方式进行排序
      • ORDER:指明排序的顺序
        • ASCENDING:按照升序排序,为默认值
        • DESCENDING:按照降序排列

4.宏定义

  • 在进行程序测试的时候,可以在代码中添加一些宏定义,通过这些宏来控制这些代码是否生效
    #include <stdio.h>
    #define NUMBER  3int main()
    {int a = 10;
    #ifdef DEBUGprintf("Pikachu~\n");
    #endiffor(int i=0; i<NUMBER; ++i){printf("DieSnowK\n");}return 0;
    }
    
  • 在上述程序的第七行对DEBUG宏进行了判断,如果该宏被定义了,那么第八行就会进行日志输出,如果没有定义这个宏,第八行就相当于被注释掉了,因此最终无法看到日志输出(上述代码中并没有定义这个宏)
  • 为了让测试更灵活,可以不在代码中定义这个宏,而是在测试的时候去把它定义出来,其中一种方式就是在gcc/g++命令中去指定,通过参数-D指定出要定义的宏的名字,这样就相当于在代码中定义了一个宏,其名字为DEBUG
    gcc test.c -DDEBUG -o app
    
  • 在CMake中,对应的命令为add_definitions
    add_definitions(-D宏名称)
    
  • 示例
    cmake_minimum_required(VERSION 3.0)
    project(test)add_definitions(-DDEBUG)
    add_executable(app ./main.c)
    

5.预定义宏

  • 以下为CMake中常用的一些预定义宏

    功能
    PROJECT_SOURCE_DIR使用cmake命令后紧跟的目录,一般是工程的根目录
    PROJECT_BINARY_DIR执行cmake命令的目录
    CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径
    CMAKE_CURRENT_BINARY_DIRtarget编译目录
    EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置
    LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置
    PROJECT_NAME返回通过PROJECT指令定义的项目名称
    CMAKE_BINARY_DIR项目实际构建路径,假设在build目录进行的构建,那么得到的就是这个目录的路径

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

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

相关文章

大数据期末复习——hadoop、hive等基础知识

一、题型分析 1、Hadoop环境搭建 2、hadoop的三大组件 HDFS&#xff1a;NameNode&#xff0c;DataNode&#xff0c;SecondaryNameNode YARN&#xff1a;ResourceManager&#xff0c;NodeManager &#xff08;Yarn的工作原理&#xff09; MapReduce&#xff1a;Map&#xff0…

七人互助拼团模式:共创共赢的电商新篇章

在当今电商行业的繁荣浪潮中&#xff0c;七人互助拼团模式犹如一股清流&#xff0c;凭借其独特的激励机制与深厚的互助合作文化&#xff0c;赢得了消费者与商家的广泛赞誉。这一模式不仅重新定义了团购体验&#xff0c;更在无形中强化了社群间的联系与协作&#xff0c;共同绘制…

中英双语介绍日本东京(Tokyo)

中文版 东京介绍 东京是日本的首都&#xff0c;也是日本的政治、经济、文化和国际交流中心。以下是对东京的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化和主要景点。 地理位置 东京位于日本关东地区的南部&#xff0c;地理坐标大致为北纬35度41分&#xf…

C语言_练习题

求最小公倍数 思路&#xff1a;假设两个数&#xff0c;5和7&#xff0c;那么最小至少也要7吧&#xff0c;所以先假定最小公倍数是两个数之间较大的&#xff0c;然后看7能不能同时整除5和7&#xff0c;不能就加1继续除 int GetLCM(int _num1, int _num2) {int max _num1>_n…

C++11中新特性介绍-之(二)

11.自动类型推导 (1) auto类型自动推导 auto自动推导变量的类型 auto并不代表某个实际的类型&#xff0c;只是一个类型声明的占位符 auto并不是万能的在任意场景下都能推导&#xff0c;使用auto声明的变量必须进行初始化&#xff0c;以让编译器推导出它的实际类型&#xff0c;…

Python入门 2024/7/6

目录 数据容器入门 列表的定义语法 基本语法 嵌套列表 ​编辑 列表的下表索引 ​编辑 列表的常用操作 列表的常见方法 查找元素的下标 修改下标索引的值 插入元素 追加元素 追加一批元素 删除元素 删除某元素在列表中的第一个匹配项 清空列表内容 统计元素在…

2024亚太杯中文赛数学建模B题完整论文讲解(含每一问python代码+结果+可视化图)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2024 年第十四届 APMCM 亚太地区大学生数学建模竞赛B题洪水灾害的数据分析与预测完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人…

web服务之Nginx

web服务之Nginx &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Li…

将IConfiguration对象转换成一个具体的对象,以面向对象的方式来使用配置

我们倾向于将IConfiguration对象转换成一个具体的对象&#xff0c;以面向对象的方式来使用配置&#xff0c;我们将这个转换过程称为配置绑定。除了将配置树叶子节点配置节的绑定为某种标量对象外&#xff0c;我们还可以直接将一个配置节绑定为一个具有对应结构的符合对象。除此…

【音视频 | RTSP】RTSP协议详解 及 抓包例子解析(详细而不赘述)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

华为开发者大会2024纪要:鸿蒙OS的全新篇章与AI大模型的革命

华为开发者大会2024纪要:鸿蒙OS的全新篇章与AI大模型的革命 在科技的浪潮中,华为再次引领潮流,2024年的开发者大会带来了一系列令人瞩目的创新成果。从鸿蒙操作系统的全新Beta版到盘古大模型的震撼发布,华为正以前所未有的速度重塑智能生态。以下是本次大会的亮点,让我们…

MUNIK解读ISO26262--系统架构

功能安全之系统阶段-系统架构 我们来浅析下功能安全系统阶段重要话题——“系统架构” 目录概览&#xff1a; 系统架构的作用系统架构类型系统架构层级的相关安全机制梳理 1.系统架构的作用 架构的思维包括抽象思维、分层思维、结构化思维和演化思维。通过将复杂系统分解…

哨兵1SAR空间数据包协议数据单元文档(七)

《哨兵1SAR空间数据包协议数据单元》文档对数据包的结构进行了详细描述&#xff0c;并提供了用户数据的格式和解码算法。 原文链接: 哨兵1SAR空间数据包协议数据单元文档英文版 同系列中的其他文章篇链接: 哨兵1SAR空间数据包协议数据单元文档&#xff08;一&#xff09; 哨兵…

lodash-es 基本使用

中文文档&#xff1a;https://www.lodashjs.com/ cloneDeep方法文档&#xff1a;https://www.lodashjs.com/docs/lodash.cloneDeep#_clonedeepvalue 参考掘金文章&#xff1a;https://juejin.cn/post/7354940462061715497 安装&#xff1a; pnpm install lodash-esnpm地址&a…

Javase-异常

文章目录 1. 异常概述2. 异常的继承结构3. 自定义异常4. 异常的处理5. 异常的使用6. finally语句块7. 方法覆盖与异常 1. 异常概述 什么是异常 ①什么是异常?有什么用? 1.Java中的异常是指程序运行时出现了错误或异常情况&#xff0c;导致程序无法继续正常执行的现象。例如&…

谷粒商城 - 树形菜单递归流查询、三级分类数据查询性能优化、Jmter 性能压测

目录 树形分类菜单&#xff08;递归查询&#xff0c;强扩展&#xff09; 1&#xff09;需求 2&#xff09;数据库表设计 3&#xff09;实现 4&#xff09;关于 asSequence 优化 性能压测 1&#xff09;Jmeter 安装使用说明 2&#xff09;中间件对性能的影响 三级分类数…

【Kubernetes】Pod 资源调度之亲和性调度

Pod 资源调度之亲和性调度 1.Node 亲和性调度1.1 Node 硬亲和性1.2 Node 软亲和性 2.Pod 亲和性调度2.1 Pod 硬亲和2.2 Pod 软亲和2.3 Pod 反亲和 Kubernetes 的 默认调度器 以 预选、优选、选定机制 完成将每个新的 Pod 资源绑定至为其选出的目标节点上&#xff0c;不过&#…

吴恩达深度学习笔记:机器学习策略(2)(ML Strategy (2)) 2.7-2.8

目录 第三门课 结构化机器学习项目&#xff08;Structuring Machine Learning Projects&#xff09;第二周&#xff1a;机器学习策略&#xff08;2&#xff09;(ML Strategy (2))2.7 迁移学习&#xff08;Transfer learning&#xff09; 第三门课 结构化机器学习项目&#xff0…

学习笔记——动态路由——IS-IS中间系统到中间系统(区域划分)

三、IS-IS区域划分 根据IS-IS路由器邻居关系&#xff0c;可以将IS-IS划分为两个区域——骨干区域和非骨干区域。&#xff08;注意&#xff0c;这里的区域不是上文中提到的Area ID&#xff09;由L2的IS-IS邻居构成的区域为骨干区域&#xff0c;由L1的IS-IS邻居构成的区域为非骨…

智能运维场景探索 | 运营分析

【本场景来源于 擎创科技《一体化数智运维AIOps解决方案》白皮书&#xff0c;经过重新编写】 该场景主要围绕生产运行、运营决策两个维度进行展开&#xff0c;通过对配置、性能、业务等运行数据的加工计算&#xff0c;形成可量化运营效果、可衡量发展方向的运营数据。整体以低…