Я создаю общий C ++, CMake и Ловить шаблон проекта, который я планирую использовать в будущем, и хочу включить отчеты о покрытии кода для него. Для этого я решил добавить следующий модуль 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
(Внутри 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);
}
}
ОБНОВИТЬ
Следующий код на самом деле не является решением. Оно работает только для всех функций, которые определены только в исходных файлах. Это означает, что если у вас есть библиотека шаблонов или библиотека только заголовков, то это решение совершенно бесполезно. Истинное решение является вызвать функцию append_coverage_compiler_flags
что позволяет для полного охвата. Однако, это может привести к зависанию компиляции, как показано в посте ОП …
Хорошо, я немного поэкспериментировал, посмотрел документацию и нашел решение, которое не совсем оптимально, но, тем не менее, работает. Я использовал функцию target_compile_options
добавить только флаги покрытия к нужным целям вместо функции ADD_COVERAGE_COMPILE_FLAGS()
из модуля, следующим образом:
если (НЕ CMAKE_BUILD_TYPE STREQUAL "Debug") сообщение (СОСТОЯНИЕ «Освещение в не отладочной сборке может привести к ошибочным результатам! Установка типа сборки на« Отладка »!») set (CMAKE_BUILD_TYPE "Отладка" CACHE STRING "" FORCE) endif (НЕ CMAKE_BUILD_TYPE STREQUAL "Отладка") включают в себя (покрытие кода) если (НЕ BUILD_TESTS) сообщение (СОСТОЯНИЕ "Тесты должны быть включены в сборку покрытия! Установка BUILD_TESTS на Вкл!") set (BUILD_TESTS On CACHE STRING "" FORCE) endif (НЕ BUILD_TESTS) набор (COVERAGE_EXCLUDES 'тесты / *') включают в себя (покрытие кода) include_directories (включая $ {PROJECT_BINARY_DIR}) add_subdirectory (SRC) target_compile_options (Project-Name-lib PRIVATE "--coverage") target_compile_options (Project-Name PRIVATE "--coverage") SETUP_TARGET_FOR_COVERAGE (покрытие NAME EXECUTABLE тестирует покрытие DEPENDENCIES)
Существует предостережение для этого решения. Судя по всему, файлы заголовков не включены в покрытие кода …
Других решений пока нет …