blob: 5bae2df3aa70ce2d97592b2f1a731b52de7070d8 [file] [log] [blame]
Imre Kise6bf9e62020-01-20 11:34:24 +01001#
2# Copyright (c) 2020, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6
7include_guard(DIRECTORY)
8
9# Checking GCC
10if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
11 message(FATAL_ERROR "Coverage measurement is only supported when using GCC")
12endif()
13
14# Checking lcov
15find_program(LCOV_COMMAND "lcov")
16if (NOT LCOV_COMMAND)
17 message(FATAL_ERROR "Please install lcov")
18endif()
19
20# Checking c-picker-coverage-mapper
21find_program(CPICKER_COVERAGE_MAPPER_COMMAND "c-picker-coverage-mapper")
22if (NOT CPICKER_COVERAGE_MAPPER_COMMAND)
23 message(FATAL_ERROR "Please install c-picker-coverage-mapper using pip (part of c-picker)")
24endif()
25
26# Checking genhtml
27find_program(GENHTML_COMMAND "genhtml")
28if (NOT GENHTML_COMMAND)
29 message(FATAL_ERROR "Please install genhtml with genhtml (part of lcov)")
30endif()
31
32# Including this file enables code coverage measurement by adding the necessary compiler and
33# linker flags.
34set(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
35set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage -fno-exceptions")
36set(CMAKE_EXE_LINKER_FLAGS "-fprofile-arcs -ftest-coverage")
37
38# Adding custom targets
39add_custom_target(coverage)
40add_custom_target(coverage_report)
41
42# Generates LCOV coverage info file by processing the .gcda and .gcno files.
43# The function also maps coverage of the c-picker generated files to the original source lines
44# Global dependencies:
45# CPICKER_CACHE_PATH: root directory of the c-picker generated files
46function(coverage_generate)
47 set(_OPTIONS_ARGS)
48 set(_ONE_VALUE_ARGS NAME OUTPUT_FILE)
49 set(_MULTI_VALUE_ARGS)
50 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
51
52 set(TEST_NAME ${_MY_PARAMS_NAME})
53 set(TEMP_FILE temp_${_MY_PARAMS_OUTPUT_FILE})
54 set(OUTPUT_FILE ${_MY_PARAMS_OUTPUT_FILE})
55
56 # This is a workaround for running test target before expecting to have coverage.
57 # Currently there's no other way to set a dependency for this target.
58 add_custom_command(
59 OUTPUT test.stamp
60 COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR} -- test
61 COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/test.stamp
62 )
63
64 # Collecting information from .gcda and .gcno files into an lcov .info file
65 # Mapping c-picker generated files' coverage info to the original source lines
66 add_custom_command(
67 OUTPUT ${TEMP_FILE} ${OUTPUT_FILE}
68 COMMAND ${LCOV_COMMAND}
69 --capture
70 --test-name ${TEST_NAME}
71 --directory ${CMAKE_CURRENT_BINARY_DIR}
72 --base-directory ${TF_A_PATH}
73 --output-file ${TEMP_FILE}
74 COMMAND ${CPICKER_COVERAGE_MAPPER_COMMAND}
75 --input ${TEMP_FILE}
76 --output ${OUTPUT_FILE}
77 --mapping-path ${CPICKER_CACHE_PATH}
78 DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/test.stamp
79 )
80endfunction()
81
82# Filters coverage info of files from the matching directory
83function(coverage_filter)
84 set(_OPTIONS_ARGS)
85 set(_ONE_VALUE_ARGS INPUT_FILE OUTPUT_FILE INCLUDE_DIRECTORY)
86 set(_MULTI_VALUE_ARGS)
87 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
88
89 # The pattern must be an absolute path ending with an asterisk
90 get_filename_component(INCLUDE_DIRECTORY_ABSPATH "${_MY_PARAMS_INCLUDE_DIRECTORY}" ABSOLUTE)
91 set(INCLUDE_DIRECTORY_ABSPATH "${INCLUDE_DIRECTORY_ABSPATH}/*")
92
93 add_custom_command(
94 OUTPUT ${_MY_PARAMS_OUTPUT_FILE}
95 COMMAND ${LCOV_COMMAND}
96 --extract ${_MY_PARAMS_INPUT_FILE} \"${INCLUDE_DIRECTORY_ABSPATH}\"
97 --output-file ${_MY_PARAMS_OUTPUT_FILE}
98 DEPENDS ${_MY_PARAMS_INPUT_FILE}
99 )
100
101 add_custom_target(coverage_target_${_MY_PARAMS_OUTPUT_FILE} DEPENDS ${_MY_PARAMS_OUTPUT_FILE})
102 add_dependencies(coverage coverage_target_${_MY_PARAMS_OUTPUT_FILE})
103endfunction()
104
105# Generated an HTML report from the LCOV info file
106function(coverage_generate_report)
107 set(_OPTIONS_ARGS)
108 set(_ONE_VALUE_ARGS INPUT_FILE OUTPUT_DIRECTORY)
109 set(_MULTI_VALUE_ARGS)
110 cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN})
111
112 add_custom_command(
113 OUTPUT ${_MY_PARAMS_OUTPUT_DIRECTORY}
114 COMMAND genhtml ${_MY_PARAMS_INPUT_FILE}
115 --show-details
116 --output-directory ${_MY_PARAMS_OUTPUT_DIRECTORY}
117 DEPENDS ${_MY_PARAMS_INPUT_FILE}
118 )
119
120 add_custom_target(coverage_report_target_${_MY_PARAMS_INPUT_FILE} DEPENDS ${_MY_PARAMS_OUTPUT_DIRECTORY})
121 add_dependencies(coverage_report coverage_report_target_${_MY_PARAMS_INPUT_FILE})
122endfunction()