当前位置: 首页 > news >正文

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

文章目录

  • 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。所以建议小伙伴们熟悉这种使用方法。对开发会很有用哦。

相关文章:

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

文章目录 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.需求描述 当我们开发…...

【MVP争夺战】python实现-附ChatGPT解析

1.题目 MVP争夺战 知识点 :DFS搜索 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 在星球争霸篮球赛对抗赛中,强大的宇宙战队,希望每个人都能拿到MVP。 MVP的条件是,单场最高分得分获得者,可以并列,所以宇宙战队决定在比赛中尽可能让更多的队员上场,且让所有有得…...

6 个最佳免费 Android 数据恢复软件

如果您是 Android 用户&#xff0c;您可能会发现没有回收站。然而&#xff0c;聪明的开发人员已经创建了各种 Android 数据恢复软件程序&#xff0c;可以解决各种与数据丢失相关的问题。 Android 数据恢复软件如何工作&#xff1f; 问题是当你删除一个文件时&#xff0c;它的数…...

数学建模Matlab之数据预处理方法

本文综合代码来自文章http://t.csdnimg.cn/P5zOD 异常值与缺失值处理 %% 数据修复 % 判断缺失值和异常值并修复&#xff0c;顺便光滑噪音&#xff0c;渡边笔记 clc,clear;close all; x 0:0.06:10; y sin(x)0.2*rand(size(x)); y(22:34) NaN; % 模拟缺失值 y(89:95) 50;% 模…...

如何保证Redis的HA高可用

目录 1.关于Redis2.Redis 的使用场景3.Redis的高可用3.1 哨兵模式&#xff08;Sentinel&#xff09;3.2 集群模式&#xff08;Cluster&#xff09; 4.参考 本文主要介绍Redis如何保证高可用。 1.关于Redis Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的…...

第一百六十三回 如何在任意位置显示PopupMenu

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了PopupMenuButton相关的内容&#xff0c;本章回中将介绍如何在任意位置显示PopupMenu.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在上一章回中介绍了PopupMenuButton相关的内容&#xff0c;它主…...

采用python中的opencv2的库来运用机器视觉移动物体

一. 此次我们来利用opencv2来进行机器视觉的学习 1. 首先我们先来进行一个小的案例的实现. 这次我们是将会进行一个小的矩形手势的移动. import cv2 from cvzone.HandTrackingModule import HandDetectorcap cv2.VideoCapture(0) # cap.set(3, 1280) # cap.set(4, 720) col…...

一、thymeleaf简介

1.1 什么是thymeleaf Thymeleaf是一个适用于web和独立环境的现代服务器端Java模板引擎&#xff0c;能够处理HTML、XML、JavaScript、CSS甚至纯文本。主要目标是提供一种优雅且高度可维护的创建模板的方法。 何为模板引擎呢&#xff1f;模板引擎就是为了使用户页面和业务数据…...

二分查找模版

对于一个递增序列我们要找大于等于target的数&#xff0c;返回结果的下标时 比如 序列 5 7 7 8 8 10 初始化左右指针l0 rn-1 猜测区间 [l,r] 闭区间&#xff0c;mid(lr)/2 防溢出就写成 midl(r-l)/2 如果有nums[mid]<target 那么[l,mid]这个区间的数就都小于target 更新 lmi…...

idea清空缓存类

解决办法 网上有很多是让你去清空什么maven依赖&#xff0c;但假如这个项目是你不可以大刀阔斧的话 可以清空idea缓存 选择 Invalidate 开头的 然后全选 运行重启idea OK...

PAT(Basic Level) Practice(中文) 1015德才论

前言 ※ PTA是 程序设计类实验辅助教学平台 &#xff0c;里边包含一些编程题目集以供练习。 这道题用java解&#xff0c;我试了三种解法&#xff0c;不断优化&#xff0c;但始终是三个测试点通过、三个测试点超时。我把我的代码放在这里&#xff0c;做个参考吧。 1015 德才…...

接口自动化测试的概述及流程梳理~

接下来开始学习接口自动化测试。 因为之前从来没接触过&#xff0c;所以先了解一些基础知识。 1.接口测试的概述 2.接口自动化测试流程。 接口测试概述 接口&#xff0c;又叫API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;&a…...

竞赛 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#x…...

虚拟货币(也称为加密货币或数字货币)的运作

虚拟币发展史 虚拟币的发展史可以追溯到20世纪末和21世纪初&#xff0c;以下是虚拟币的重要发展节点&#xff1a; 1998年&#xff1a;比特币白皮书的发布 比特币的概念最早由中本聪&#xff08;Satoshi Nakamoto&#xff09;在1998年提出&#xff0c;随后在2008年发布了一份名…...

N. Number Reduction

Problem - 1765N - Codeforces 发现如果是无前导0最小数那么在保证删除k个数时第1位是最小的&#xff0c;第二位一定是相对最小的&#xff0c;且答案第一位和第二位在原位置的间隔是小于等于还可以删除的位数的。 因此&#xff0c;对于原数字长度位n&#xff0c;要删除k&#…...

Java集合面试题

一、Java集合面试题 1.LinkedHashMap底层原理&#xff1f; HashMap是无序的&#xff0c;迭代HashMap所得到元素的顺序并不是它们最初放到HashMap的顺序&#xff0c;即不能保持它们的插入顺序。 LinkedHashMap继承于HashMap&#xff0c;是HashMap和LinkedList的融合体&#x…...

Python 编程基础 | 第三章-数据类型 | 3.5、列表

一、列表 1、创建列表 序列是Python中最基本的数据结构&#xff0c;Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。序列都可以进行的操作包括索引&#xff0c;切片&#xff0c;加&#xff0c;乘&#xff0c;检查成员。此外&#xff0c;Python已经内置确定序列…...

Spring Cloud Zuul 基本原理

Spring Cloud Zuul 底层是基于Servlet实现的&#xff0c;核心是通过一系列的ZuulFilter来完成请求的转发。 1、核心组件注册 1.1. EnableZuulProxy注解 启用Zuul作为微服务网关&#xff0c;需要在Application应用类加上EnableZuulProxy注解&#xff0c;而该注解核心是利用Im…...

QT实现TCP服务器客户端的实现

ser&#xff1a; widget.cpp&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//实例化一个服务器server new QTcpServer(this);// 此时&#xf…...

行为型设计模式——责任链模式

摘要 责任链模式(Chain of responsibility pattern): 通过责任链模式, 你可以为某个请求创建一个对象链. 每个对象依序检查此请求并对其进行处理或者将它传给链中的下一个对象。 一、责任链模式意图 职责链模式&#xff08;Chain Of Responsibility&#xff09; 是一种行为设…...

AI大模型赋能数据治理:小白也能掌握的5个高频场景与避坑指南(收藏备用)

数据治理是企业数字化转型难题&#xff0c;AI大模型带来破局点。本文阐述大模型如何解决效率低、门槛高、适配弱等痛点&#xff0c;提供3个高价值落地场景&#xff08;非结构化数据治理、数据质量治理、数据资产化治理&#xff09;及5个高频踩坑陷阱&#xff0c;并给出最佳实践…...

TrendForge 每日精选:10 个热门开源项目,今日总获星 11321 颗!

TrendForge 每日精选热门开源项目发布 TrendForge 致力于追踪全球开源项目动态&#xff0c;每日为开发者精选最具价值的 GitHub 项目。今日共收录 10 个热门项目&#xff0c;项目描述已自动翻译为智能中文翻译版&#xff0c;便于理解。 今日最热项目 Top 10 mattpocock/skills&…...

NotebookLM无法识别PDF表格?手把手复现Google Research 2024最新LayoutParser适配方案(附可运行Colab脚本)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM无法识别PDF表格&#xff1f;手把手复现Google Research 2024最新LayoutParser适配方案&#xff08;附可运行Colab脚本&#xff09; NotebookLM 默认使用轻量级 PDF 解析器&#xff08;如 Py…...

嵌入式软件测试的范式革命——技术体系与工程价值深度解析

第一章 引言&#xff1a;嵌入式软件质量危机的时代背景在汽车电子、航空航天、工业控制、医疗设备等安全关键领域&#xff0c;嵌入式软件的复杂度正以指数级速度增长。一辆高端智能电动汽车的代码量已突破两亿行&#xff0c;超越了波音787客机的软件规模。与此同时&#xff0c;…...

终极音乐解锁指南:3步免费解锁任何加密音乐文件

终极音乐解锁指南&#xff1a;3步免费解锁任何加密音乐文件 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://git…...

构建可靠AI编码代理:OpenClaw-Build工作流详解与实战

1. 项目概述&#xff1a;一个能“闭环”的AI编码代理工作流如果你用过市面上那些号称能自动编程的AI代理&#xff0c;大概率经历过这样的挫败感&#xff1a;你满怀期待地丢给它一个需求&#xff0c;它吭哧吭哧干了两三个任务&#xff0c;然后要么开始“神游”&#xff0c;写出来…...

3步构建个人知识库:微信读书笔记智能同步终极方案

3步构建个人知识库&#xff1a;微信读书笔记智能同步终极方案 【免费下载链接】obsidian-weread-plugin Obsidian Weread Plugin is a plugin to sync Weread(微信读书) hightlights and annotations into your Obsidian Vault. 项目地址: https://gitcode.com/gh_mirrors/ob…...

从AWE Designer到独立声卡:awb二进制文件固化Flash的实战解析

1. 从AWE Designer到独立声卡的核心逻辑 第一次接触AWE Designer的朋友可能会疑惑&#xff1a;为什么要把算法从PC端搬到开发板&#xff1f;简单来说&#xff0c;这就好比把厨师做好的预制菜打包成罐头——让美味脱离厨房环境也能随时享用。AWE Designer原本需要依赖电脑实时运…...

PyTorch Tensor运算的‘潜规则’:运算符重载(如a*b)与函数调用(torch.mul)到底选哪个?

PyTorch运算符重载与显式函数调用的工程实践指南 在PyTorch的日常开发中&#xff0c;我们经常面临一个看似简单却值得深思的选择&#xff1a;该用a b这样的运算符重载&#xff0c;还是显式调用torch.add(a, b)&#xff1f;这个选择不仅关乎代码风格&#xff0c;更影响着团队协…...

告别AT指令!用nRF52832的BLE NUS服务,5分钟搞定手机与开发板的双向通信

用nRF52832的BLE NUS服务实现高效蓝牙串口通信 在嵌入式开发中&#xff0c;设备与移动端的双向通信一直是个痛点。传统AT指令虽然简单&#xff0c;但效率低下、扩展性差&#xff0c;每次通信都需要复杂的握手流程。而基于nRF52832的BLE NUS&#xff08;Nordic UART Service&…...