Step 5: Installing and Testing 注意版本要求3.15
Often, it is not enough to only build an executable, it should also be installable. 可下载的
With CMake, we can specify install rules using the install() command. Supporting local installations for your builds in CMake is often as simple as specifying an install location and the targets and files to be installed. 通常只要指定
Exercise 1 - Install Rules
将文件放到什么位置
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)
install(FILES MathFunctions.h DESTINATION include)CMakeLists.txt
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"DESTINATION include)
解释1
这是一个 CMakeLists.txt 文件中的两个 install()
命令,用于安装生成的可执行文件和头文件。
第一个命令 install(TARGETS Tutorial DESTINATION bin)
将名为 Tutorial
的目标(通常是一个可执行文件)安装到系统的 bin
目录下。在 UNIX 系统上,该目录通常是 /usr/bin
或 /usr/local/bin
,而在 Windows 上,则是 %ProgramFiles%\[Product Name]\bin
。
如果需要安装多个目标,可以在 TARGETS
参数中列出所有目标名称。例如,install(TARGETS Foo Bar Baz DESTINATION bin)
表示将三个目标 Foo
、Bar
和 Baz
安装到 bin
目录下。
第二个命令 install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" DESTINATION include)
将名为 TutorialConfig.h
的文件安装到系统的 include
目录下。该文件通常是由 CMake 通过模板文件生成的,用于包含一些配置信息或预处理变量。
这里使用了 ${PROJECT_BINARY_DIR}
变量来表示 CMake 构建目录下的路径,因为 TutorialConfig.h
是在构建阶段生成的。在安装到其他系统时,PROJECT_BINARY_DIR
变量会被替换成实际的安装目录。
需要注意的是,DESTINATION
参数指定了安装的目标路径,它可以是绝对路径或相对路径。在安装时,CMake 会将所有安装目标复制到该路径下,并根据各自的类型进行适当的处理。例如,可执行文件会被复制到 bin
目录下,库文件会被复制到 lib
目录下,头文件会被复制到 include
目录下。
解释2
这是一个使用 CMake 的 install() 命令安装库文件的示例,其中 if 条件语句判断是否有名为 SqrtLibrary 的目标。
首先,代码定义了一个变量 installable_libs,用于存储需要安装的库文件。该变量包含两个值:MathFunctions 和 tutorial_compiler_flags,它们都是前面定义的库文件。
然后,通过 if(TARGET SqrtLibrary) 条件语句检查是否存在名为 SqrtLibrary 的目标。如果存在,则将其名称添加到 installable_libs 列表中,否则忽略该步骤。
最终,通过 install(TARGETS i n s t a l l a b l e l i b s D E S T I N A T I O N l i b ) 命令将所有库文件安装到系统的 l i b 目录下。 {installable_libs} DESTINATION lib) 命令将所有库文件安装到系统的 lib 目录下。 installablelibsDESTINATIONlib)命令将所有库文件安装到系统的lib目录下。{installable_libs} 是一个变量,它包含要安装的库文件的名称列表。DESTINATION lib 指定了安装目标路径,即 lib 目录。
需要注意的是,install() 命令会在生成 Makefile 或 Visual Studio 项目文件时自动添加到构建过程中。因此,在运行 make install 或构建 VS 项目时,安装操作会自动执行,将可执行文件和库文件以及所需的其他文件安装到指定的目录。
外部的cmakelist
cmake_minimum_required(VERSION 3.15)# set the project name and version
project(Tutorial VERSION 1.0)# specify the C++ standard
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)# add compiler warning flags just when building this project via
# the BUILD_INTERFACE genex
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
target_compile_options(tutorial_compiler_flags INTERFACE"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>""$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)# add the MathFunctions library
add_subdirectory(MathFunctions)# add the executable
add_executable(Tutorial tutorial.cxx)target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC"${PROJECT_BINARY_DIR}")# TODO 3: Install Tutorial in the bin directory
# Hint: Use the TARGETS and DESTINATION parameters# TODO 4: Install TutorialConfig.h to the include directory
# Hint: Use the FILES and DESTINATION parameters# TODO 5: Enable testing# TODO 6: Add a test called Runs which runs the following command:
# $ Tutorial 25# TODO 7: Add a test called Usage which runs the following command:
# $ Tutorial
# Make sure the expected output is displayed.
# Hint: Use the PASS_REGULAR_EXPRESSION property with "Usage.*number"# TODO 8: Add a test which runs the following command:
# $ Tutorial 4
# Make sure the result is correct.
# Hint: Use the PASS_REGULAR_EXPRESSION property with "4 is 2"# TODO 9: Add more tests. Create a function called do_test to avoid copy +
# paste. Test the following values: 4, 9, 5, 7, 25, -25 and 0.0001.
内部cmakelist
add_library(MathFunctions MathFunctions.cxx)# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctionsINTERFACE ${CMAKE_CURRENT_SOURCE_DIR})# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")# library that just does sqrtadd_library(SqrtLibrary STATICmysqrt.cxx)# link our compiler flags interface librarytarget_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()# link our compiler flags interface library
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)# TODO 1: Create a variable called installable_libs that is a list of all
# libraries we want to install (e.g. MathFunctions and tutorial_compiler_flags)
# Then install the installable libraries to the lib folder.
# Hint: Use the TARGETS and DESTINATION parameters# TODO 2: Install the library headers to the include folder.
# Hint: Use the FILES and DESTINATION parameters
Exercise 2 - Testing Support
Navigate to the build directory and rebuild the application. Then, run
the ctest executable: ctest -N and ctest -VV. For multi-config
generators (e.g. Visual Studio), the configuration type must be
specified with the -C flag. For example, to run tests in Debug
mode use ctest -C Debug -VV from the build directory (not the Debug
subdirectory!). Release mode would be executed from the same location
but with a -C Release. Alternatively, build the RUN_TESTS target from
the IDE.
CMakeLists.txt
enable_testing()
add_test(NAME Runs COMMAND Tutorial 25)add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(UsagePROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")add_test(NAME StandardUse COMMAND Tutorial 4) name后面是测试名称 随便起
set_tests_properties(StandardUsePROPERTIES PASS_REGULAR_EXPRESSION "4 is 2")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")
解释 comp$()
Comp${arg} 是一个字符串表达式,它是由两部分组成:
- 字符串 “Comp”
- 变量 arg 的值
使用 ${} 的方式可以将变量的值嵌入到字符串中,从而方便地构建新的字符串。在本例中,使用 a r g 将函数参数 a r g 的值替换到字符串中,从而生成一个新的字符串 C o m p {arg} 将函数参数 arg 的值替换到字符串中,从而生成一个新的字符串 Comp arg将函数参数arg的值替换到字符串中,从而生成一个新的字符串Comp{arg}。
例如,当 arg 的值为 “5” 时,Comp${arg} 的值将会是 “Comp5”。这个字符串用来给测试案例命名,以便于在测试报告中识别每个测试案例的具体名称。
总之,Comp${arg} 是一个字符串表达式,用于根据函数参数 arg 的值动态生成一个字符串。
解释
这是一个使用 CMake 的 add_test()
命令添加测试的示例,其中测试的名称为 Runs
,测试命令为 Tutorial 25
。
首先,使用 add_test()
命令创建一个测试。NAME Runs
指定了测试的名称为 Runs
,而 COMMAND Tutorial 25
则指定了运行测试的命令,即运行 Tutorial
可执行文件,并将参数 25
传递给它。
在构建时,CMake 会自动将 Runs
测试添加到测试套件中,并生成测试驱动程序。可以通过运行 ctest
命令来运行测试,或者在多种持续集成系统中集成测试。
需要注意的是,add_test()
命令还支持其他选项和参数,例如 WORKING_DIRECTORY
、ENVIRONMENT
和 FIXTURES_REQUIRED
等,用于设置测试环境和依赖关系等。可以参考 CMake 文档以了解更多选项和用法。
解释2
ctest
命令用于运行 CMake 项目中的测试。它的语法是 ctest [options] [test]
,其中 options
是选项参数,test
是要运行的测试名称或测试文件名。
在你的示例中,应该使用 -R
选项来指定测试名称,而不是用 -Runs
。正确的命令应该是 ctest -R Runs
。
如果要传递参数给测试程序,可以使用 -E env
选项来设置环境变量,然后在测试程序中读取这些变量。例如,可以使用以下命令来设置环境变量 MY_TEST_PARAM
的值为 25
:
ctest -R Runs -E MY_TEST_PARAM=25
在测试程序中,可以通过读取环境变量 MY_TEST_PARAM
来获取该值。具体来说,在 C++ 中,可以使用 getenv()
函数读取环境变量,例如:
#include <cstdlib>
#include <iostream>int main() {const char* val = std::getenv("MY_TEST_PARAM");int param = val ? std::stoi(val) : 0;std::cout << "MY_TEST_PARAM = " << param << std::endl;return 0;
}
这样,在运行测试时,CTest 会自动将环境变量传递给测试程序,并执行测试程序以进行测试。
解释3
ctest -N
命令用于显示项目中定义的测试列表,而不运行任何测试。它的输出将显示测试名称、测试命令和测试部件等信息。该命令用于列出所有可供运行的测试,以便在运行测试之前对测试进行检查。
在使用 ctest -N
命令时,可以添加其他选项来筛选测试。例如,可以使用 -R
选项来只列出名称符合给定正则表达式的测试,或者使用 -E
选项来排除名称符合给定正则表达式的测试。可以结合使用这两个选项来过滤特定的测试,并只显示感兴趣的测试。
需要注意的是,ctest -N
命令只是列出测试,而不运行它们。如果要运行测试,请使用 ctest
命令,同时指定要运行的测试名称或测试文件名。
解释4
这段代码是在 CMake 中通过 add_test()
命令来为一个名为 Usage
的测试添加测试案例,然后使用 set_tests_properties()
命令为该测试案例设置测试属性。
add_test(NAME Usage COMMAND Tutorial)
创建了一个名为 Usage
的测试,并指定了要运行的命令为 Tutorial
。这意味着在运行测试时,CMake 会执行 Tutorial
可执行文件,并将输出结果与预期结果进行比较。如果测试执行成功,则测试被标记为通过;否则,它将被标记为失败。
接下来,使用 set_tests_properties()
命令为测试案例 Usage
设置了一个测试属性。具体来说,这个属性是 PASS_REGULAR_EXPRESSION
,它指定了一个正则表达式字符串 "Usage:.*number"
。这意味着在比较测试输出结果和预期结果时,CMake 将使用这个正则表达式字符串来匹配输出结果。如果匹配成功,则测试被标记为通过;否则,它将被标记为失败。
总的来说,这段代码的作用是为一个名为 Usage
的测试添加测试案例,并为该测试案例设置预期输出结果,以便在运行测试时自动检查测试执行结果是否正确。如果测试执行成功且输出结果与预期结果匹配,则测试通过;否则,测试失败。
解释 .*
在正则表达式中,“.*” 表示零个或多个任意字符。这个符号组合通常被用于表示匹配任意字符,可以用来匹配不定长度的字符串。
在给定的例子 “Usage:.number" 中,".” 表示匹配在 “Usage:” 和 “number” 之间的所有字符(包括空格、标点符号和其他特殊字符),不论其类型和数量。使用 .* 表示我们不关心中间的任意内容,只要能够匹配 “Usage:” 和 “number” 之间的所有字符。其中,“.” 表示匹配任意单个字符,“*” 表示匹配0次或多次。
因此,该正则表达式可以匹配以 “Usage:” 开头和 “number” 结尾的任意字符串,例如 “Usage: the number is 10” 或 “Usage: this is a test number string for testing” 等。正则表达式的作用是提供了一种灵活且比较精确的方式来匹配和搜索文本数据,可以应用于很多场景,如文本处理、数据抽取、表单验证等。
message 用于终端输出东西
正则表达式字符串
正则表达式字符串是一种用于描述文本模式的字符串表达式。它通常被用来匹配和搜索符合某种规则的文本内容。正则表达式字符串可以包含特殊字符、元字符和限制字符串等内容,用于定义所需匹配的输入模式。
在 CMake 中,正则表达式字符串经常被用于测试属性中,来验证测试案例输出是否与期望值匹配。具体来说,set_tests_properties()
命令中的 PASS_REGULAR_EXPRESSION
属性就是一个正则表达式字符串,用于指定测试输出的预期模式,并验证测试执行结果是否符合预期。
使用正则表达式字符串需要掌握一些基础语法规则,如通配符、字符集、分组、量词等,这些规则均被定义在不同的正则表达式规范中。熟练掌握正则表达式的语法规则可以帮助我们更轻松地编写和调试正则表达式字符串,从而提高代码的可读性和可维护性。
总结来说,正则表达式字符串是一种用于描述文本模式的字符串表达式,通常被用于字符串匹配和搜索中,也经常被用于测试属性中以便在测试过程中自动验证测试结果的正确性。
tutorial cpp代码
// A simple program that computes the square root of a number
#include <cmath>
#include <iostream>
#include <string>#include "MathFunctions.h"
#include "TutorialConfig.h"int main(int argc, char* argv[])
{if (argc < 2) {// report versionstd::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."<< Tutorial_VERSION_MINOR << std::endl;std::cout << "Usage: " << argv[0] << " number" << std::endl;return 1;}// convert input to doubleconst double inputValue = std::stod(argv[1]);const double outputValue = mathfunctions::sqrt(inputValue);std::cout << "The square root of " << inputValue << " is " << outputValue<< std::endl;return 0;
}
注
到这里感觉差不多了 后面有需要再看
https://cmake.org/cmake/help/latest/guide/tutorial/Installing%20and%20Testing.html