CMake使用教程三:系统检查和自定义命令及生成文件

1. 系统检查

系统检查的主要作用是在编译前对环境进行检查,以生成符合系统的可执行程序或库。

1.1 源码

mysqrt.cpp

#include <cmath>
#include <iostream>

#include "MathFunctions.h"

// a hack square root calculation using simple operations
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }

  // if we have both log and exp then use them
#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;
}

1.2 CMake文件

./MathFunctions/CMakeLists.txt

add_library(MathFunctions mysqrt.cpp)

# INTERFACE 指定的是使用者(依赖此库的目标)需要的东西,因此其他使用者就不用额外添加这个库的包含目录
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)

# add compile definitions
if(HAVE_LOG AND HAVE_EXP)
  # 给MathFunctions 编译时添加  HAVE_LOG 和 HAVE_EXP 的宏
  target_compile_definitions(MathFunctions PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

2. 自定义命令及生成文件

自定义命令是指,CMake调用其他可执行文件,生成文件则是指通过调用的其他命令来生成的文件。

2.1 源码

mysqrt.cpp

#include <iostream>

#include "MathFunctions.h"

// include the generated table
#include "Table.h"

// a hack square root calculation using simple operations
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }

  // use the table to help find an initial value
  double result = x;
  if (x >= 1 && x < 10) {
    std::cout << "Use the table to help find an initial value " << std::endl;
    result = sqrtTable[static_cast<int>(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;
  }

  return result;
}

MakeTable.cpp此文件在MathFunctions目录下

// A simple program that builds a sqrt table
#include <cmath>
#include <fstream>
#include <iostream>

int main(int argc, char* argv[])
{
  // make sure we have enough arguments
  if (argc < 2) {
    return 1;
  }

  std::ofstream fout(argv[1], std::ios_base::out);
  const bool fileOpen = fout.is_open();
  if (fileOpen) {
    fout << "double sqrtTable[] = {" << std::endl;
    for (int i = 0; i < 10; ++i) {
      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
    }
    // close the table with a zero
    fout << "0};" << std::endl;
    fout.close();
  }
  return fileOpen ? 0 : 1; // return 0 if wrote the file
}

2.2 CMake文件

./MathFunctions/CMakeLists.txt

add_executable(MakeTable MakeTable.cpp)

# 添加一个自定义命令,指定如何通过运行MakeTable生成Table.h
add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
)


add_library(MathFunctions 
  mysqrt.cpp
  #[[
    告诉CMake mysqrt.cpp取决于生成的文件Table.h
    这是通过将生成的Table.h添加到MathFunctions库的源列表中来实现的
  ]] 
  ${CMAKE_CURRENT_BINARY_DIR}/Table.h
)

# INTERFACE 指定的是使用者(依赖此库的目标)需要的东西,因此其他使用者就不用额外添加这个库的包含目录
target_include_directories(MathFunctions
  INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}"
  # 将当前的二进制目录添加到包含目录列表中,以便mysqrt.cpp能够找到并包含Table.h
  PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
)

3. 项目的其他文件

CMake使用教程二:CMake依赖外部库

4. 参考

CMake Tutorial Step 5
CMake Tutorial Step 6

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值