blob: dd1e6ce9e867c9e9d73013dc26aad27d01bb0be0 [file] [log] [blame]
#
# Copyright (c) 2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
include_guard(DIRECTORY)
# Checking GCC
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message(FATAL_ERROR "Coverage measurement is only supported when using GCC")
endif()
# Checking lcov
find_program(LCOV_COMMAND "lcov")
if (NOT LCOV_COMMAND)
message(FATAL_ERROR "Please install lcov")
endif()
# Checking c-picker-coverage-mapper
find_program(CPICKER_COVERAGE_MAPPER_COMMAND "c-picker-coverage-mapper")
if (NOT CPICKER_COVERAGE_MAPPER_COMMAND)
message(FATAL_ERROR "Please install c-picker-coverage-mapper using pip (part of c-picker)")
endif()
# Checking genhtml
find_program(GENHTML_COMMAND "genhtml")
if (NOT GENHTML_COMMAND)
message(FATAL_ERROR "Please install genhtml with genhtml (part of lcov)")
endif()
# Including this file enables code coverage measurement by adding the necessary compiler and
# linker flags.
set(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage -fno-exceptions")
set(CMAKE_EXE_LINKER_FLAGS "-fprofile-arcs -ftest-coverage")
# Adding custom targets
add_custom_target(coverage)
add_custom_target(coverage_report)
# Adds a file to the dependency list of the target by inserting an accessory
# custom target. The name of the custom target is properly escaped.
function(add_coverage_dependency)
set(_OPTIONS_ARGS)
set(_ONE_VALUE_ARGS TARGET DEPENDS)
set(_MULTI_VALUE_ARGS)
cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
set(TARGET ${_MY_PARAMS_TARGET})
set(DEPENDS ${_MY_PARAMS_DEPENDS})
string(REGEX REPLACE "\\/" "_" CUSTOM_TARGET_SUFFIX ${DEPENDS})
add_custom_target(${TARGET}_target_${CUSTOM_TARGET_SUFFIX} DEPENDS ${DEPENDS})
add_dependencies(${TARGET} ${TARGET}_target_${CUSTOM_TARGET_SUFFIX})
endfunction()
# Generates LCOV coverage info file by processing the .gcda and .gcno files.
# The function also maps coverage of the c-picker generated files to the original source lines
function(coverage_generate)
set(_OPTIONS_ARGS)
set(_ONE_VALUE_ARGS NAME SOURCE_DIR BINARY_DIR CPICKER_MAPPING_PATH OUTPUT_FILE)
set(_MULTI_VALUE_ARGS)
cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
set(TEST_NAME ${_MY_PARAMS_NAME})
set(SOURCE_DIR ${_MY_PARAMS_SOURCE_DIR})
set(BINARY_DIR ${_MY_PARAMS_BINARY_DIR})
set(CPICKER_MAPPING_PATH ${_MY_PARAMS_CPICKER_MAPPING_PATH})
set(TEMP_FILE ${_MY_PARAMS_OUTPUT_FILE}_temp)
set(OUTPUT_FILE ${_MY_PARAMS_OUTPUT_FILE})
# Collecting information from .gcda and .gcno files into an lcov .info file
# Mapping c-picker generated files' coverage info to the original source lines
add_custom_command(
OUTPUT ${TEMP_FILE} ${OUTPUT_FILE}
COMMAND ${LCOV_COMMAND}
--capture
--test-name ${TEST_NAME}
--directory ${BINARY_DIR}
--base-directory ${SOURCE_DIR}
--output-file ${TEMP_FILE}
COMMAND ${CPICKER_COVERAGE_MAPPER_COMMAND}
--input ${TEMP_FILE}
--output ${OUTPUT_FILE}
--mapping-path ${CPICKER_MAPPING_PATH}
)
add_coverage_dependency(
TARGET coverage
DEPENDS ${OUTPUT_FILE}
)
endfunction()
# Filters coverage info of files from the matching directory
function(coverage_filter)
set(_OPTIONS_ARGS)
set(_ONE_VALUE_ARGS INPUT_FILE OUTPUT_FILE INCLUDE_DIRECTORY)
set(_MULTI_VALUE_ARGS)
cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
set(INPUT_FILE ${_MY_PARAMS_INPUT_FILE})
set(OUTPUT_FILE ${_MY_PARAMS_OUTPUT_FILE})
set(INCLUDE_DIRECTORY ${_MY_PARAMS_INCLUDE_DIRECTORY})
# The pattern must be an absolute path ending with an asterisk
get_filename_component(INCLUDE_DIRECTORY_ABSPATH "${INCLUDE_DIRECTORY}" ABSOLUTE)
set(INCLUDE_DIRECTORY_ABSPATH "${INCLUDE_DIRECTORY_ABSPATH}/*")
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMAND ${LCOV_COMMAND}
--extract ${INPUT_FILE} \"${INCLUDE_DIRECTORY_ABSPATH}\"
--output-file ${OUTPUT_FILE}
DEPENDS ${INPUT_FILE}
)
add_coverage_dependency(
TARGET coverage
DEPENDS ${OUTPUT_FILE}
)
endfunction()
# Generated an HTML report from the LCOV info file
function(coverage_generate_report)
set(_OPTIONS_ARGS)
set(_ONE_VALUE_ARGS INPUT_FILE OUTPUT_DIRECTORY)
set(_MULTI_VALUE_ARGS)
cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
set(INPUT_FILE ${_MY_PARAMS_INPUT_FILE})
set(OUTPUT_DIRECTORY ${_MY_PARAMS_OUTPUT_DIRECTORY})
add_custom_command(
OUTPUT ${OUTPUT_DIRECTORY}
COMMAND genhtml ${INPUT_FILE}
--show-details
--output-directory ${OUTPUT_DIRECTORY}
DEPENDS ${INPUT_FILE}
)
add_coverage_dependency(
TARGET coverage_report
DEPENDS ${OUTPUT_DIRECTORY}
)
endfunction()