步骤 5:安装与测试

练习 1 - 安装规则

通常,仅构建可执行文件还不够,它还应该是可安装的。使用 CMake,我们可以使用 install() 命令来指定安装规则。在 CMake 中为构建提供本地安装通常和你指定一个安装位置和需要安装的目标和文件一样简单。

目标

安装 Tutorial 可执行文件和 MathFunctions 库。

有用的材料

要编辑的文件

  • MathFunctions/CMakeLists.txt

  • CMakeLists.txt

开始

初始代码提供在 Step5 目录中。在此练习中,完成 TODO 1TODO 4

首先,将 MathFunctions/CMakeLists.txt 更新为将 MathFunctionstutorial_compiler_flags 库安装到 lib 目录中。在同一文件中,指定安装 MathFunctions.hinclude 目录所需的安装规则。

然后,更新顶级 CMakeLists.txt 以将 Tutorial 可执行文件安装到 bin 目录中。最后,应该安装任何头文件到 include 目录中。记住,TutorialConfig.hPROJECT_BINARY_DIR 中。

构建并运行

创建一个名为 Step5_build 的新文件夹。运行 cmake 可执行文件或 cmake-gui 来配置项目,然后使用你选择的构建工具构建它。

然后,使用 cmake 命令的 --install 选项运行安装步骤(在 3.15 中引入,旧版本的 CMake 必须使用 make install)从命令行。此步骤将安装适当的头文件、库和可执行文件。例如

cmake --install .

对于多配置工具,不要忘记使用 --config 参数指定配置。

cmake --install . --config Release

如果使用 IDE,只需构建 INSTALL 目标。你可以从命令行像下面那样构建相同的安装目标

cmake --build . --target install --config Debug

CMake 变量 CMAKE_INSTALL_PREFIX 用于确定文件的安装根目录。如果使用 cmake --install 命令,则可以通过 --prefix 参数覆盖安装前缀。例如

cmake --install . --prefix "/home/myuser/installdir"

导航到安装目录并验证已安装的 Tutorial 是否运行。

解决方案

我们项目的安装规则非常简单

  • 对于 MathFunctions,我们希望将库和头文件分别安装到 libinclude 目录。

  • 对于可执行文件 Tutorial,我们希望将可执行文件和已配置的头文件分别安装到 bininclude 目录。

因此在 MathFunctions/CMakeLists.txt 的末尾添加

TODO 1:单击显示/隐藏答案
TODO 1:MathFunctions/CMakeLists.txt
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs} DESTINATION lib)

TODO 2:单击显示/隐藏答案
TODO 2: MathFunctions/CMakeLists.txt
install(FILES MathFunctions.h DESTINATION include)

可执行文件 Tutorial 和已配置标头文件的安装规则类似。在顶级 CMakeLists.txt 的末尾,我们添加

TODO 3、4:点击显示/隐藏答案
CMakeLists.txt
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  DESTINATION include
  )

这就是创建教程的基本本地安装所需的全部内容。

练习 2 - 测试支持

CTest 提供了一种方法,让你可以轻松管理项目的测试。可以通过 add_test() 命令添加测试。虽然此教程没有明确介绍,但 CTest 与 GoogleTest 等其它测试框架之间存在很大的兼容性。

目标

使用 CTest 为可执行文件创建单元测试。

有帮助的资料

要编辑的文件

  • CMakeLists.txt

开始使用

起始源代码在 Step5 目录中提供。在此练习中,完成 TODO 5TODO 9

首先,我们需要启用测试。接下来,使用 add_test() 开始向项目中添加测试。我们会逐步添加 3 个简单测试,然后你可以根据需要添加其它测试。

构建并运行

导航至构建目录并重建应用程序。然后,运行 ctest 可执行文件: ctest -Nctest -VV。对于多配置生成器(例如,Visual Studio),配置类型必须通过 -C <mode> 标志进行指定。例如,要以调试模式运行测试,请在构建目录(而非 Debug 子目录!)中使用 ctest -C Debug -VV。发布模式将从相同位置执行,但使用 -C Release。或者,从 IDE 中构建 RUN_TESTS 目标。

解决方案

让我们测试我们的应用程序。在顶层 CMakeLists.txt 文件的尾部,我们首先需要通过 enable_testing() 命令启用测试。

TODO 5:单击以显示/隐藏答案
TODO 5:CMakeLists.txt
enable_testing()

启用测试后,我们将添加多个基本测试以验证应用程序是否正常运行。首先,我们使用 add_test() 创建一个测试,该测试运行 Tutorial 可执行文件,并传入参数 25。对于此测试,我们不检查可执行文件的计算结果。此测试将验证应用程序是否运行,没有分段错误或其他崩溃,并且具有零返回值。这是 CTest 测试的基本形式。

TODO 6:单击以显示/隐藏答案
TODO 6:CMakeLists.txt
add_test(NAME Runs COMMAND Tutorial 25)

接下来,让我们使用 PASS_REGULAR_EXPRESSION 测试属性来验证测试的输出中是否包含某些字符串。在这种情况下,验证当提供的参数数量不正确时,是否打印使用率信息。

TODO 7:单击以显示/隐藏答案
TODO 7:CMakeLists.txt
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage
  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
  )

我们将添加的下一个测试验证计算值是否真的为平方根。

TODO 8:单击以显示/隐藏答案
TODO 8:CMakeLists.txt
add_test(NAME StandardUse COMMAND Tutorial 4)
set_tests_properties(StandardUse
  PROPERTIES PASS_REGULAR_EXPRESSION "4 is 2"
  )

一次测试不足以让我们相信它对所有传入值都适用。我们应该添加更多测试来验证这一点。为了轻松添加更多测试,我们制作了一个名为 do_test 的函数,该函数运行应用程序并验证为给定输入计算的平方根是否正确。对于每次 do_test 调用,都会向项目添加另一个测试,其中包含基于传入参数的名称、输入和预期结果。

TODO 9: 单击以显示/隐藏答案
TODO 9: CMakeLists.txt
function(do_test target arg result)
  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
  set_tests_properties(Comp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
    )
endfunction()

# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")