cmake入门系列总结三

cmake入门系列总结三


版本说明

版本作者日期备注
0.1loon2019.3.13初稿

目录

一、主旨

这节的主旨是安装和测试,为项目添加安装规则和测试支持。

二、安装规则

安装规则非常简单。对于printHelloWorld库,我们通过将以下两行添加到printHelloWorld的CMakeLists.txt文件来设置库和要安装的头文件:

install (TARGETS printHelloWorld DESTINATION bin)
install (FILES printHelloWorld.h DESTINATION include)

对于应用程序,将以下行添加到顶级CMakeLists.txt文件以安装可执行文件和配置的头文件:

# add the install targets
install (TARGETS helloWorld DESTINATION bin)
install (FILES "${PROJECT_SOURCE_DIR}/helloWorldConfig.h"        
         DESTINATION include)

这就是它的全部。此时,您应该能够构建成功,然后键入make install(或从IDE构建INSTALL目标),它将安装相应的头文件,库和可执行文件。CMake变量CMAKE_INSTALL_PREFIX用于确定文件的安装位置。

目录结构(创建一个install目录):

zy@zy-virtual-machine:~/test/cmake_test/hello_world$ tree ./
./
├── build
├── CMakeLists.txt
├── helloWorldConfig.h
├── helloWorldConfig.h.in
├── install
├── main.c
└── printHelloWorld
    ├── CMakeLists.txt
    ├── printHelloWorld.c
    └── printHelloWorld.h

3 directories, 7 files

printHelloWorld目录下的CMakeLists.txt最终:

add_library(printHelloWorld printHelloWorld.c)
install(TARGETS printHelloWorld DESTINATION bin)
install(FILES "printHelloWorld.h" DESTINATION include)

顶级CMakeLists.txt最终:

cmake_minimum_required(VERSION 2.8)
project(helloWorld)

configure_file(
    "${PROJECT_SOURCE_DIR}/helloWorldConfig.h.in"
    "${PROJECT_SOURCE_DIR}/helloWorldConfig.h"
)

include_directories(
    "${PROJECT_SOURCE_DIR}/printHelloWorld"
    "${PROJECT_SOURCE_DIR}"
)
add_subdirectory(printHelloWorld)
 
add_executable(helloWorld main.c)
target_link_libraries(helloWorld printHelloWorld)

install(TARGETS helloWorld DESTINATION bin)
install(FILES "${PROJECT_SOURCE_DIR}/helloWorldConfig.h"
    DESTINATION include)

运行过程及结果(使用-DCMAKE_INSTALL_PREFIX来指定安装路径):

zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zy/test/cmake_test/hello_world/build
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ cmake -DCMAKE_INSTALL_PREFIX=/home/zy/test/cmake_test/hello_world/install/ ..
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zy/test/cmake_test/hello_world/build
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ make
Scanning dependencies of target printHelloWorld
[ 25%] Building C object printHelloWorld/CMakeFiles/printHelloWorld.dir/printHelloWorld.c.o
[ 50%] Linking C static library libprintHelloWorld.a
[ 50%] Built target printHelloWorld
Scanning dependencies of target helloWorld
[ 75%] Building C object CMakeFiles/helloWorld.dir/main.c.o
[100%] Linking C executable helloWorld
[100%] Built target helloWorld
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ make install
[ 50%] Built target printHelloWorld
[100%] Built target helloWorld
Install the project...
-- Install configuration: ""
-- Installing: /home/zy/test/cmake_test/hello_world/install/bin/helloWorld
-- Up-to-date: /home/zy/test/cmake_test/hello_world/install/include/helloWorldConfig.h
-- Installing: /home/zy/test/cmake_test/hello_world/install/bin/libprintHelloWorld.a
-- Up-to-date: /home/zy/test/cmake_test/hello_world/install/include/printHelloWorld.h
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ ./helloWorld 
Use my print hello world library?
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ cd ..
zy@zy-virtual-machine:~/test/cmake_test/hello_world$ cd build/
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ rm * -rf
zy@zy-virtual-machine:~/test/cmake_test/hello_world/build$ cd ..
zy@zy-virtual-machine:~/test/cmake_test/hello_world$ tree .
.
├── build
├── CMakeLists.txt
├── helloWorldConfig.h
├── helloWorldConfig.h.in
├── install
│   ├── bin
│   │   ├── helloWorld
│   │   └── libprintHelloWorld.a
│   └── include
│       ├── helloWorldConfig.h
│       └── printHelloWorld.h
├── main.c
└── printHelloWorld
    ├── CMakeLists.txt
    ├── printHelloWorld.c
    └── printHelloWorld.h

5 directories, 11 files

三、添加测试

添加测试也是一个相当简单的过程。在顶级CMakeLists.txt文件的末尾,我们可以添加许多基本测试来验证应用程序是否正常工作。

include(CTest)

# 测试程序是否可运行
add_test(test_run helloWorld)
# 测试信息是否正确
add_test(helloWorldUsage helloWorld)
set_tests_properties (helloWorldUsage PROPERTIES PASS_REGULAR_EXPRESSION "Use my print hello world library?")

构建完成后,可以运行“ctest”命令行工具来运行测试。第一个测试只是验证应用程序运行,不会发生段错误或以其他方式崩溃,并且返回值为零。这是CTest测试的基本形式。接下来的几个测试都使用PASS_REGULAR_EXPRESSION测试属性来验证测试的输出是否包含某些字符串。

这个时候我们运行,由于运行结果为“Use my print hello world library?”,所以两个测试用例都是通过的(make编译后make test或者ctest均可):

loon@loon-virtual-machine:~/work/cmake_test/helloWorld/build$ make
[ 50%] Built target printHelloWorld
[100%] Built target helloWorld
loon@loon-virtual-machine:~/work/cmake_test/helloWorld/build$ make test
Running tests...
Test project /home/loon/work/cmake_test/helloWorld/build
    Start 1: test_run
1/2 Test #1: test_run .........................   Passed    0.00 sec
    Start 2: helloWorldUsage
2/2 Test #2: helloWorldUsage ..................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) =   0.01 sec
loon@loon-virtual-machine:~/work/cmake_test/helloWorld/build$ ctest 
Test project /home/loon/work/cmake_test/helloWorld/build
    Start 1: test_run
1/2 Test #1: test_run .........................   Passed    0.00 sec
    Start 2: helloWorldUsage
2/2 Test #2: helloWorldUsage ..................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) =   0.02 sec

如果我们再增加一个测试用例:

add_test(error_show helloWorld)
set_tests_properties(error_show PROPERTIES PASS_REGULAR_EXPRESSION "123")

那么由于运行结果中没有“123”这个字符串,那么测试就会报错:

loon@loon-virtual-machine:~/work/cmake_test/helloWorld/build$ make
-- Configuring done
-- Generating done
-- Build files have been written to: /home/loon/work/cmake_test/helloWorld/build
[ 50%] Built target printHelloWorld
[100%] Built target helloWorld
loon@loon-virtual-machine:~/work/cmake_test/helloWorld/build$ ctest 
Test project /home/loon/work/cmake_test/helloWorld/build
    Start 1: test_run
1/3 Test #1: test_run .........................   Passed    0.00 sec
    Start 2: helloWorldUsage
2/3 Test #2: helloWorldUsage ..................   Passed    0.00 sec
    Start 3: error_show
3/3 Test #3: error_show .......................***Failed  Required regular expression not found.Regex=[123
]  0.00 sec

67% tests passed, 1 tests failed out of 3

Total Test time (real) =   0.02 sec

The following tests FAILED:
	  3 - error_show (Failed)
Errors while running CTest

如果要添加大量测试来测试不同的输入值,可以考虑创建如下的宏:

#define a macro to simplify adding tests, then use it
macro (do_test arg result)
  add_test (TutorialComp${arg} Tutorial ${arg})
  set_tests_properties (TutorialComp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
 
# do a bunch of result based tests
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")

对于do_test的每次调用,将根据传递的参数向项目添加另一个测试,其中包含名称,输入和结果。

以上那种就是变量替换的方式,将arg和result做了替换,然后在下面只需要增加do_test表达式即可。

四、最后

其实,总结到这一步,cmake的套路基本上已经有些清晰了,也就和编程语言类似,定义一些变量、特殊字符、表达式、宏、函数等,将我们使用shell脚本和Makefile、测试命令等的过程进行了封装,形成这样一个集构建、编译、测试于一体的工具,让我们能更快更方便的去构建、编译和测试项目。

此外,更多的测试用法可以查找Ctest这个工具,我们明显可以看出这个是用include包含了Ctest来使用test功能的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昵称系统有问题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值