title: CMake实战四:装置测试和增加环境生成安装包

categories:[实战四]

tags:[CMake]

date: 2021/12/24

作者:hackett

微信公众号:加班猿


1、装置测试

CMake 也能够指定装置规定,以及增加测试。这两个性能别离能够通过在产生 Makefile 后应用 make installmake test 来执行。在 GNU Makefile 里,你可能须要为此编写 installtest 两个伪指标和相应的规定,但在 CMake 里,这样的工作同样只须要简略的调用几条命令。

1.1定制装置规定

首先先在 math/CMakeLists.txt 文件里增加上面两行:

# 指定 MathFunctions 库的装置门路install (TARGETS MathFunctions DESTINATION bin)install (FILES MathFunctions.h DESTINATION include)

指明 MathFunctions 库的装置门路。之后同样批改根目录的 CMakeLists 文件,在开端增加上面几行:

# 指定装置门路install (TARGETS Demo DESTINATION bin)install (FILES "${PROJECT_BINARY_DIR}/config.h"         DESTINATION include)

通过下面的定制,生成的 Demo 文件和 MathFunctions 函数库 libMathFunctions.o 文件将会被复制到 /usr/local/bin 中,而 MathFunctions.h 和生成的 config.h 文件则会被复制到 /usr/local/include 中。咱们能够验证一下(顺带一提的是,这里的 /usr/local/ 是默认装置到的根目录,能够通过批改 CMAKE_INSTALL_PREFIX 变量的值来指定这些文件应该拷贝到哪个根目录):

[root@hackett demo5]# make installConsolidate compiler generated dependencies of target MathFunctions[ 50%] Built target MathFunctionsConsolidate compiler generated dependencies of target demo[100%] Built target demoInstall the project...-- Install configuration: ""-- Installing: /usr/local/bin/demo-- Installing: /usr/local/include/config.h-- Installing: /usr/local/bin/libMathFunctions.a-- Installing: /usr/local/include/myMath.h[root@hackett demo5]# ls /usr/local/bin/demo         libMathFunctions.a               [root@iZwz97bu0gr8vx0j8l6kkzZ demo5]# ls /usr/local/include/config.h    myMath.h

1.2工程增加测试

增加测试同样很简略。CMake 提供了一个称为 CTest 的测试工具。咱们要做的只是在我的项目根目录的 CMakeLists 文件中调用一系列的 add_test 命令。

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)# set the project nameproject(demo5)# 退出一个配置头文件,用于解决 CMake 对源码的设置configure_file (    "${PROJECT_SOURCE_DIR}/config.h.in"    "${PROJECT_BINARY_DIR}/config.h")# 是否应用本人的 MathFunctions 库option (USE_MYMATH        "Use provided math implementation" ON)# 是否退出 MathFunctions 库if (USE_MYMATH)    include_directories ("${PROJECT_SOURCE_DIR}/math")    add_subdirectory (math)    set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)endif (USE_MYMATH)aux_source_directory(. DIR_SRCS)# 指定生成指标add_executable(demo ${DIR_SRCS})target_link_libraries(demo ${EXTRA_LIBS})# 指定装置门路install (TARGETS demo DESTINATION bin)install (FILES "${PROJECT_BINARY_DIR}/config.h"                 DESTINATION include)enable_testing()# 测试程序是否胜利运行add_test (test_run demo 3 2)add_test (test_35_2 demo 35 2)set_tests_properties (test_35_2 PROPERTIES PASS_REGULAR_EXPRESSION "37")add_test (test_5_2 demo 5 2)set_tests_properties (test_5_2 PROPERTIES PASS_REGULAR_EXPRESSION "7")add_test (test_2_3 demo 2 3)set_tests_properties (test_2_3 PROPERTIES PASS_REGULAR_EXPRESSION "5")

下面的代码蕴含了四个测试。第一个测试 test_run 用来测试程序是否胜利运行并返回 0 值。剩下的三个测试别离用来测试 35 + 2 、5 + 2、2 + 3是否都能失去正确的后果。其中 PASS_REGULAR_EXPRESSION 用来测试输入是否蕴含前面跟着的字符串。

测试后果:

[root@hackett demo5]# make Consolidate compiler generated dependencies of target MathFunctions[ 50%] Built target MathFunctionsConsolidate compiler generated dependencies of target demo[ 75%] Building CXX object CMakeFiles/demo.dir/main.cpp.o[100%] Linking CXX executable demo[100%] Built target demo[root@hackett demo5]# make testRunning tests...Test project /root/workspace/cmake/demo5    Start 1: test_run1/4 Test #1: test_run .........................   Passed    0.00 sec    Start 2: test_35_22/4 Test #2: test_35_2 ........................   Passed    0.00 sec    Start 3: test_5_23/4 Test #3: test_5_2 .........................   Passed    0.00 sec    Start 4: test_2_34/4 Test #4: test_2_3 .........................   Passed    0.00 sec100% tests passed, 0 tests failed out of 4Total Test time (real) =   0.01 sec

如果要测试更多的输出数据,像下面那样一个个写测试用例未免太繁琐。这时能够通过编写宏来实现:

# 定义一个宏,用来简化测试工作macro (do_test arg1 arg2 result)  add_test (test_${arg1}_${arg2} demo ${arg1} ${arg2})  set_tests_properties (test_${arg1}_${arg2}    PROPERTIES PASS_REGULAR_EXPRESSION ${result})endmacro (do_test) # 应用该宏进行一系列的数据测试do_test (35 2 "37")do_test (5 52 "7")do_test (2 3 "5")

对于 CTest 的更具体的用法能够通过 man 1 ctest 参考 CTest 的文档。

2、增加版本号

首先批改顶层 CMakeLists 文件,在 project 命令之后退出如下两行:

set (Demo_VERSION_MAJOR 1)set (Demo_VERSION_MINOR 0)

别离指定以后的我的项目的主版本号和副版本号。

之后,为了在代码中获取版本信息,咱们能够批改 config.h.in 文件,增加两个预约义变量:

// the configured options and settings for Tutorial#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@

这样就能够间接在代码中打印版本信息了:

#include <stdio.h>#include <stdlib.h>#include "config.h"#ifdef USE_MYMATH  #include "math/myMath.h"#else  #include <math.h>#endifint sub(int a, int b) {    return (a - b);}int main(int argc, char *argv[]) {    if (argc < 3) {        printf("Usage: %s argv[1] argv[2] \n", argv[0]);        return 1;    }    printf("version : %d.%d\n", Demo_VERSION_MAJOR, Demo_VERSION_MINOR);    int a = atof(argv[1]);    int b = atoi(argv[2]);#ifdef USE_MYMATH    printf("Now we use our own Math library. \n");    int result = add(a, b);    printf("%d + %d = %d\n", a, b, result);#else    printf("Now we use the main.cpp sub function. \n");    int result = sub(a, b);    printf("%d - %d = %d\n", a, b, result);#endif    return 0;}

运行后果:

[root@hackett demo7]# cmake .-- Configuring done-- Generating done-- Build files have been written to: /root/workspace/cmake/demo7[root@hackett demo7]# makeConsolidate compiler generated dependencies of target MathFunctions[ 25%] Building CXX object math/CMakeFiles/MathFunctions.dir/myMath.cpp.o[ 50%] Linking CXX static library libMathFunctions.a[ 50%] Built target MathFunctions[ 75%] Building CXX object CMakeFiles/demo.dir/main.cpp.o[100%] Linking CXX executable demo[100%] Built target demo[root@hackett demo7]# ./demo 2 3 version : 1.0Now we use our own Math library. 2 + 3 = 5

3、生成安装包

如何配置生成各种平台上的安装包,包含二进制安装包和源码安装包。为了实现这个工作,咱们须要用到 CPack ,它同样也是由 CMake 提供的一个工具,专门用于打包。

首先在顶层的 CMakeLists.txt 文件尾部增加上面几行:

# 构建一个 CPack 安装包include (InstallRequiredSystemLibraries)set (CPACK_RESOURCE_FILE_LICENSE  "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")include (CPack)

下面的代码做了以下几个工作:

  1. 导入 InstallRequiredSystemLibraries 模块,以便之后导入 CPack 模块;
  2. 设置一些 CPack 相干变量,包含版权信息和版本信息,其中版本信息用了上一节定义的版本号;
  3. 导入 CPack 模块。

创立一个`License.txt文件

touch License.txt

接下来的工作是像平常一样构建工程,并执行 cpack 命令。

  • 生成二进制安装包:
cpack -C CPackConfig.cmake
  • 生成源码安装包
cpack -C CPackSourceConfig.cmake

咱们能够试一下。在生成我的项目后,执行 cpack -C CPackConfig.cmake 命令:

[root@hackett demo8]# cmake .-- Configuring done-- Generating done-- Build files have been written to: /root/workspace/cmake/demo8[root@hackett demo8]# cpack -C CPackConfig.cmakeCPack: Create package using STGZCPack: Install projectsCPack: - Run preinstall target for: demo8CPack: - Install project: demo8 [CPackConfig.cmake]CPack: Create packageCPack: - package: /root/workspace/cmake/demo8/demo8-1.0.1-Linux.sh generated.CPack: Create package using TGZCPack: Install projectsCPack: - Run preinstall target for: demo8CPack: - Install project: demo8 [CPackConfig.cmake]CPack: Create packageCPack: - package: /root/workspace/cmake/demo8/demo8-1.0.1-Linux.tar.gz generated.CPack: Create package using TZCPack: Install projectsCPack: - Run preinstall target for: demo8CPack: - Install project: demo8 [CPackConfig.cmake]CPack: Create packageCPack: - package: /root/workspace/cmake/demo8/demo8-1.0.1-Linux.tar.Z generated.[root@hackett demo8]# lsCMakeCache.txt  cmake_install.cmake  config.h     CPackConfig.cmake  CPackSourceConfig.cmake  demo                  demo8-1.0.1-Linux.tar.gz  install_manifest.txt  main.cpp  mathCMakeFiles      CMakeLists.txt       config.h.in  _CPack_Packages    CTestTestfile.cmake      demo8-1.0.1-Linux.sh  demo8-1.0.1-Linux.tar.Z   License.txt           Makefile

这 3 个二进制包文件所蕴含的内容是完全相同的。咱们能够执行其中一个。此时会呈现一个由 CPack 主动生成的交互式装置界面:

[root@hackett demo8]# sh demo8-1.0.1-Linux.sh demo8 Installer Version: 1.0.1, Copyright (c) HumanityThis is a self-extracting archive.The archive will be extracted to: /root/workspace/cmake/demo8If you want to stop extracting, please press <ctrl-C>.Do you accept the license? [yn]: yBy default the demo8 will be installed in:  "/root/workspace/cmake/demo8/demo8-1.0.1-Linux"Do you want to include the subdirectory demo8-1.0.1-Linux?Saying no will install in: "/root/workspace/cmake/demo8" [Yn]: yUsing target directory: /root/workspace/cmake/demo8/demo8-1.0.1-LinuxExtracting, please wait...Unpacking finished successfully

实现后提醒装置到了 demo8-1.0.1-Linux 子目录中,咱们能够进去执行该程序:

[root@hackett demo8]# lsCMakeCache.txt  cmake_install.cmake  config.h     CPackConfig.cmake  CPackSourceConfig.cmake  demo               demo8-1.0.1-Linux.sh      demo8-1.0.1-Linux.tar.Z  main.cpp  mathCMakeFiles      CMakeLists.txt       config.h.in  _CPack_Packages    CTestTestfile.cmake      demo8-1.0.1-Linux  demo8-1.0.1-Linux.tar.gz  install_manifest.txt     Makefile[root@hackett demo8]# ./demo8-1.0.1-Linux/bin/demo 3 2version : 1.0Now we use our own Math library. 3 + 2 = 5

如果你感觉文章还不错,能够给个"三连",文章同步到集体微信公众号[加班猿]

我是hackett,咱们下期见

参考文档:

CMake入门实战

CMake Tutorial