cmake设置单元测试目标
目录结构
.
|-- cmake
| |-- CompilerSettings.cmake
| |-- Options.cmake
| |-- ProjectBoost.cmake
| `-- UseOpenSSL.cmake
|-- CMakeLists.txt
|-- hello-cpp
| |-- CMakeLists.txt
| `-- main.cpp
|-- libfoo
| |-- CMakeLists.txt
| |-- Foo.cpp
| `-- Foo.h
`-- test
|-- CMakeLists.txt
|-- test-hello-cpp
| `-- main.cpp
`-- test-libfoo
`-- Foo.cpp
根目录cmake
# cmake版本要求
cmake_minimum_required(VERSION 3.7)
# 项目信息
project(hello-cpp
VERSION 1.0.0
LANGUAGES CXX)
# 添加模块目录(CMAKE_CURRENT_SOURCE_DIR表示当前CMakeList.txt的路径)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# 基本设置
include(Options)
include(CompilerSettings)
print_config()
# 下载安装依赖库
include(UseOpenSSL)
include(ProjectBoost)
# 添加子目录
add_subdirectory(libfoo)
add_subdirectory(${PROJECT_NAME})
# 构建并运行单元测试
if (WITH_TESTS)
enable_testing()
add_subdirectory(test)
endif()
cmake目录
- Options.cmake:用于指定编译特性选项
# 构建类型,支持Debug Release RelWithDebInfo MinSizeRel,默认为RelWithDebInfo
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()
# C++标准,使用C++11
set(CMAKE_CXX_STANDARD 11)
# 是否构建代码覆盖率检测任务
option(WITH_COVERAGE "Test code coverage" OFF)
# 是否构建并运行单元测试
option(WITH_TESTS "Build and run tests" ON)
if (WITH_COVERAGE)
set(WITH_TESTS ON)
endif()
# 显示所有配置信息
macro(print_config)
message("")
message("------------------------------------------------------------------------")
message("-- Configuring ${PROJECT_NAME} ${PROJECT_VERSION}${VERSION_SUFFIX}")
message("------------------------------------------------------------------------")
message("-- CMake Cmake version and location ${CMAKE_VERSION} (${CMAKE_COMMAND})")
message("-- Compiler C++ compiler version ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message("-- TARGET_PLATFORM Target platform ${CMAKE_SYSTEM_NAME}")
message("-- CMAKE_BUILD_TYPE Build type ${CMAKE_BUILD_TYPE}")
message("-- CMAKE_CXX_STANDARD C++ standard ${CMAKE_CXX_STANDARD}")
message("-- WITH_COVERAGE Test code coverage ${WITH_COVERAGE}")
message("-- WITH_TESTS Build and run tests ${WITH_TESTS}")
message("------------------------------------------------------------------------")
message("")
endmacro()
- CompilerSettings.cmake:用于指定编译选项
# 添加根目录到头文件搜索目录
include_directories(BEFORE ${PROJECT_SOURCE_DIR})
# 设置可执行文件输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# 设置编译器选项
if (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
# gcc
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.8+. Current is ${CMAKE_CXX_COMPILER_VERSION}.")
endif()
# 各个编译模式下共用的编译选项
set(CMAKE_CXX_FLAGS "-Wall -Wextra -pthread")
if (WITH_COVERAGE)
set(CMAKE_CXX_FLAGS "-g --coverage ${CMAKE_CXX_FLAGS}")
find_program(LCOV_TOOL lcov)
message(STATUS "lcov tool: ${LCOV_TOOL}")
if (LCOV_TOOL)
add_custom_target(coverage
COMMAND ${LCOV_TOOL} -o ${CMAKE_BINARY_DIR}/coverage.info.in -c -d ${CMAKE_BINARY_DIR}/
COMMAND ${LCOV_TOOL} -r ${CMAKE_BINARY_DIR}/coverage.info.in '/usr*' '${CMAKE_SOURCE_DIR}/deps*' '${CMAKE_SOURCE_DIR}/test*' -o ${CMAKE_BINARY_DIR}/coverage.info
COMMAND genhtml -q -o ${CMAKE_BINARY_DIR}/CodeCoverage ${CMAKE_BINARY_DIR}/coverage.info)
else ()
message(FATAL_ERROR "Can't find lcov tool. Please install lcov")
endif()
endif()
# 各编译模式专有的编译选项
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
else()
message(FATAL_ERROR "Your compiler is not supported.")
endif()
- ProjectBoost.cmake:下载编译boost库
# 导入插件
include(ExternalProject)
include(ProcessorCount)
# 获取cpu核数
ProcessorCount(CORES)
if(CORES EQUAL 0)
set(CORES 1)
endif()
# 配置命令
set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
# 构建命令
set(BOOST_BUILD_TOOL ./b2)
# 编译选项
set(BOOST_CXXFLAGS "cxxflags=-std=c++11")
# 下载构建安装依赖库
ExternalProject_Add(boost
# 项目根目录
PREFIX ${CMAKE_SOURCE_DIR}/deps
# 下载名
DOWNLOAD_NAME boost_1_74_0.tar.bz2
# 下载链接(支持多源下载)
URL https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
# sha256哈希值校验
URL_HASH SHA256=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
# 在源码中构建
BUILD_IN_SOURCE 1
# 配置命令
CONFIGURE_COMMAND ${BOOST_BOOTSTRAP_COMMAND}
# 构建命令
BUILD_COMMAND ${BOOST_BUILD_TOOL} stage
${BOOST_CXXFLAGS}
threading=multi
variant=release
link=static
--layout=system
--with-date_time
--with-regex
--with-serialization
--with-system
--with-test
-j${CORES}
# 安装命令
INSTALL_COMMAND ""
# 日志记录
LOG_CONFIGURE 1
LOG_BUILD 1
LOG_INSTALL 1
)
# boost库头文件目录和库目录
ExternalProject_Get_Property(boost SOURCE_DIR)
set(BOOST_INCLUDE_DIR ${SOURCE_DIR})
set(BOOST_LIBRARY_PREFIX ${SOURCE_DIR}/stage/lib/${CMAKE_STATIC_LIBRARY_PREFIX})
# Boost::Algorithm库
add_library(Boost::Algorithm INTERFACE IMPORTED GLOBAL)
set_property(TARGET Boost::Algorithm PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
add_dependencies(Boost::Algorithm boost)
# Boost::ASIO库
add_library(Boost::ASIO INTERFACE IMPORTED GLOBAL)
set_property(TARGET Boost::ASIO PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
set_property(TARGET Boost::ASIO PROPERTY INTERFACE_LINK_LIBRARIES Boost::DateTime Boost::Regex Boost::Serialization
Boost::System OpenSSL::SSL)
add_dependencies(Boost::ASIO boost)
# Boost::DateTime库
add_library(Boost::DateTime STATIC IMPORTED GLOBAL)
set_property(TARGET Boost::DateTime PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
set_property(TARGET Boost::DateTime PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_PREFIX}boost_date_time${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET Boost::DateTime PROPERTY INTERFACE_LINK_LIBRARIES Boost::Serialization)
add_dependencies(Boost::DateTime boost)
# Boost::Functional库
add_library(Boost::Functional INTERFACE IMPORTED GLOBAL)
set_property(TARGET Boost::Functional PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
add_dependencies(Boost::Functional boost)
# Boost::Multiprecision库
add_library(Boost::Multiprecision INTERFACE IMPORTED GLOBAL)
set_property(TARGET Boost::Multiprecision PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
add_dependencies(Boost::Multiprecision boost)
# Boost::Regex库
add_library(Boost::Regex STATIC IMPORTED GLOBAL)
set_property(TARGET Boost::Regex PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
set_property(TARGET Boost::Regex PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_PREFIX}boost_regex${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(Boost::Regex boost)
# Boost::Serialization库
add_library(Boost::Serialization STATIC IMPORTED GLOBAL)
set_property(TARGET Boost::Serialization PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
set_property(TARGET Boost::Serialization PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_PREFIX}boost_serialization${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(Boost::Serialization boost)
# Boost::System库
add_library(Boost::System STATIC IMPORTED GLOBAL)
set_property(TARGET Boost::System PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
set_property(TARGET Boost::System PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_PREFIX}boost_system${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(Boost::System boost)
# Boost::UnitTestFramework库
add_library(Boost::UnitTestFramework STATIC IMPORTED GLOBAL)
set_property(TARGET Boost::UnitTestFramework PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BOOST_INCLUDE_DIR})
set_property(TARGET Boost::UnitTestFramework PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_PREFIX}boost_unit_test_framework${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(Boost::UnitTestFramework boost)
# 取消临时定义
unset(SOURCE_DIR)
- UseOpenSSL.cmake:ASIO中的ssl特性依赖openssl库:
# OpenSSL::SSL库
add_library(OpenSSL::SSL INTERFACE IMPORTED GLOBAL)
set_property(TARGET OpenSSL::SSL PROPERTY INTERFACE_LINK_LIBRARIES -lssl)
hello-cpp模块cmake
# 获取源文件和头文件列表
file(GLOB SRCS "*.cpp")
file(GLOB HEADERS "*.h")
# 添加可执行目标
add_executable(${PROJECT_NAME} ${SRCS} ${HEADERS})
# 添加依赖库
target_link_libraries(${PROJECT_NAME} PUBLIC libfoo)
libfoo的cmake:
# 获取源文件和头文件列表
file(GLOB SRCS "*.cpp")
file(GLOB HEADERS "*.h")
# 添加可执行目标
add_executable(${PROJECT_NAME} ${SRCS} ${HEADERS})
# 添加依赖库
target_link_libraries(${PROJECT_NAME} PUBLIC libfoo)
test模块cmake
# 获取源文件和头文件列表
file(GLOB_RECURSE SRCS "*.cpp")
file(GLOB_RECURSE HEADERS "*.h")
# 添加可执行目标
add_executable(test-${PROJECT_NAME} ${SRCS} ${HEADERS})
# 添加依赖库
target_link_libraries(test-${PROJECT_NAME} PUBLIC Boost::UnitTestFramework)
target_link_libraries(test-${PROJECT_NAME} PUBLIC libfoo)
# 添加测试目标
add_test(NAME test-${PROJECT_NAME} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ./bin/test-${PROJECT_NAME})
# 自动运行测试
add_custom_command(TARGET test-${PROJECT_NAME} POST_BUILD WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ./bin/test-${PROJECT_NAME})
test模块main函数:
#define BOOST_TEST_MODULE XX_Tests
#include <boost/test/unit_test.hpp>
test模块单元测试:
#include <boost/test/unit_test.hpp>
#include <libfoo/Foo.h>
BOOST_AUTO_TEST_SUITE(FooTests)
BOOST_AUTO_TEST_CASE(sumTest)
{
BOOST_CHECK(10 == sum(4, 6));
}
BOOST_AUTO_TEST_SUITE_END()