CMake:Tutorial-Step5

Step 5: Adding System Introspection(添加系统自察)

为了代码能根据不同平台的特征来check环境中的依赖是否都存在,以check环境平台中是否有 logexp函数为例来check(实际上很多平台都有这俩函数,这里只是简单的以这俩为例,假设他们不是很common的依赖函数):

如果在mysqrt这个函数的计算过程中要用到logexp这俩个函数,需要先使用CheckSymbolExitst这个模块来检测是否该功能存在。

0 修改配置文件

MathFunctions子目录的CMakeLists.txt中添加如下字段:

include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)#检查头文件math.h 中是否有函数 log,若有的则定义HAVE_LOG 缓存变量,固定设置为1
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP#如果最初未找到 log 和 exp,则需要 m 库并重试。
  unset(HAVE_LOG CACHE)
  unset(HAVE_EXP CACHE)
  set(CMAKE_REQUIRED_LIBRARIES "m") #将libm.so 加入CMAKE_REQUEST_LIBRARIES 列表中
  check_symbol_exists(log "math.h" HAVE_LOG)
  check_symbol_exists(exp "math.h" HAVE_EXP)
  if(HAVE_LOG AND HAVE_EXP)
    target_link_libraries(MathFunctions PRIVATE m)
  endif()
endif()
if(HAVE_LOG AND HAVE_EXP)#如果找到了log 和exp,使用 target_compile_definitions() 将 HAVE_LOG 和 HAVE_EXP 指定为私有编译定义。 
  target_compile_definitions(MathFunctions
                             PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

check_symbol_exists()语法如下:

check_symbol_exists(<symbol> <files> <variable>)

在包含给定的头文件 <files> 后检查<symbol> 是否可用并将结果存储在 <variable> 中。 将一个参数中的文件列表指定为以分号分隔的列表。 <variable> 将被创建为内部缓存变量。

如果头文件将符号定义为宏,则认为它可用并假定可以工作。 如果头文件将符号声明为函数或变量,则符号也必须可用于链接(因此可能无法检测到内部函数)。 如果符号是类型、枚举值或内部符号,则无法识别(考虑使用 CheckTypeSize 或 CheckCSourceCompiles)。 如果需要在 C++ 中完成检查,请考虑改用 CheckCXXSymbolExists。

unset()语法如下:

取消设置变量、缓存变量或环境变量。

unset(<variable> [CACHE | PARENT_SCOPE])

如果没有关键字,unset用于从当前作用域删除一个普通变量(normal ariable),使其变为未定义。

如果有CACHE 关键字的话,意味着删除了一个缓存变量。

说明:在CMake语义里,引用${VAR}首先找到具有该名的普通变量,如果没有的话再在缓存中找这个名字。

如果存在 PARENT_SCOPE,则该变量将从当前作用域之上的作用域中移除。

set(CMAKE_REQUIRED_LIBRARIES "m")加载了libm.so库,看当前本地安装的库可使用如下命令:

dconfig -p | grep lib_name

比如在我的本地就有如下动态库:

在这里插入图片描述

1 修改源代码

如果系统上有 log 和 exp,那么我们将使用它们来计算 mysqrt 函数中的平方根。 将以下代码添加到 MathFunctions/mysqrt.cxx 中的 mysqrt 函数中(在返回结果之前不要忘记 #endif!):

#if defined(HAVE_LOG) && defined(HAVE_EXP)
  double result = exp(log(x) * 0.5);
  std::cout << "Computing sqrt of " << x << " to be " << result
            << " using log and exp" << std::endl;
#else
  double result = x;
#endif

同时也需要在mysqrt.cxx 文件内添加头文件包含#include<cmath>

测试:

mkdir build
cd build
cmake ../
cmake --build .
ctest -C DEBUG -VV

结果如下:

在这里插入图片描述

执行安装sudo make install的时候仍然有bug

[ 50%] Built target MathFunctions
[100%] Built target Tutorial
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/Tutorial
CMake Error at cmake_install.cmake:57 (file):
  file INSTALL cannot find "//TutorialConfig.h".
Makefile:128: recipe for target 'install' failed
make: *** [install] Error 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值