我正在创建一个我计划在未来使用的通用 C++、CMake 和Catch项目模板,并希望为其启用代码覆盖率报告。为此,我决定将以下 CMake 模块添加到我的模块列表中:CodeCoverage.cmake。我对此的使用基本上归结为以下代码段:
if (ENABLE_COVERAGE AND NOT CMAKE_CONFIGURATION_TYPES)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Coverage in a non-debug build may lead to misleading results! Setting build type to 'Debug'!")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "" FORCE)
endif (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
include(CodeCoverage)
APPEND_COVERAGE_COMPILER_FLAGS()
if (NOT BUILD_TESTS)
message(STATUS "Tests must be enabled in a coverage build! Setting BUILD_TESTS to On!")
set(BUILD_TESTS On CACHE STRING "" FORCE)
endif (NOT BUILD_TESTS)
set(COVERAGE_EXCLUDES 'tests/*')
include(CodeCoverage)
APPEND_COVERAGE_COMPILER_FLAGS()
SETUP_TARGET_FOR_COVERAGE(NAME coverage EXECUTABLE tests DEPENDENCIES coverage)
else (ENABLE_COVERAGE AND NOT CMAKE_CONFIGURATION_TYPES)
# ...
endif (ENABLE_COVERAGE AND NOT CMAKE_CONFIGURATION_TYPES)
细节。
ENABLE_COVERAGE
是我用来启用/禁用代码覆盖的命令行标志,它将使用 lcov/gcov 生成。tests
是运行我所有单元测试的可执行文件的名称。首先我add_subdirectory
用来添加它的文件夹,并在我使用的文件夹内:set(TEST_SOURCES test_hello_world.cpp test_factorial.cpp) add_executable(tests main.cpp ${TEST_SOURCES}) target_link_libraries(tests Project-Name-lib) include(ParseAndAddCatchTests) ParseAndAddCatchTests(tests)
我的问题:
当我通常运行我的make
脚本时,代码很容易编译,包括构建需要大约 10 秒的测试可执行文件。但是,当我为我的代码启用覆盖时,代码会卡在构建main.cpp.o
(Inside tests
)上,并且make
永远不会完成。当我运行时make VERBOSE=1
,我得到以下正在为所述对象运行的命令:
cd project_dir/build/tests && /usr/bin/g++-5
-g -O0 --coverage -fprofile-arcs -ftest-coverage -g -O0
--coverage -fprofile-arcs -ftest-coverage -g
-I/project_dir/include -I/project_dir/build
-std=c++14 -o CMakeFiles/tests.dir/main.cpp.o -c /project_dir/main.cpp
(为了便于阅读,我缩短了一些路径,缩进的行是同一命令的一部分)
显然,即使使用set(COVERAGE_EXCLUDES 'tests/*')
,编译器仍在将覆盖标志附加到测试可执行文件中,我认为这是构建时间缓慢的根源。如果我的结论是正确的,那么我如何告诉编译器不要将这些标志添加到我的测试可执行文件中?如果我的结论不正确,那么如何减少此可执行文件的构建时间?(我不想直接提及标志名称,因为这可能不适用于所有编译器(我的意思是 GCC/Clang))
在旁注中,我的main.cpp
包含:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
一个示例测试文件包含:
#include <project-abbr/factorial.hpp>
#include "catch.hpp"
TEST_CASE("function factorial")
{
SECTION("normal arguments")
{
REQUIRE(factorial(2) == 2);
REQUIRE(factorial(3) == 6);
REQUIRE(factorial(4) == 24);
REQUIRE(factorial(5) == 120);
}
}