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

CMake教程(七):添加系统检查

个人觉得 CMake 官网教程 Step6 对当前我们增加对 CMake 的了解作用不大,所以直接写了教程七。

现在,我们考虑在项目中添加一些代码,这些代码取决于目标平台可能没有的功能。对于这个例子,我们将添加一些代码,这取决于目标平台是否具有logexp 函数。几乎每个平台都具有这两个函数,在这里我们仅是作为例子来说明本节的内容。

本节的目标是根据可用的系统依赖让编译器有选择性编译具体的实现代码。

需要编辑的文件:

  • MathFunctions/CMakeLists.txt
  • MathFunctions/mysqrt.cxx

本节使用的源代码是官网 Step7 目录下的文件。一开始我们需要编辑 MathFunctions/CMakeLists.txt 文件,包含 CheckCXXSourceCompiles 模块。之后,使用 check_cxx_source_compiles 确认 cmath 库当中的 logexp 函数是否可用。如果它们可用,使用 target_compile_definitions() 指定 HAVE_LOGHAVE_EXP 作为编译定义。

MathFunctions/mysqrt.cxx 文件中,包含 cmath。之后,如果系统有 logexp 函数,使用它们计算平方根。

首先,修改 MathFunctions/mysqrt.cxx 文件,在其中添加下面的指令:
include(CheckCXXSourceCompiles)

之后,使用 check_cxx_compiles_source 测试 logexp 函数的可用性。此函数允许我们在编译真正的源代码之前,尝试编译具有所需依赖关系的简单代码。结果变量 HAVE_LOGHAVE_EXP 表示这些依赖关系是否可用。继续修改 MathFunctions/CMakeLists.txt 文件,添加以下的内容:

 check_cxx_source_compiles("#include <cmath>int main() {std::log(1.0);return 0;}" HAVE_LOG)check_cxx_source_compiles("#include <cmath>int main() {std::exp(1.0);return 0;}" HAVE_EXP)

然后,需要传递这些 CMake 变量到源代码中。这样,源代码就能够分辨出哪些资源是可用的。如果 logexp 函数都可用,使用指令 target_compile_definitions() 指定 HAVE_LOGHAVE_EXP 作为 PRIVATE 的编译定义。继续修改 MathFunctions/CMakeLists.txt 文件,添加以下的内容:

 if(HAVE_LOG AND HAVE_EXP)target_compile_definitions(SqrtLibraryPRIVATE "HAVE_LOG" "HAVE_EXP")endif()target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()

接下来,我们需要修改 mysqrt.cxx 文件包含 cmath

#include <cmath>

如果 logexp 函数都可用,那么在 mysqrt 函数当中使用它们来计算平方根。修改 MathFunctions/mysqrt.cxx 文件中的 mysqrt 函数:

#if defined(HAVE_LOG) && defined(HAVE_EXP)double result = std::exp(std::log(x) * 0.5);std::cout << "Computing sqrt of " << x << " to be " << result<< " using log and exp" << std::endl;
#elsedouble result = x;// do ten iterationsfor (int i = 0; i < 10; ++i) {if (result <= 0) {result = 0.1;}double delta = x - (result * result);result = result + 0.5 * delta / result;std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;}
#endif

执行结果:
在这里插入图片描述

如果想要使用我们自己编写的指数函数和对数函数,需要在 MathFunctions/CMakeLists.txt 当中删除以下的代码:

check_cxx_source_compiles("#include <cmath>int main() {std::log(1.0);return 0;}" HAVE_LOG)check_cxx_source_compiles("#include <cmath>int main() {std::exp(1.0);return 0;}" HAVE_EXP)

再次编译并运行程序:
在这里插入图片描述
小结:本节我们利用 CMake 当中的 CheckCXXSourceCompiles 模块,该模块提供了一系列用于检查 C++ 源代码片段是否能够在当前系统上成功编译的宏。接着,使用 CHECK_CXX_SOURCE_COMPILES 指令让 CMake 编译一小段代码,如果编译成功,根据这个结果来设置变量、条件编译选项或者定义特定的特性。

最后,介绍 include(CheckCXXSourceCompiles) 的作用。

include(CheckCXXSourceCompiles) 的作用

在CMake中,include(CheckCXXSourceCompiles) 命令的作用是引入一个 CMake 模块,该模块提供了一系列用于检查 C++ 源代码片段是否能够在当前系统上成功编译的宏。这通常用于在配置(configure)阶段自动检测系统或编译器的特定功能或限制。

具体来说,CheckCXXSourceCompiles 模块定义了一个或多个宏,比如 CHECK_CXX_SOURCE_COMPILES,你可以使用这些宏来编写一小段 C++ 代码,并让 CMake 尝试编译这段代码。如果编译成功,你可以根据这个结果来设置变量、条件编译选项或者定义特定的特性。

使用 CHECK_CXX_SOURCE_COMPILES 宏时,需要提供至少两个参数:

  • 第一个参数是要执行的 C++ 代码;
  • 第二个参数是一个自定义的变量,用于存储编译这段代码的结果。

下面是一个简单的例子,展示了如何使用 CheckCXXSourceCompiles 来检测编译器是否支持 C++11 的某些特性(如 auto 关键字):

include(CheckCXXSourceCompiles)  # 检查C++11的auto关键字是否可用  
CHECK_CXX_SOURCE_COMPILES("  
#include <vector>  int main() {  std::vector<int> v = {1, 2, 3};  auto x = v[0];  return 0;  
}  
" HAVE_CXX11_AUTO)  # 根据检查结果,可以做出不同的配置决策  
if(HAVE_CXX11_AUTO)  message(STATUS "Compiler supports C++11 auto keyword.")  
else()  message(FATAL_ERROR "Compiler does not support C++11 auto keyword.")  
endif()

各位道友,码字不易,如有收获,记得一键三连啊。
看完觉得有帮助的道友,可以关注我的公众号,里面会分享一些高质量的个人成长类读书笔记、生活随笔以及职场经验等等。
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Linux bash脚本本地开发环境(Git Bash)配置
  • 聊一聊站在对方的立场去阐述问题
  • SVN笔记-SVN安装
  • 动手学深度学习9.1. 门控循环单元(GRU)-笔记练习(PyTorch)
  • 比亚迪技术面试(测试、测开)
  • 服务监控插件全览:提升微服务可观测性的利器
  • 计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-22
  • 【LTW】Domain General Face Forgery Detection by Learning to Weight
  • 如何用 HAproxy 实施高可用部署 | OceanBase 实践
  • NLP 文本分类任务核心梳理
  • 握手传输 状态机序列检测(记忆科技笔试题)_2024年9月2日
  • 仪表放大器AD620
  • SpringBoot开发——整合SpringDoc实现在线接口文档
  • 深度学习模型之BERT的24个小模型源码与预训练紧凑模型的重要性
  • 前端算法学习,包含复杂度、双指针、滑动窗口、二叉树、堆等常见题型和方法,含leetcode例题
  • C# 免费离线人脸识别 2.0 Demo
  • CSS 三角实现
  • CSS 提示工具(Tooltip)
  • CSS魔法堂:Absolute Positioning就这个样
  • java取消线程实例
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • tensorflow学习笔记3——MNIST应用篇
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • use Google search engine
  • vue总结
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 从伪并行的 Python 多线程说起
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 技术发展面试
  • 经典排序算法及其 Java 实现
  • 精彩代码 vue.js
  • 跨域
  • 数据科学 第 3 章 11 字符串处理
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • Semaphore
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • $.proxy和$.extend
  • (02)Unity使用在线AI大模型(调用Python)
  • (2)STM32单片机上位机
  • (C语言)fread与fwrite详解
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (补充)IDEA项目结构
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .net core 控制台应用程序读取配置文件app.config
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET学习全景图