原文作者:
发布时间:
让我们考虑在我们的项目中添加一些代码,这些代码取决于目标平台可能没有的功能。在这个例子中,我们将添加一些代码,这些代码取决于目标平台是否有log和exp函数。当然,几乎每个平台都有这些功能,但在本教程中,假设它们并不常见。
如果平台有log和exp,那么我们将使用它们来计算mysqrt函数中的平方根。我们首先使用顶层CMakeLists.txt中的CheckSymbolExists模块来测试这些函数是否可用。在某些平台上,我们需要链接到m库。如果最初没有找到 log 和 exp,则需要 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
如果系统上有log和exp,那么我们将在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 可执行文件。
你会注意到我们没有使用log和exp,即使我们认为它们应该是可用的。我们应该很快意识到,我们已经忘记在mysqrt.cxx中包含TutorialConfig.h。
我们还需要更新MathFunctions/CMakeLists.txt,以便mysqrt.cxx知道这个文件的位置。
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_BINARY_DIR}
)
做完这个更新后,再去构建项目,并运行构建的Tutorial可执行文件。如果仍然没有使用log和exp,请打开构建目录中生成的TutorialConfig.h文件。也许它们在当前系统中不可用?
sqrt和mysqrt哪个函数现在给出的结果更好?
指定编译定义
除了在TutorialConfig.h中,是否有更好的地方让我们保存HAVE_LOG和HAVE_EXP值?让我们尝试使用 target_compile_definitions()。
首先,删除 TutorialConfig.h.in 中的定义。我们不再需要包含mysqrt.cxx中的TutorialConfig.h或MathFunctions/CMakeLists.txt中的额外包含。
接下来,我们可以将HAVE_LOG和HAVE_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可执行文件,并验证结果是否与前面这一步相同。