cmake之如何构建环境

构建环境

  • 检测操作系统

    • 在不同的操作系统上,CMake需要根据操作系统启用条件编译,就需要检测当前的操作系统;

    • 进行操作系统匹配的变量为CMAKE_SYSTEM_NAME,该名称为CMAKE为操作系统定义的,使用if的条件语句可以进行操作系统的匹配,如下

      if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      	message(STATUS "Configuring on/for Linux")
      endif()
      

      唯一需要注意的是,操作系统有不同的名称,如macOS对应“Darwin”;

    • 为了最小化平台之间的转移成本,需要避免直接使用shell命令、还应该避免显示使用路径分隔符;

    • cmake代码只是用前斜杠作为路径分割符,cmake自动将他们转换为所所涉及的操作系统环境;

  • 处理与平台相关的代码

    • 当编写原码时,可能需要考虑到其在不同操作系统上的安装和编译,这时需要根据操作系统编译源码;

    • 同样需要首先检测操作系统,然后再编译定义,如下所示:

      ...
      add_executable(hello-world hello-world.cpp)
      if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      	target_compile_definitions(hello-world PUBLIC "IS_LINUX")
      endif()
      ...
      

      即在继续之前,需要检查前面的表达式,并考虑在系统上的行为;

  • 处理与编译器相关的源码

    • 对于适应不同的编译器,我们需要在CMake中进行预定义;

    • 同样的,需要在add_executable之后使用target_compile_definitions进行指定,其变量名称为COMPILE_NAME,然后使用is语句判断对应的处理器,代码如下:

      ...
      add_executable(hello-world hello-world.cpp)
      if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      	target_compile_definitions(hello-world PUBLIC "$COMPILE_NAME=\"${CMAKE_CXX_COMPILER_ID}\"")
      endif()
      
      if(CMAKE_CXX_COMPILER_ID MATCHES Intel)
      	target_compile_definitions(hello-world PUBLIC "IS_INTEL_COMPILE")
      endif()
      ...
      
  • 检测处理器体系结构

  • 检测主机的处理器指令集

  • 为Eigen库使能向量化

    • 处理器的向量化功能,可以提高代码的性能。如使用线性代数的Eigen C++库加速可执行文件;

    • 对于如下代码而言:

      #include <Eigen/Dense>
      
      EIGEN_DONT_INLINE
      double simple_function(Eigen::VectorXd &va, Eigen::VectorXd &vb)
      {
         // this simple function computes the dot product of two vectors
         // of course it could be expressed more compactly
         double d = va.dot(vb);
         return d;
      }
      

      向量化可以加快simple_function中的点积操作.

    • 根据Eigen库的文档,设置适当的编译器标志就足以生成向量化代码,,代码如下:

      ...
      # 使用Eigen库,需要在系统上找到其头文件
      find_package(Eigen3 3.3 REQUIRED CONFIG)
      # 引入CheckCXXCompilerFlag.cmake标准模块文件
      include(CheckCXXCompilerFlag)
      #检查-match=native和-xHost编译器标志是否工作
      check_cxx_compiler_flag("-march-native" _march_native_works)
      check_cxx_compiler_flag("-xHost" _xhost_works)
      
      #设置空变量_CXX_FLAGS保存找到的两个编译器标志,如果都不起作用,则为空
      set(_CXX_FLAGS)
      if(_march_native_works)
      	message(STATUS "Using processor's vector instructions (-march=native compiler flag set)")
      	set(_CXX_FLAGS "-march=native")
      esleif(_march_native_works)
      	message(STATUS "Using processor's vector instructions (-xHost compiler flag set)")
      	set(_CXX_FLAGS "_xHost")
      else()
      	message(STATUS "No suitable compiler flag found for vectorization")
      endif()
      
      add_executable(linear-algebra linear-algebra.cpp)
      target_compile_options(linear-algebra PRIVATE ${_CXX_FLAGS}) #使用优化标志
      target_link_libraries(linear-algebra PRIVATE Eigen3::Eigen)
      ...
      
    • 工作原理:处理器大都提供向量指令集,利用这一特点可以使代码提速;

    • 线性代数可以从Eigen库中获得加速,所以在使用Eigen库时,需要考虑向量化;

    • 我们需要指示编译器检查处理器,为当前体系结构生成本机指令;

    • 不同的编译器供应商会使用不同的标志来实现,GNU使用-march=native标志实现,Intel编译器使用-xHostsh标志是实现;

    • 使用CheckCXXCompilerFlag.cmake模块提供的check_cxx_compiler_flag函数进行编译器标志的检查。其中,第一个参数为要检查的标志,第二个用于存储检查结果(true or false);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值