[CMake翻译]增加系统反省(步骤5)

346 阅读2分钟

原文地址:cmake.org/cmake/help/…

原文作者:

发布时间:

让我们考虑在我们的项目中添加一些代码,这些代码取决于目标平台可能没有的功能。在这个例子中,我们将添加一些代码,这些代码取决于目标平台是否有logexp函数。当然,几乎每个平台都有这些功能,但在本教程中,假设它们并不常见。

如果平台有logexp,那么我们将使用它们来计算mysqrt函数中的平方根。我们首先使用顶层CMakeLists.txt中的CheckSymbolExists模块来测试这些函数是否可用。在某些平台上,我们需要链接到m库。如果最初没有找到 logexp,则需要 m 库并再次尝试。

我们将使用TutorialConfig.h.in中的新定义,所以一定要在配置该文件之前设置它们。

include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP))
  unset(HAVE_LOG CACHE)
  unset(HAVE_EXP CACHE)
  set(CMAKE_REQUIRED_LIBRARIES "m")
  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()

现在让我们把这些定义添加到TutorialConfig.h.in中,这样我们就可以从mysqrt.cxx中使用它们。

// does the platform provide exp and log functions?
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP

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

#if defined(HAVE_LOG) && defined(HAVE_EXP)
  double result = exp(log(x) * 0.5);
  std::cout << "计算" << x << "的平方根为" << result
            << "使用日志和exp" << std::endl;
#else
  double result = x;

我们还需要修改mysqrt.cxx以包含cmath

#include <cmath>

运行 cmake 可执行文件或 cmake-gui 来配置项目,然后用你选择的构建工具来构建它,并运行 Tutorial 可执行文件。

你会注意到我们没有使用logexp,即使我们认为它们应该是可用的。我们应该很快意识到,我们已经忘记在mysqrt.cxx中包含TutorialConfig.h

我们还需要更新MathFunctions/CMakeLists.txt,以便mysqrt.cxx知道这个文件的位置。

target_include_directories(MathFunctions
          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
          PRIVATE ${CMAKE_BINARY_DIR}
          )

做完这个更新后,再去构建项目,并运行构建的Tutorial可执行文件。如果仍然没有使用logexp,请打开构建目录中生成的TutorialConfig.h文件。也许它们在当前系统中不可用?

sqrt和mysqrt哪个函数现在给出的结果更好?

指定编译定义

除了在TutorialConfig.h中,是否有更好的地方让我们保存HAVE_LOGHAVE_EXP值?让我们尝试使用 target_compile_definitions()

首先,删除 TutorialConfig.h.in 中的定义。我们不再需要包含mysqrt.cxx中的TutorialConfig.hMathFunctions/CMakeLists.txt中的额外包含。

接下来,我们可以将HAVE_LOGHAVE_EXP的检查移到MathFunctions/CMakeLists.txt中,然后将这些值指定为PRIVATE编译定义。

include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP))
  unset(HAVE_LOG CACHE)
  unset(HAVE_EXP CACHE)
  set(CMAKE_REQUIRED_LIBRARIES "m")
  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()

# add compile definitions
if(HAVE_LOG AND HAVE_EXP)
  target_compile_definitions(MathFunctions
                             PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

做完这些更新后,再继续构建项目。运行构建好的Tutorial可执行文件,并验证结果是否与前面这一步相同。


www.deepl.com 翻译