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

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

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

相关文章

自动驾驶学习笔记(一)——Apollo平台

#Apollo开发者社区# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 Apollo框架 开发平台 总结 前…

【Acwing1010】拦截导弹(LIS+贪心)题解

题目描述 思路分析 本题有两问&#xff0c;第一问直接用lis的模板即可&#xff0c;下面重点看第二问 思路是贪心&#xff1a; 贪心流程&#xff1a; 从前往后扫描每一个数&#xff0c;对于每个数&#xff1a; 情况一&#xff1a;如果现有的子序列的结尾都小于当前的数&…

unity脚本_Input鼠标键盘 c#

获取鼠标坐标 检测鼠标输入 如果在运行游戏场景中点击一下鼠标左键 检测鼠标抬起 选中即可 检测键盘按下 当前屏幕分辨率 注意&#xff1a;获取的是显示器的分辨率 获取设备屏幕宽高 屏幕休眠模式 窗口/全屏模式 移动设备屏幕转向

CS5366最新设计电路|Typec转HDMI 8K带PD方案设计|带DSC视频压缩技术Typec扩展方案

CS5366支持4K24/25/30/50/60Hz刷新率的HDR&#xff0c;CS5366集成DSC decoded影像解压缩技术,可将DPRX 4Lanes等效宽推升至97.2Gbps或 DPRX 2Lanes等效带宽推升至48.6Gbps ,此功能可改善画面延迟、影像撕裂等问题,可让用户在观看电影或是电玩游戏等高效能影像时有更好的体验。…

分布式文件系统HDFS(林子雨慕课课程)

文章目录 3. 分布式文件系统HDFS3.1 分布式文件系统HDFS简介3.2 HDFS相关概念3.3 HDFS的体系结构3.4 HDFS的存储原理3.5 HDFS数据读写3.5.1 HDFS的读数据过程3.5.2 HDFS的写数据过程 3.6 HDFS编程实战 3. 分布式文件系统HDFS 3.1 分布式文件系统HDFS简介 HDFS就是解决海量数据…

开发与运营:“开发”和“运营”角色有何不同和重叠?

开发和运营是促进软件系统交付的两种角色。大多数大规模构建软件的组织都会雇用这两个学科的人员。不过,开发和运维并不是完全孤立的。团队重叠并实现更高的吞吐量是很常见的。 在本文中,您将学习区分开发人员和操作人员之间的主要区别,以及它们重叠的方式。尽管有将两者结合…

Django基础入门操作 (Django-01)

一 背景介绍 Django是一个开源的 Web应用框架&#xff0c;由Python写成。采用了MTV的框架模式&#xff0c;它最初是被用来做CMS&#xff08;内容管理系统&#xff09;软件。 官方中文文档&#xff1a;Django 文档 | Django 文档 | Django 应用&#xff1a;做内容管理系统(新…

Day4:Linux系统编程1-60P

我的学习方法是&#xff1a;Linux系统编程&#xff08;看pdf笔记&#xff09; Linux网络编程 WebServer 01P-17P Linux相关命令及操作 cp -a dirname1 dirname2 复制目录 cp -r dirname1 dirname2 递归复制目录 1 到目录 2 这里-a 和-r 的差别在于&#xff0c;-a 是完全复制…

kafka、rabbitmq 、rocketmq的区别

一、语言不同 RabbitMQ是由内在高并发的erlanng语言开发&#xff0c;用在实时的对可靠性要求比较高的消息传递上。 kafka是采用Scala语言开发&#xff0c;它主要用于处理活跃的流式数据,大数据量的数据处理上 二、结构不同 RabbitMQ采用AMQP&#xff08;Advanced Message Q…

5分钟理解什么是卷积的特征提取

大家好啊&#xff0c;我是董董灿。 卷积算法之所以重要&#xff0c;关键在于其提取特征的能力。 5分钟入门卷积算法中提到&#xff0c;卷积模仿的就是人眼识图的过程&#xff0c;以“感受野”的视角去扫描图片&#xff0c;从而获取不同区域的图片信息。 在这一过程中&#x…

香港Web3.0生态现状

目前香港Web3.0生态正在快速发展。香港政府和金融机构正在积极推动Web3.0生态的建设&#xff0c;以推动数字经济和智慧城市的发展。香港政府已经发布了有关虚拟资产发展的政策宣言&#xff0c;鼓励和监管并重&#xff0c;加大力度推动虚拟资产产业向前发展。同时&#xff0c;香…

stable diffusion学习笔记【2023-10-2】

L1&#xff1a;界面 CFG Scale&#xff1a;提示词相关性 denoising&#xff1a;重绘幅度 L2&#xff1a;文生图 女性常用的负面词 nsfw,NSFW,(NSFW:2),legs apart, paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, (…

SpringCloud学习笔记-Eureka的服务拉取

假设是OrderService里面拉取Eureka的服务之一User Service 1.依然需要在该服务里面引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependenc…

Android中的RxJava入门及常用操作符

文章目录 1.定义2.作用3.特点4.使用4.1创建被观察者&#xff08;Observable&#xff09;4.2创建观察者&#xff08;Observer&#xff09;4.3订阅&#xff08;Subscribe&#xff09;4.4Dispose 5.操作符5.1操作符类型5.2just操作符5.2链式调用5.3 fromArray操作符5.4 fromIterab…

四位十进制数字频率计VHDL,仿真视频、代码

名称&#xff1a;四位十进制数字频率计VHDL&#xff0c;quartus仿真 软件&#xff1a;Quartus 语言&#xff1a;VHDL 代码功能&#xff1a; 使用直接测频法测量信号频率&#xff0c;测频范围为1~9999Hz&#xff0c;具有超量程报警功能 演示视频&#xff1a;四位十进制数字频…

SpringBoot结合dev-tool 实现IDEA项目热部署

什么是热部署&#xff1f; 应用正在运行的时候升级功能, 不需要重新启动应用对于Java应用程序来说, 热部署就是在运行时更新Java类文件 通俗的来讲&#xff0c;应用在运行状态下&#xff0c;修改项目源码后&#xff0c;不用重启应用&#xff0c;会把编译的内容部署到服务器上…

李宏毅 2022机器学习 HW3 boss baseline 上分记录

作业数据是所有数据都有标签的版本。 李宏毅 2022机器学习 HW3 boss baseline 上分记录 1. 训练数据增强, private 0.760562. cross validation&ensemble, private 0.816473. test dataset augmentation, private 0.824584. resnet, private 0.865555. Image Normalizatio…

1024 画跳动的爱心#程序代码 #编程语言 #计算机

废话不多说 直接开干! 用到库 random time tkinter 快速镜像 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tkinter 上代码 import random import time from math import sin, cos, pi, log from tkinter import *CANVAS_WIDTH 640 # 画布的宽 CANVAS_HEIGH…

vue启动项目,npm run dev出现error:0308010C:digital envelope routines::unsupported

运行vue项目&#xff0c;npm run dev的时候出现不支持错误error:0308010C:digital envelope routines::unsupported。 在网上找了很多&#xff0c;大部分都是因为版本问题&#xff0c;修改环境之类的&#xff0c;原因是对的但是大多还是没能解决。经过摸索终于解决了。 方法如…

LLMs与外部应用程序交互 Interacting with external applications

在上一节中&#xff0c;您看到了LLM如何与外部数据集进行交互。现在让我们看看它们如何与外部应用程序进行交互。为了激发需要这种LLM增强的问题和用例的类型&#xff0c;您将重新审视之前在课程中看到的客户服务机器人示例。在这次浏览中&#xff0c;您将查看需要的集成&#…