C/C++跨平台构建工具CMake-----在C++源码中读取CMakeLists.txt配置文件中的内容

news2024/11/28 13:41:30

文章目录

  • 1.需求描述
  • 2.需求准备
    • 2.1 创建项目
    • 2.2 编辑CMakeLists.txt文件
    • 2.3 编写C++文件
    • 2.4 编译构建项目
  • 3.需求实现
    • 3.1 在CMakeLists.txt中输出日志信息
    • 3.2 增加配置生成C++头文件
    • 3.3在C++ 源码中访问配置的值
    • 3.4 C++文件中读取CMakeLists.txt中的字符串
  • 总结

1.需求描述

当我们开发软件项目时,通常会用到版本控制,每个版本都会有不同的修改,因为软件一旦发布给用户,当我们升级版本的时候,必定会出现一些用户的版本会是旧版本,所以每次发布版本的时候都会有一个版本号标识用户的版本,这个版本号一般都是放到构建的配置文件中,比如Android是放到App目录下的build.gradle文件中,而我们使用CMake工具构建的C/C++的项目中,自然是放在CMakeLists.txt配置文件中啦。在CMakeLists.txt中,会用下面的语句声明版本号:

project(Tutorial VERSION 2.11)

这个版本号假设我们想要在我们的C/C++源码中读取出来,并且上传到服务器做埋点标识。直接读取肯定是不行的,因为CMakeLists.txt和C/C++源文件是属于不同的系统。那么需要如何做呢。本文就是介绍如何从CMakeLists.txt中读取我们设置的值(不只是版本号哦),并且能在C/C++源文件中访问。

2.需求准备

2.1 创建项目

创建一个C/C++演示项目,非常简单,找到一个目录,在目录下新建一个文件夹,并按照下图创建号对应的文件:
在这里插入图片描述目录中包含一个build目录,用于存放构建后的产物,一个构建脚本CmakeLists.txt,一个用于读取构建脚本中值的C++源代码文件:readConfigValue.cpp,然后我们使用IDE打开这个目录,也可以直接编写,反正怎么方便怎么来吧,我使用VScode打开。

2.2 编辑CMakeLists.txt文件

在CMakeLists.txt文件下编写下面的语句代码:

#1.设置最小要求的Cmake版本号
cmake_minimum_required(VERSION 3.10)

#2.设置项目名称
project(ReadConfigValue)

#3.设置项目的版本号,在C++源文件中会读取这个版本号
project(ReadConfigValue VERSION 1.0)

#4.设置C++ 的版本,这里选择的是C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

#5.将项目编译成一个可执行文件,Windows上的 .exe文件
add_executable(ReadConfigValue readConfigValue.cpp)

这里只做了基本的配置,主要是先验证下项目是否跑通,后面还会编辑这个文件,完成我们的最终需求。

2.3 编写C++文件

在ReadConfigValue.cpp文件中编写下面的代码:

#include<iostream>
#include<string>

int main(int argc,char* argv[]){
    std::cout<<"Hello CMake"<<std::endl;
    return 0;
}

2.4 编译构建项目

进入我们创建的项目目录下,进入build目录,打开命令行工具CMD,输入命令:
cmake ..编译项目, 然后输入命令:cmake --build .构建项目
在这里插入图片描述
执行完上面的命令后会在build目录下生成一些编译后的文件和可执行文件:
在这里插入图片描述我们在命令行执行exe文件后输出我们在C++ 源码中输出的信息就证明我们的环境准备好了,示例项目的输出为: Hello CMake

3.需求实现

项目环境准备好后,我们可以开始实现我们的需求了,其实我们熟悉Android Gradle构建脚本的小伙伴可能会注意到,在编写Android程序的时候,我们可以使用一个类叫BuildConfig,这个类就是在编译期间由Android提供的Gradle插件生成的。这里的CMakeLists.txt实现也和Gradle的方法差不多,这里的大致思想是在编译的时候,将我们想给到C++源码中的值放到一个生成的头文件里面,在C++程序中引用这个头文件就可以了。接下来我们看下具体实现:

3.1 在CMakeLists.txt中输出日志信息

在编写CMakeLists.txt文件时,我们常常需要打印一些信息,这里我们使用一个函数:message(STATUS 内容),如下所示:

#1.设置最小要求的Cmake版本号
cmake_minimum_required(VERSION 3.10)

#2.设置项目名称
project(ReadConfigValue)

#3.设置项目的版本号,在C++源文件中会读取这个版本号
project(ReadConfigValue VERSION 1.0)

#4.设置C++ 的版本,这里选择的是C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

#5.将项目编译成一个可执行文件,Windows上的 .exe文件
add_executable(ReadConfigValue readConfigValue.cpp)

#6.打印调试信息
message(STATUS "Hello from CMakeLists.txt")
message(STATUS "${PROJECT_BINARY_DIR}")
message(STATUS "${ReadConfigValue_VERSION_MAJOR}")
message(STATUS "${ReadConfigValue_VERSION_MINOR}")

修改完CMakeLists.txt后,进入项目的build目录,输入命令cmake . 会得到下图中的信息:
在这里插入图片描述

3.2 增加配置生成C++头文件

我们如果要实现在C++中读取到CMakeLists.txt中的值,需要先生成头文件。生成头文件我们需要先在根目录下创建一个config.h.in文件,用于配置生成的头文件信息:创建好的文件如下图所示:
在这里插入图片描述然后在CMakeLists.txt文件中添加代码引用我们新创建的配置文件,代码如下所示:

configure_file(config.h.in config.h)

并且在我们创建的config.h.in中配置我们要给C++访问的值,如下所示:

#define ReadConfigValue_VERSION_MAJOR ${ReadConfigValue_VERSION_MAJOR}
// 可以使用@ 或者${}去获取对应的值
#define ReadConfigValue_VERSION_MINOR @ReadConfigValue_VERSION_MINOR@

3.3在C++ 源码中访问配置的值

编写完上面的配置后,我们在readConfigValue.cpp文件中引用config.h头文件

#include<iostream>
#include<string>
#include "config.h"

int main(int argc,char* argv[]){
    std::cout<<"Hello CMake"<<std::endl;
    std::cout<<"Major version=>"<<ReadConfigValue_VERSION_MAJOR<<std::endl;
    std::cout<<"Major version=>"<<ReadConfigValue_VERSION_MINOR<<std::endl;
    return 0;
}

然后我们编译后会得到一个config.h头文件:
在这里插入图片描述头文件中的内容就是我们在CMakeLists.txt文件中配置的值:
在这里插入图片描述

但是当我们构建时会报错:
在这里插入图片描述
原因就是我们的config.h文件生成成功了,但是没有正确的引用到C++源文件中,也就是说include"config.h"找不到config.h的路径,所以我们需要在CMakeLists.txt文件中配置好这个路径,代码如下所示:

target_include_directories(ReadConfigValue PUBLIC "${PROJECT_BINARY_DIR}")

这里的第一个参数是我们的项目名称,第二个参数可以是PUBLIC、PRIVATE、INTERFACE 目前暂时使用PUBLIC就行,最后一个是我们生成的config.h所在目录的路径,我们的config.h实际上是在build目录下的,我们在前面输出的调试信息中也发现${PROJECT_BINARY_DIR}输出的是build目录的路径,所以配置好它就行了

配置完成后我们再编译构建就发现可以运行并且成功读取到CMakeLists.txt文件的值了。
在这里插入图片描述

3.4 C++文件中读取CMakeLists.txt中的字符串

如果我们想要读取CMakeLists.txt文件中的字符串也是可以的,比较简单,首先在CMakeLists.txt中设置我们要给C++源代码文件中读取的字符串:

#.设置字符串给C++文件读取
set(STR_VALUE "I am String from CMakeLists.txt")

在这里插入图片描述如上图所示,需要注意set()语句的位置,不能放在最后否则这个值无法生成
然后再config.h.in中增加配置:

//必须使用双引号,否则在C++源码读取的时候这里没有双引号包裹,会导致读取错误
#define STR_VALUE "@STR_VALUE@"

注意:配置字符串时必须使用双引号包裹我们的取值语句,否则在C++源码读取的时候这里没有双引号包裹,会导致读取错误
然后在C++文件中访问:

#include<iostream>
#include<string>
#include "config.h"

int main(int argc,char* argv[]){
    std::cout<<"Hello CMake"<<std::endl;
    std::cout<<"Major version=>"<<ReadConfigValue_VERSION_MAJOR<<std::endl;
    std::cout<<"Major version=>"<<ReadConfigValue_VERSION_MINOR<<std::endl;
    std::cout<<"String value from CMakeLists.txt==>"<<STR_VALUE<<std::endl;
    return 0;
}

最后编译运行:
在这里插入图片描述

总结

本文虽然简单,但是在开发中确实有用,比如我们的程序中想要区分debug环境和release环境的时候就可以在CMakeList中添加配置,就像Android 的gradle 插件生成的BuildCongfig类一样,我们可以方便的用这个类的DEBUG和RELEASE来区分开发环境和正式环境,以此来隔离掉一些开发环境的log。所以建议小伙伴们熟悉这种使用方法。对开发会很有用哦。

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

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

相关文章

C语言数据结构之排序整合与比较(冒泡,选择,插入,希尔,堆排序,快排及改良,归并排序,计数排序)

前言&#xff1a;排序作为数据结构中的一个重要模块&#xff0c;重要性不言而寓&#xff0c;我们的讲法为下理论掌握大致的算法结构&#xff0c;再上代码及代码讲解&#xff0c;助你一臂之力。 一&#xff0c;冒泡 冒泡排序应该是大家学习以来第一个认识的排序方法&#xff0…

FFmpeg 命令:从入门到精通 | FFmpeg 基本介绍

FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍FFmpeg 简介FFmpeg 基础知识复用与解复用编解码器码率和帧率 资料 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 基本介绍 本系列文章要解决的问题&#xff1…

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题 模块一&#xff1a;数据库系统运维&#xff08;25分&#xff09;任务一&#xff1a;数据库系统搭建&#xff08;10分&#xff09;任务二&#xff1a;房源数据库系统运维&#xff08;15分&#xff09; 模块二&a…

milvus 结合Thowee 文本转向量 ,新建表,存储,搜索,删除

1.向量数据库科普 【上集】向量数据库技术鉴赏 【下集】向量数据库技术鉴赏 milvus连接 from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility connections.connect(host124.****, port19530)2.milvus Thowee 文本转向量 使用 …

模拟实现简单的通讯录

前言&#xff1a;生活中处处都会看到或是用到通讯录&#xff0c;今天我们就通过C语言来简单的模拟实现一下通讯录。 鸡汤&#xff1a;跨越山海&#xff0c;终见曙光&#xff01; 链接:gitee仓库&#xff1a;代码链接 目录 主函数声明部分初始化通讯录实现扩容的函数增加通讯录所…

【Docker】docker拉取镜像错误 missing signature key

问题 当我使用docker拉取一个特定的镜像时&#xff0c;提示错误&#xff1a; 错误 missing signature key 但是拉取其他镜像又可以访问&#xff0c;&#xff0c;&#xff0c;&#xff0c;于是&#xff0c;我怀疑是否是docker版本问题。 docker --version结果确实&#xff0…

使用Python进行App用户细分

App用户细分是根据用户与App的互动方式对用户进行分组的任务。它有助于找到保留用户&#xff0c;找到营销活动的用户群&#xff0c;并解决许多其他需要基于相似特征搜索用户的业务问题。这篇文章中&#xff0c;将带你完成使用Python进行机器学习的App用户细分任务。 App用户细…

FFmpeg 命令:从入门到精通 | FFmpeg 音视频处理流程

FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 音视频处理流程 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 音视频处理流程实例 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 音视频处理流程 实例 ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x…

ElasticSearch 同步数据变少了

一、前言 这几天对接ES遇到几个坑&#xff0c;我们将一张库存表同步到ES发现Docs Count和我们表中的数据对不上&#xff0c;需要加上Docs deleted才对得上&#xff0c;也不知道批量写入数据为什么有些数据就会成 Docs deleted。 二、ID和版本号 ES中每一个Document都有一个_…

ElementUI之增删改及表单验证

⭐⭐本文章收录与ElementUI原创专栏&#xff1a;ElementUI专栏 ⭐⭐ ElementUI的官网&#xff1a;ElementUI官网 目录 一.前言 二.使用ElementUI完成增删改 2.1 后台代码 2.2 前端代码 三.使用ElementUI完成表单验证 一.前言 本章是继上一篇的基础之上在做完善&#xff0…

Leetcode---364场周赛

题目列表 2864. 最大二进制奇数 2865. 美丽塔 I 2866. 美丽塔 II 2867. 统计树中的合法路径数目 一、最大二进制奇数 这题只要你对二进制有了解(学编程的不会不了解二进制吧)&#xff0c;应该问题不大&#xff0c;这题要求最大奇数&#xff0c;1.奇数&#xff1a;只要保证…

二维码智慧门牌管理系统:创新历史,稳定未来

文章目录 前言一、解决传统门牌管理混乱二、提供便捷服务三、尊重历史&#xff0c;保持稳定 前言 随着科技的飞速发展&#xff0c;二维码智慧门牌管理系统已经成为了城市管理的新趋势。这款系统的出现&#xff0c;不仅优化了传统门牌管理的不足&#xff0c;还大大提高了城市管…

3.物联网射频识别,(高频)RFID应用ISO14443-2协议

一。ISO14443-2协议简介 1.ISO14443协议组成及部分缩略语 &#xff08;1&#xff09;14443协议组成&#xff08;下面的协议简介会详细介绍&#xff09; 14443-1 物理特性 14443-2 射频功率和信号接口 14443-3 初始化和防冲突 &#xff08;分为Type A、Type B两种接口&…

(高阶) Redis 7 第16讲 预热/雪崩/击穿/穿透 缓存篇

面试题 什么是缓存预热/雪崩/击穿/穿透如何做缓存预热如何避免或减少缓存雪崩穿透和击穿的区别?穿透和击穿的解决方案出现缓存不一致时,有哪些修补方案缓存预热 理论 将需要的数据提前加载到缓存中,不需要用户使用的过程中进行数据回写。(比如秒杀活动数据等) 方案 1.…

【C语言深入理解指针(1)】

1.内存和地址 1.1内存 在讲内存和地址之前&#xff0c;我们想有个⽣活中的案例&#xff1a; 假设有⼀栋宿舍楼&#xff0c;把你放在楼⾥&#xff0c;楼上有100个房间&#xff0c;但是房间没有编号&#xff0c;你的⼀个朋友来找你玩&#xff0c;如果想找到你&#xff0c;就得挨…

学校安全用电管理系统解决方案

随着科技的发展和进步&#xff0c;电力已成为我们日常生活和学习的重要支柱。然而&#xff0c;电力的使用也带来了一定的安全风险。特别是对于学校这个复杂而又活跃的环境&#xff0c;安全用电管理系统的角色显得尤为重要。 一、学校用电管理系统的现状 目前&#xff0…

2023-09-28 LeetCode每日一题(花期内花的数目)

2023-09-28每日一题 一、题目编号 2251. 花期内花的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个下标从 0 开始的二维整数数组 flowers &#xff0c;其中 flowers[i] [starti, endi] 表示第 i 朵花的 花期 从 starti 到 endi &#xff08;都 包含&#xf…

JSP学习笔记【三】——JQuery

前言 在写项目的时候需要动态对某组件的属性进行调整&#xff0c;我看网上的教程都是使用document.getElementById等&#xff0c;但我在eclipse编写.jsp文件的时候&#xff0c;却提示document cannot be resolved。由于我对jsp没有系统的了解以及无人可咨询&#xff0c;网上也…

【DTEmpower案例操作教程】向导式建模

DTEmpower是由天洑软件自主研发的一款通用的智能数据建模软件&#xff0c;致力于帮助工程师及工科专业学生&#xff0c;利用工业领域中的仿真、试验、测量等各类数据进行挖掘分析&#xff0c;建立高质量的数据模型&#xff0c;实现快速设计评估、实时仿真预测、系统参数预警、设…

XSS详解

XSS一些学习记录 XXS短标签、属性、事件、方法短标签属性事件函数弹窗函数一些对于绕过有用的函数一些函数使用payload收集 浏览器编码问题XML实体编码URL编码JS编码混合编码 一些绕过方法利用constructor原型污染链构造弹框空格绕过圆括号过滤绕过其他的一些绕过 参考 XXS短标…