Существует ли метод кросс-компиляции для отключения флагов покрытия для тестовых исполняемых файлов, использующих CMake?
Я создаю общий шаблон проекта 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
(Внутри 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);
}
}
1 ответ
ОБНОВИТЬ
Следующий код на самом деле не является решением. Он работает только для всех функций, которые определены только в исходных файлах. То есть, если у вас есть библиотека шаблонов или библиотека только с заголовками, то это решение совершенно бесполезно. Истинное решение состоит в том, чтобы вызвать функцию 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)
Существует предостережение для этого решения. Судя по всему, файлы заголовков не включены в покрытие кода...