forked from RWTH-HPC/CMake-codecov
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFindLcov.cmake
370 lines (305 loc) · 11.5 KB
/
FindLcov.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# This file is part of CMake-codecov.
#
# CMake-codecov is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License and GNU
# Lesser General Public License along with this program. If not, see
#
# http://www.gnu.org/licenses/
#
#
# Copyright (c)
# 2015 RWTH Aachen University, Federal Republic of Germany
#
# Written by Alexander Haase, [email protected]
#
#
# configuration
#
set(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data")
set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init")
set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture")
set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html")
# Search for Gcov which is used by Lcov. If it is not found, we can exit this
# module now.
find_package(Gcov)
if (NOT GCOV_FOUND)
return()
endif (NOT GCOV_FOUND)
# include required Modules
include(FindPackageHandleStandardArgs)
# Search for required lcov binaries.
find_program(LCOV_BIN lcov)
find_program(GENINFO_BIN geninfo)
find_program(GENHTML_BIN genhtml)
find_package_handle_standard_args(lcov
REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN
)
# enable genhtml C++ demangeling, if c++filt is found
set(GENHTML_CPPFILT_FLAG "")
find_program(CPPFILT_BIN c++filt)
if (NOT CPPFILT_BIN STREQUAL "")
set(GENHTML_CPPFILT_FLAG "--demangle-cpp")
endif (NOT CPPFILT_BIN STREQUAL "")
# If Lcov was not found, exit module now.
if (NOT LCOV_FOUND)
return()
endif (NOT LCOV_FOUND)
# Add a new global target to generate initial coverage reports for all targets.
# This target will be used to generate the global initial info file, which is
# used to gather even empty report data.
if (NOT TARGET lcov-capture-init)
add_custom_target(lcov-capture-init)
endif (NOT TARGET lcov-capture-init)
# This function will add initial capture of coverage data for target <TNAME>,
# which is needed to get also data for objects, which were not loaded at
# execution time. It will call geninfo for every source file of <TNAME> once and
# store the info file in the same directory.
function (lcov_capture_initial_tgt TNAME)
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
get_target_property(TSOURCES ${TNAME} SOURCES)
set(GENINFO_FILES "")
set(LCOV_ARGS "")
foreach(FILENAME ${TSOURCES})
# get the right path for filename
string(REPLACE ".." "__" FILE "${FILENAME}")
# get relative path for COMMENT
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${TDIR}/${FILE}")
# generate empty coverage files
set(OUTFILE "${TDIR}/${FILE}.info.init")
add_custom_command(OUTPUT ${OUTFILE}
COMMAND ${GENINFO_BIN}
--base-directory ${PROJECT_SOURCE_DIR}
--gcov-tool ${GCOV_BIN}
--initial
--output-filename ${OUTFILE}
--quiet
${TDIR}/${FILE}.gcno
DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno
COMMENT "capturing initial coverage data for ${FILE_REL}"
)
list(APPEND GENINFO_FILES ${OUTFILE})
list(APPEND LCOV_ARGS -a ${OUTFILE})
endforeach()
# create path for info files
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT})
# Concatenate all files generated by geninfo to a single file per target.
set(OUTFILE "${LCOV_DATA_PATH_INIT}/${TNAME}.info")
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}")
add_custom_command(OUTPUT ${OUTFILE}
COMMAND ${LCOV_BIN}
${LCOV_ARGS}
--base-directory ${PROJECT_SOURCE_DIR}
--no-extern
--gcov-tool ${GCOV_BIN}
--initial
--output-file ${OUTFILE}
--quiet
DEPENDS ${GENINFO_FILES}
COMMENT "Generating ${FILE_REL}"
)
# add target for geninfo file for <TNAME>
add_custom_target(${TNAME}-capture-init DEPENDS ${OUTFILE})
# add geninfo file generation to global lcov-geninfo target
add_dependencies(lcov-capture-init ${TNAME}-capture-init)
set_property(TARGET lcov-capture-init
APPEND
PROPERTY SOURCES ${OUTFILE}
)
endfunction (lcov_capture_initial_tgt)
# This function will generate the global info file for all targets. It has to be
# called after all other CMake functions in the root CMakeLists.txt file, to get
# a full list of all targets that generate coverage data.
function (lcov_capture_initial)
# Get a list of all initial info files
get_target_property(TSOURCES lcov-capture-init SOURCES)
set(GENINFO_FILES "")
set(LCOV_ARGS "")
foreach(FILE ${TSOURCES})
list(APPEND GENINFO_FILES ${FILE})
list(APPEND LCOV_ARGS -a ${FILE})
endforeach()
# Clear sources to avoid error messages
set_property(TARGET lcov-capture-init PROPERTY SOURCES "")
# create path for info files
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT})
# Concatenate all files to a single file
set(OUTFILE "${LCOV_DATA_PATH_INIT}/all_targets.info")
add_custom_command(OUTPUT ${OUTFILE}
COMMAND ${LCOV_BIN}
${LCOV_ARGS}
--base-directory ${PROJECT_SOURCE_DIR}
--no-extern
--gcov-tool ${GCOV_BIN}
--output-file ${OUTFILE}
--quiet
DEPENDS ${GENINFO_FILES}
)
# add dependencie to target lcov-capture-init
add_custom_target(lcov-geninfo-init ALL
DEPENDS ${OUTFILE} lcov-capture-init
)
endfunction (lcov_capture_initial)
# Add a new global target to generate coverage reports for all targets. This
# target will be used to generate the global info file.
if (NOT TARGET lcov-capture)
add_custom_target(lcov-capture)
endif (NOT TARGET lcov-capture)
# This function will add capture of coverage data for target <TNAME>, which is
# needed to get also data for objects, which were not loaded at execution time.
# It will call geninfo for every source file of <TNAME> once and store the info
# file in the same directory.
function (lcov_capture_tgt TNAME)
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)
get_target_property(TSOURCES ${TNAME} SOURCES)
set(GENINFO_FILES "")
set(LCOV_ARGS "")
foreach(FILENAME ${TSOURCES})
# get the right path for file
string(REPLACE ".." "__" FILE "${FILENAME}")
# get relative path for COMMENT
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${TDIR}/${FILE}")
# Generate coverage files. If no .gcda file was generated during
# execution, the empty coverage file will be used instead.
set(OUTFILE "${TDIR}/${FILE}.info")
add_custom_command(OUTPUT ${OUTFILE}
COMMAND test -f "${TDIR}/${FILE}.gcda"
&& ${GENINFO_BIN}
--base-directory ${PROJECT_SOURCE_DIR}
--gcov-tool ${GCOV_BIN}
--output-filename ${OUTFILE}
--quiet
${TDIR}/${FILE}.gcda
|| cp ${OUTFILE}.init ${OUTFILE}
DEPENDS ${TNAME} ${TNAME}-capture-init
COMMENT "capturing coverage data for ${FILE_REL}"
)
list(APPEND GENINFO_FILES ${OUTFILE})
list(APPEND LCOV_ARGS -a ${OUTFILE})
endforeach()
# create path for info files
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE})
# Concatenate all files generated by geninfo to a single file per target.
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info")
string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}")
add_custom_command(OUTPUT ${OUTFILE}
COMMAND ${LCOV_BIN}
${LCOV_ARGS}
--base-directory ${PROJECT_SOURCE_DIR}
--gcov-tool ${GCOV_BIN}
--output-file ${OUTFILE}
--quiet
DEPENDS ${GENINFO_FILES}
COMMENT "Generating ${FILE_REL}"
)
# add target for geninfo file for <TNAME>
add_custom_target(${TNAME}-geninfo DEPENDS ${OUTFILE})
# add geninfo file generation to global lcov-geninfo target
add_dependencies(lcov-capture ${TNAME}-geninfo)
set_property(TARGET lcov-capture
APPEND
PROPERTY SOURCES ${OUTFILE}
)
# create path for html files
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/${TNAME})
# add target for generating html output for this target only.
add_custom_target(${TNAME}-genhtml
COMMAND ${GENHTML_BIN}
--quiet
--baseline-file ${LCOV_DATA_PATH_INIT}/${TNAME}.info
--output-directory ${LCOV_HTML_PATH}/${TNAME}
--title "${CMAKE_PROJECT_NAME} - target ${TNAME}"
--prefix ${PROJECT_SOURCE_DIR}
--sort
${GENHTML_CPPFILT_FLAG}
${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info
DEPENDS ${TNAME}-geninfo ${TNAME}-capture-init
)
endfunction (lcov_capture_tgt)
# This function will generate the global info file for all targets. It has to be
# called after all other CMake functions in the root CMakeLists.txt file, to get
# a full list of all targets that generate coverage data.
function (lcov_capture)
# call lcov_capture_initial to capture initial data after source compiled
lcov_capture_initial()
# Get a list of all initial info files
get_target_property(TSOURCES lcov-capture SOURCES)
set(GENINFO_FILES "")
set(LCOV_ARGS "")
foreach(FILE ${TSOURCES})
list(APPEND GENINFO_FILES ${FILE})
list(APPEND LCOV_ARGS -a ${FILE})
endforeach()
# Clear sources to avoid error messages
set_property(TARGET lcov-capture PROPERTY SOURCES "")
# create path for info files
file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE})
# Concatenate all files to a single file
set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info")
add_custom_command(OUTPUT ${OUTFILE}
COMMAND ${LCOV_BIN}
${LCOV_ARGS}
--base-directory ${PROJECT_SOURCE_DIR}
--no-extern
--gcov-tool ${GCOV_BIN}
--output-file ${OUTFILE}
--quiet
DEPENDS ${GENINFO_FILES}
)
# add dependencie to target lcov-capture-init
add_custom_target(lcov-geninfo DEPENDS ${OUTFILE} lcov-capture)
# create path for html files
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/all_targets)
# Add a new global target for all lcov targets. This target could be used to
# generate the lcov html output for the whole project instead of calling
# <TARGET>-geninfo and <TARGET>-genhtml for each target. It will also be
# used to generate a html site for all project data together instead of one
# for each target.
add_custom_target(lcov
COMMAND ${GENHTML_BIN}
--quiet
--baseline-file ${LCOV_DATA_PATH_INIT}/all_targets.info
--output-directory ${LCOV_HTML_PATH}/all_targets
--title "${CMAKE_PROJECT_NAME}"
--prefix ${PROJECT_SOURCE_DIR}
--sort
${GENHTML_CPPFILT_FLAG}
${LCOV_DATA_PATH_CAPTURE}/all_targets.info
DEPENDS lcov-geninfo lcov-geninfo-init
)
endfunction (lcov_capture)
# This function will add lcov evaluation for target <TNAME>. Only sources of
# this target will be evaluated and no dependencies will be added. It will call
# geninfo on any source file of <TNAME> once and store the info file in the same
# directory.
function (add_lcov_target TNAME)
# capture initial coverage data
lcov_capture_initial_tgt(${TNAME})
# capture coverage data after execution
lcov_capture_tgt(${TNAME})
endfunction (add_lcov_target)
# Add a new global target to generate the lcov html report for the whole project
# instead of calling <TARGET>-genhtml for each target (to create an own report
# for each target). Instead of the lcov target it does not require geninfo for
# all targets, so you have to call <TARGET>-geninfo to generate the info files
# the targets you'd like to have in your report or lcov-geninfo for generating
# info files for all targets before calling lcov-genhtml.
file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/selected_targets)
add_custom_target(lcov-genhtml
COMMAND ${GENHTML_BIN}
--quiet
--output-directory ${LCOV_HTML_PATH}/selected_targets
--title \"${CMAKE_PROJECT_NAME} - targets `find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name \"all_targets.info\" -exec basename {} .info \\\;`\"
--prefix ${PROJECT_SOURCE_DIR}
--sort
${GENHTML_CPPFILT_FLAG}
`find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name \"all_targets.info\"`
)