CMake Tutorial 巡礼(5)_添加系统自察

CMake Tutorial巡礼(5)_ 添加系统自察

这是本系列的第六篇。
上一篇我们学习了如何生成安装包,以及如何使用ctest进行简单的测试。
这一篇我们继续学习,如何添加系统自察。什么是“系统自察”呢?具体到本例,就是对系统是否具有某些函数或功能进行预先的测试,通过判断系统的自身属性,在编译时决定采用不同的分支。

本章导读

在这里插入图片描述

第五步:添加系统自察

Let us consider adding some code to our project that depends on features the target platform may not have. For this example, we will add some code that depends on whether or not the target platform has the log and exp functions. Of course almost every platform has these functions but for this tutorial assume that they are not common.

让我们考虑向项目中添加一些代码,这些代码依赖于目标平台可能没有的功能。对于此示例,我们将添加一些代码,这些代码将依赖于平台是否具有logexp函数,当然,几乎每个平台都具有这些功能,但在本Tutorial中,假设它们并不常见。

If the platform has log and exp then we will use them to compute the square root in the mysqrt function. We first test for the availability of these functions using the CheckCXXSourceCompiles module in MathFunctions/CMakeLists.txt.

如果平台有logexp函数,那么我们将使用它们来计算mysqrt函数中的平方根。我们首先使用MathFunctions/CMakeLists.txt中的CheckCXXSourceCompiles模块测试这些函数的可用性。

Add the checks for log and exp to MathFunctions/CMakeLists.txt, after the call to target_include_directories():

MathFunctions/CMakeLists.txt中添加针对logexp的测试,位于target_include_directories()调用之后。

MathFunctions/CMakeLists.txt

target_include_directories(MathFunctions
          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
          )

# does this system provide the log and exp functions?
include(CheckCXXSourceCompiles)
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)

If available, use target_compile_definitions() to specify HAVE_LOG and HAVE_EXP as PRIVATE compile definitions.

如果得到的验证结果是“可行”,使用target_compile_definitions()来指定HAVE_LOGHAVE_EXP,作为私有,即PRIVATE编译定义。

MathFunctions/CMakeLists.txt

if(HAVE_LOG AND HAVE_EXP)
  target_compile_definitions(MathFunctions
                             PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

小白按:以上修改完成后,最终修改的结果为

add_library(MathFunctions mysqrt.cxx)

# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
          )

# does this system provide the log and exp functions?
include(CheckCXXSourceCompiles)
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)

if(HAVE_LOG AND HAVE_EXP)
  target_compile_definitions(MathFunctions
                             PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

# install rules
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)

If log and exp are available on the system, then we will use them to compute the square root in the mysqrt function. Add the following code to the mysqrt function in MathFunctions/mysqrt.cxx (don’t forget the #endif before returning the result!):

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

MathFunctions/mysqrt.cxx

#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;
#else
  double result = x;

We will also need to modify mysqrt.cxx to include cmath.

我们也需要修改mysqrt.cxx,使其包含cmath

MathFunctions/mysqrt.cxx

#include <cmath>

小白按:以上修改全部完成后,mysqrt.cxx的全貌为

#include <iostream>
#include <cmath>  

#include "MathFunctions.h" 
// a hack square root calculation using simple operations
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }  

#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;
#else
  double result = x; 

  // do ten iterations
  for (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
  return result;
}

Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool and run the Tutorial executable.

执行 cmakecmake-gui,指定项目,并且用你选定的编译工具进行编译,最后运行Tutorial可执行文件。

Which function gives better results now, sqrt or mysqrt?

哪一个函数给出了更优的结果?sqrt还是mysqrt?

小白按:给出所有的编译代码:

mkdir Step5_build
cd Step5_build
cmake ../Step5
cmake --build .
cd Debug
Tutorial 4294967206
cd ..
cmake ../Step5 -DUSE_MYMATH=OFF
cmake --build .
cd Debug
Tutorial 4294967206

两个结果分别是:

Computing sqrt of 4.29497e+09 to be 65536 using log and exp
The square root of 4.29497e+09 is 65536
The square root of 4.29497e+09 is 65536

可以看出,使用了logexp之后,平方根运算的精度已经和系统自带的sqrt函数不相上下了。

这一小节还算是比较容易+平顺的,下一回合我们将要学习“添加自定义命令和生成文件”。

【水平所限,错漏难免,创作不易,轻喷勿骂】

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值