步骤 7: 添加系统自省¶
让我们考虑向项目中添加一些代码,这些代码依赖于目标平台可能不具备的功能。在本例中,我们将添加一些代码,这些代码依赖于目标平台是否具有 log
和 exp
函数。当然,几乎所有平台都具有这些函数,但对于本教程,我们假设它们不常见。
练习 1 - 评估依赖项可用性¶
目标¶
根据可用的系统依赖项更改实现。
有用资源¶
要编辑的文件¶
MathFunctions/CMakeLists.txt
MathFunctions/mysqrt.cxx
开始¶
起始源代码在 Step7
目录中提供。在本练习中,完成 TODO 1
到 TODO 5
。
首先编辑 MathFunctions/CMakeLists.txt
。包含 CheckCXXSourceCompiles
模块。然后,使用 check_cxx_source_compiles()
来确定 log
和 exp
是否可以从 cmath
获得。如果它们可用,则使用 target_compile_definitions()
来指定 HAVE_LOG
和 HAVE_EXP
作为编译定义。
在 MathFunctions/mysqrt.cxx
中,包含 cmath
。然后,如果系统具有 log
和 exp
,则使用它们来计算平方根。
构建并运行¶
创建一个名为 Step7_build
的新目录。运行 cmake
可执行文件或 cmake-gui
来配置项目,然后使用您选择的构建工具构建它并运行 Tutorial
可执行文件。
这看起来像以下内容
mkdir Step7_build
cd Step7_build
cmake ../Step7
cmake --build .
现在哪个函数能给出更好的结果,sqrt
还是 mysqrt
?
解决方案¶
在本练习中,我们将使用 CheckCXXSourceCompiles
模块中的函数,所以首先我们必须将其包含在 MathFunctions/CMakeLists.txt
中。
TODO 1:点击显示/隐藏答案
include(CheckCXXSourceCompiles)
然后使用 check_cxx_compiles_source
测试 log
和 exp
的可用性。此函数允许我们在真正的源代码编译之前尝试使用所需依赖项编译简单的代码。结果变量 HAVE_LOG
和 HAVE_EXP
表示这些依赖项是否可用。
TODO 2:点击显示/隐藏答案
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)
接下来,我们需要将这些 CMake 变量传递给我们的源代码。这样,我们的源代码就可以知道有哪些资源可用。如果 log
和 exp
都可用,则使用 target_compile_definitions()
来指定 HAVE_LOG
和 HAVE_EXP
作为 PRIVATE
编译定义。
TODO 3:点击显示/隐藏答案
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(SqrtLibrary
PRIVATE "HAVE_LOG" "HAVE_EXP"
)
endif()
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
由于我们可能会使用 log
和 exp
,我们需要修改 mysqrt.cxx
以包含 cmath
。
TODO 4:点击显示/隐藏答案
#include <cmath>
如果 log
和 exp
在系统上可用,那么使用它们在 mysqrt
函数中计算平方根。MathFunctions/mysqrt.cxx
中的 mysqrt
函数将如下所示:
TODO 5:点击显示/隐藏答案
#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