CMake實戰四:安裝測試和新增環境生成安裝包
title: CMake實戰四:安裝測試和新增環境生成安裝包
categories:[實戰四]
tags:[CMake]
date: 2021/12/24
作者:hackett 微信公眾號:加班猿1、安裝測試
CMake 也可以指定安裝規則,以及新增測試。這兩個功能分別可以通過在產生 Makefile 後使用 make install
和 make test
來執行。在 GNU Makefile 裡,你可能需要為此編寫 install
和 test
兩個偽目標和相應的規則,但在 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 install Consolidate compiler generated dependencies of target MathFunctions [ 50%] Built target MathFunctions Consolidate compiler generated dependencies of target demo [100%] Built target demo Install 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 name
project(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 MathFunctions
Consolidate 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 test
Running tests...
Test project /root/workspace/cmake/demo5
Start 1: test_run
1/4 Test #1: test_run ......................... Passed 0.00 sec
Start 2: test_35_2
2/4 Test #2: test_35_2 ........................ Passed 0.00 sec
Start 3: test_5_2
3/4 Test #3: test_5_2 ......................... Passed 0.00 sec
Start 4: test_2_3
4/4 Test #4: test_2_3 ......................... Passed 0.00 sec
100% tests passed, 0 tests failed out of 4
Total 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>
#endif
int 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]# make
Consolidate 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.0
Now 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)
上面的程式碼做了以下幾個工作:
- 匯入 InstallRequiredSystemLibraries 模組,以便之後匯入 CPack 模組;
- 設定一些 CPack 相關變數,包括版權資訊和版本資訊,其中版本資訊用了上一節定義的版本號;
- 匯入 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.cmake
CPack: Create package using STGZ
CPack: Install projects
CPack: - Run preinstall target for: demo8
CPack: - Install project: demo8 [CPackConfig.cmake]
CPack: Create package
CPack: - package: /root/workspace/cmake/demo8/demo8-1.0.1-Linux.sh generated.
CPack: Create package using TGZ
CPack: Install projects
CPack: - Run preinstall target for: demo8
CPack: - Install project: demo8 [CPackConfig.cmake]
CPack: Create package
CPack: - package: /root/workspace/cmake/demo8/demo8-1.0.1-Linux.tar.gz generated.
CPack: Create package using TZ
CPack: Install projects
CPack: - Run preinstall target for: demo8
CPack: - Install project: demo8 [CPackConfig.cmake]
CPack: Create package
CPack: - package: /root/workspace/cmake/demo8/demo8-1.0.1-Linux.tar.Z generated.
[root@hackett demo8]# ls
CMakeCache.txt cmake_install.cmake config.h CPackConfig.cmake CPackSourceConfig.cmake demo demo8-1.0.1-Linux.tar.gz install_manifest.txt main.cpp math
CMakeFiles 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) Humanity
This is a self-extracting archive.
The archive will be extracted to: /root/workspace/cmake/demo8
If you want to stop extracting, please press <ctrl-C>.
Do you accept the license? [yn]:
y
By 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]:
y
Using target directory: /root/workspace/cmake/demo8/demo8-1.0.1-Linux
Extracting, please wait...
Unpacking finished successfully
完成後提示安裝到了 demo8-1.0.1-Linux 子目錄中,我們可以進去執行該程式:
[root@hackett demo8]# ls
CMakeCache.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 math
CMakeFiles 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 2
version : 1.0
Now we use our own Math library.
3 + 2 = 5
如果你覺得文章還不錯,可以給個"三連",文章同步到個人微信公眾號[加班猿]
我是hackett,我們下期見
參考文件: