blob: 5bae2df3aa70ce2d97592b2f1a731b52de7070d8 [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)
# 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
# Global dependencies:
# CPICKER_CACHE_PATH: root directory of the c-picker generated files
function(coverage_generate)
set(_OPTIONS_ARGS)
set(_ONE_VALUE_ARGS NAME 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(TEMP_FILE temp_${_MY_PARAMS_OUTPUT_FILE})
set(OUTPUT_FILE ${_MY_PARAMS_OUTPUT_FILE})
# This is a workaround for running test target before expecting to have coverage.
# Currently there's no other way to set a dependency for this target.
add_custom_command(
OUTPUT test.stamp
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR} -- test
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/test.stamp
)
# 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 ${CMAKE_CURRENT_BINARY_DIR}
--base-directory ${TF_A_PATH}
--output-file ${TEMP_FILE}
COMMAND ${CPICKER_COVERAGE_MAPPER_COMMAND}
--input ${TEMP_FILE}
--output ${OUTPUT_FILE}
--mapping-path ${CPICKER_CACHE_PATH}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/test.stamp
)
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})
# The pattern must be an absolute path ending with an asterisk
get_filename_component(INCLUDE_DIRECTORY_ABSPATH "${_MY_PARAMS_INCLUDE_DIRECTORY}" ABSOLUTE)
set(INCLUDE_DIRECTORY_ABSPATH "${INCLUDE_DIRECTORY_ABSPATH}/*")
add_custom_command(
OUTPUT ${_MY_PARAMS_OUTPUT_FILE}
COMMAND ${LCOV_COMMAND}
--extract ${_MY_PARAMS_INPUT_FILE} \"${INCLUDE_DIRECTORY_ABSPATH}\"
--output-file ${_MY_PARAMS_OUTPUT_FILE}
DEPENDS ${_MY_PARAMS_INPUT_FILE}
)
add_custom_target(coverage_target_${_MY_PARAMS_OUTPUT_FILE} DEPENDS ${_MY_PARAMS_OUTPUT_FILE})
add_dependencies(coverage coverage_target_${_MY_PARAMS_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})
add_custom_command(
OUTPUT ${_MY_PARAMS_OUTPUT_DIRECTORY}
COMMAND genhtml ${_MY_PARAMS_INPUT_FILE}
--show-details
--output-directory ${_MY_PARAMS_OUTPUT_DIRECTORY}
DEPENDS ${_MY_PARAMS_INPUT_FILE}
)
add_custom_target(coverage_report_target_${_MY_PARAMS_INPUT_FILE} DEPENDS ${_MY_PARAMS_OUTPUT_DIRECTORY})
add_dependencies(coverage_report coverage_report_target_${_MY_PARAMS_INPUT_FILE})
endfunction()