xref: /aosp_15_r20/external/cn-cbor/cmake/CoverallsGenerateGcov.cmake (revision 254b1274ba1d768fbd68f5671e61c44001b5d4a8)
1*254b1274SAndroid Build Coastguard Worker#
2*254b1274SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a copy
3*254b1274SAndroid Build Coastguard Worker# of this software and associated documentation files (the "Software"), to deal
4*254b1274SAndroid Build Coastguard Worker# in the Software without restriction, including without limitation the rights
5*254b1274SAndroid Build Coastguard Worker# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6*254b1274SAndroid Build Coastguard Worker# copies of the Software, and to permit persons to whom the Software is
7*254b1274SAndroid Build Coastguard Worker# furnished to do so, subject to the following conditions:
8*254b1274SAndroid Build Coastguard Worker#
9*254b1274SAndroid Build Coastguard Worker# The above copyright notice and this permission notice shall be included in all
10*254b1274SAndroid Build Coastguard Worker# copies or substantial portions of the Software.
11*254b1274SAndroid Build Coastguard Worker#
12*254b1274SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13*254b1274SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14*254b1274SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15*254b1274SAndroid Build Coastguard Worker# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16*254b1274SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17*254b1274SAndroid Build Coastguard Worker# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18*254b1274SAndroid Build Coastguard Worker# SOFTWARE.
19*254b1274SAndroid Build Coastguard Worker#
20*254b1274SAndroid Build Coastguard Worker# Copyright (C) 2014 Joakim Söderberg <[email protected]>
21*254b1274SAndroid Build Coastguard Worker#
22*254b1274SAndroid Build Coastguard Worker# This is intended to be run by a custom target in a CMake project like this.
23*254b1274SAndroid Build Coastguard Worker# 0. Compile program with coverage support.
24*254b1274SAndroid Build Coastguard Worker# 1. Clear coverage data. (Recursively delete *.gcda in build dir)
25*254b1274SAndroid Build Coastguard Worker# 2. Run the unit tests.
26*254b1274SAndroid Build Coastguard Worker# 3. Run this script specifying which source files the coverage should be performed on.
27*254b1274SAndroid Build Coastguard Worker#
28*254b1274SAndroid Build Coastguard Worker# This script will then use gcov to generate .gcov files in the directory specified
29*254b1274SAndroid Build Coastguard Worker# via the COV_PATH var. This should probably be the same as your cmake build dir.
30*254b1274SAndroid Build Coastguard Worker#
31*254b1274SAndroid Build Coastguard Worker# It then parses the .gcov files to convert them into the Coveralls JSON format:
32*254b1274SAndroid Build Coastguard Worker# https://coveralls.io/docs/api
33*254b1274SAndroid Build Coastguard Worker#
34*254b1274SAndroid Build Coastguard Worker# Example for running as standalone CMake script from the command line:
35*254b1274SAndroid Build Coastguard Worker# (Note it is important the -P is at the end...)
36*254b1274SAndroid Build Coastguard Worker# $ cmake -DCOV_PATH=$(pwd)
37*254b1274SAndroid Build Coastguard Worker#         -DCOVERAGE_SRCS="catcierge_rfid.c;catcierge_timer.c"
38*254b1274SAndroid Build Coastguard Worker#         -P ../cmake/CoverallsGcovUpload.cmake
39*254b1274SAndroid Build Coastguard Worker#
40*254b1274SAndroid Build Coastguard WorkerCMAKE_MINIMUM_REQUIRED(VERSION 2.8)
41*254b1274SAndroid Build Coastguard Worker
42*254b1274SAndroid Build Coastguard Worker
43*254b1274SAndroid Build Coastguard Worker#
44*254b1274SAndroid Build Coastguard Worker# Make sure we have the needed arguments.
45*254b1274SAndroid Build Coastguard Worker#
46*254b1274SAndroid Build Coastguard Workerif (NOT COVERALLS_OUTPUT_FILE)
47*254b1274SAndroid Build Coastguard Worker	message(FATAL_ERROR "Coveralls: No coveralls output file specified. Please set COVERALLS_OUTPUT_FILE")
48*254b1274SAndroid Build Coastguard Workerendif()
49*254b1274SAndroid Build Coastguard Worker
50*254b1274SAndroid Build Coastguard Workerif (NOT COV_PATH)
51*254b1274SAndroid Build Coastguard Worker	message(FATAL_ERROR "Coveralls: Missing coverage directory path where gcov files will be generated. Please set COV_PATH")
52*254b1274SAndroid Build Coastguard Workerendif()
53*254b1274SAndroid Build Coastguard Worker
54*254b1274SAndroid Build Coastguard Workerif (NOT COVERAGE_SRCS)
55*254b1274SAndroid Build Coastguard Worker	message(FATAL_ERROR "Coveralls: Missing the list of source files that we should get the coverage data for COVERAGE_SRCS")
56*254b1274SAndroid Build Coastguard Workerendif()
57*254b1274SAndroid Build Coastguard Worker
58*254b1274SAndroid Build Coastguard Workerif (NOT PROJECT_ROOT)
59*254b1274SAndroid Build Coastguard Worker	message(FATAL_ERROR "Coveralls: Missing PROJECT_ROOT.")
60*254b1274SAndroid Build Coastguard Workerendif()
61*254b1274SAndroid Build Coastguard Worker
62*254b1274SAndroid Build Coastguard Worker# Since it's not possible to pass a CMake list properly in the
63*254b1274SAndroid Build Coastguard Worker# "1;2;3" format to an external process, we have replaced the
64*254b1274SAndroid Build Coastguard Worker# ";" with "*", so reverse that here so we get it back into the
65*254b1274SAndroid Build Coastguard Worker# CMake list format.
66*254b1274SAndroid Build Coastguard Workerstring(REGEX REPLACE "\\*" ";" COVERAGE_SRCS ${COVERAGE_SRCS})
67*254b1274SAndroid Build Coastguard Worker
68*254b1274SAndroid Build Coastguard Workerfind_program(GCOV_EXECUTABLE gcov)
69*254b1274SAndroid Build Coastguard Worker
70*254b1274SAndroid Build Coastguard Workerif (NOT GCOV_EXECUTABLE)
71*254b1274SAndroid Build Coastguard Worker	message(FATAL_ERROR "gcov not found! Aborting...")
72*254b1274SAndroid Build Coastguard Workerendif()
73*254b1274SAndroid Build Coastguard Worker
74*254b1274SAndroid Build Coastguard Workerfind_package(Git)
75*254b1274SAndroid Build Coastguard Worker
76*254b1274SAndroid Build Coastguard Worker# TODO: Add these git things to the coveralls json.
77*254b1274SAndroid Build Coastguard Workerif (GIT_FOUND)
78*254b1274SAndroid Build Coastguard Worker	# Branch.
79*254b1274SAndroid Build Coastguard Worker	execute_process(
80*254b1274SAndroid Build Coastguard Worker		COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
81*254b1274SAndroid Build Coastguard Worker		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
82*254b1274SAndroid Build Coastguard Worker		OUTPUT_VARIABLE GIT_BRANCH
83*254b1274SAndroid Build Coastguard Worker		OUTPUT_STRIP_TRAILING_WHITESPACE
84*254b1274SAndroid Build Coastguard Worker	)
85*254b1274SAndroid Build Coastguard Worker
86*254b1274SAndroid Build Coastguard Worker	macro (git_log_format FORMAT_CHARS VAR_NAME)
87*254b1274SAndroid Build Coastguard Worker		execute_process(
88*254b1274SAndroid Build Coastguard Worker			COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%${FORMAT_CHARS}
89*254b1274SAndroid Build Coastguard Worker			WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
90*254b1274SAndroid Build Coastguard Worker			OUTPUT_VARIABLE ${VAR_NAME}
91*254b1274SAndroid Build Coastguard Worker			OUTPUT_STRIP_TRAILING_WHITESPACE
92*254b1274SAndroid Build Coastguard Worker		)
93*254b1274SAndroid Build Coastguard Worker	endmacro()
94*254b1274SAndroid Build Coastguard Worker
95*254b1274SAndroid Build Coastguard Worker	git_log_format(an GIT_AUTHOR_EMAIL)
96*254b1274SAndroid Build Coastguard Worker	git_log_format(ae GIT_AUTHOR_EMAIL)
97*254b1274SAndroid Build Coastguard Worker	git_log_format(cn GIT_COMMITTER_NAME)
98*254b1274SAndroid Build Coastguard Worker	git_log_format(ce GIT_COMMITTER_EMAIL)
99*254b1274SAndroid Build Coastguard Worker	git_log_format(B GIT_COMMIT_MESSAGE)
100*254b1274SAndroid Build Coastguard Worker
101*254b1274SAndroid Build Coastguard Worker	message("Git exe: ${GIT_EXECUTABLE}")
102*254b1274SAndroid Build Coastguard Worker	message("Git branch: ${GIT_BRANCH}")
103*254b1274SAndroid Build Coastguard Worker	message("Git author: ${GIT_AUTHOR_NAME}")
104*254b1274SAndroid Build Coastguard Worker	message("Git e-mail: ${GIT_AUTHOR_EMAIL}")
105*254b1274SAndroid Build Coastguard Worker	message("Git commiter name: ${GIT_COMMITTER_NAME}")
106*254b1274SAndroid Build Coastguard Worker	message("Git commiter e-mail: ${GIT_COMMITTER_EMAIL}")
107*254b1274SAndroid Build Coastguard Worker	message("Git commit message: ${GIT_COMMIT_MESSAGE}")
108*254b1274SAndroid Build Coastguard Worker
109*254b1274SAndroid Build Coastguard Workerendif()
110*254b1274SAndroid Build Coastguard Worker
111*254b1274SAndroid Build Coastguard Worker############################# Macros #########################################
112*254b1274SAndroid Build Coastguard Worker
113*254b1274SAndroid Build Coastguard Worker#
114*254b1274SAndroid Build Coastguard Worker# This macro converts from the full path format gcov outputs:
115*254b1274SAndroid Build Coastguard Worker#
116*254b1274SAndroid Build Coastguard Worker#    /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
117*254b1274SAndroid Build Coastguard Worker#
118*254b1274SAndroid Build Coastguard Worker# to the original source file path the .gcov is for:
119*254b1274SAndroid Build Coastguard Worker#
120*254b1274SAndroid Build Coastguard Worker#   /path/to/project/root/subdir/the_file.c
121*254b1274SAndroid Build Coastguard Worker#
122*254b1274SAndroid Build Coastguard Workermacro(get_source_path_from_gcov_filename _SRC_FILENAME _GCOV_FILENAME)
123*254b1274SAndroid Build Coastguard Worker
124*254b1274SAndroid Build Coastguard Worker	# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
125*254b1274SAndroid Build Coastguard Worker	# ->
126*254b1274SAndroid Build Coastguard Worker	# #path#to#project#root#subdir#the_file.c.gcov
127*254b1274SAndroid Build Coastguard Worker	get_filename_component(_GCOV_FILENAME_WEXT ${_GCOV_FILENAME} NAME)
128*254b1274SAndroid Build Coastguard Worker
129*254b1274SAndroid Build Coastguard Worker	# #path#to#project#root#subdir#the_file.c.gcov -> /path/to/project/root/subdir/the_file.c
130*254b1274SAndroid Build Coastguard Worker	string(REGEX REPLACE "\\.gcov$" "" SRC_FILENAME_TMP ${_GCOV_FILENAME_WEXT})
131*254b1274SAndroid Build Coastguard Worker	string(REGEX REPLACE "\#" "/" SRC_FILENAME_TMP ${SRC_FILENAME_TMP})
132*254b1274SAndroid Build Coastguard Worker	set(${_SRC_FILENAME} "${SRC_FILENAME_TMP}")
133*254b1274SAndroid Build Coastguard Workerendmacro()
134*254b1274SAndroid Build Coastguard Worker
135*254b1274SAndroid Build Coastguard Worker##############################################################################
136*254b1274SAndroid Build Coastguard Worker
137*254b1274SAndroid Build Coastguard Worker# Get the coverage data.
138*254b1274SAndroid Build Coastguard Workerfile(GLOB_RECURSE GCDA_FILES "${COV_PATH}/*.gcda")
139*254b1274SAndroid Build Coastguard Workermessage("GCDA files:")
140*254b1274SAndroid Build Coastguard Worker
141*254b1274SAndroid Build Coastguard Worker# Get a list of all the object directories needed by gcov
142*254b1274SAndroid Build Coastguard Worker# (The directories the .gcda files and .o files are found in)
143*254b1274SAndroid Build Coastguard Worker# and run gcov on those.
144*254b1274SAndroid Build Coastguard Workerforeach(GCDA ${GCDA_FILES})
145*254b1274SAndroid Build Coastguard Worker	message("Process: ${GCDA}")
146*254b1274SAndroid Build Coastguard Worker	message("------------------------------------------------------------------------------")
147*254b1274SAndroid Build Coastguard Worker	get_filename_component(GCDA_DIR ${GCDA} PATH)
148*254b1274SAndroid Build Coastguard Worker
149*254b1274SAndroid Build Coastguard Worker	#
150*254b1274SAndroid Build Coastguard Worker	# The -p below refers to "Preserve path components",
151*254b1274SAndroid Build Coastguard Worker	# This means that the generated gcov filename of a source file will
152*254b1274SAndroid Build Coastguard Worker	# keep the original files entire filepath, but / is replaced with #.
153*254b1274SAndroid Build Coastguard Worker	# Example:
154*254b1274SAndroid Build Coastguard Worker	#
155*254b1274SAndroid Build Coastguard Worker	# /path/to/project/root/build/CMakeFiles/the_file.dir/subdir/the_file.c.gcda
156*254b1274SAndroid Build Coastguard Worker	# ------------------------------------------------------------------------------
157*254b1274SAndroid Build Coastguard Worker	# File '/path/to/project/root/subdir/the_file.c'
158*254b1274SAndroid Build Coastguard Worker	# Lines executed:68.34% of 199
159*254b1274SAndroid Build Coastguard Worker	# /path/to/project/root/subdir/the_file.c:creating '#path#to#project#root#subdir#the_file.c.gcov'
160*254b1274SAndroid Build Coastguard Worker	#
161*254b1274SAndroid Build Coastguard Worker	# If -p is not specified then the file is named only "the_file.c.gcov"
162*254b1274SAndroid Build Coastguard Worker	#
163*254b1274SAndroid Build Coastguard Worker	execute_process(
164*254b1274SAndroid Build Coastguard Worker		COMMAND ${GCOV_EXECUTABLE} -c -p -o ${GCDA_DIR} ${GCDA}
165*254b1274SAndroid Build Coastguard Worker		WORKING_DIRECTORY ${COV_PATH}
166*254b1274SAndroid Build Coastguard Worker	)
167*254b1274SAndroid Build Coastguard Workerendforeach()
168*254b1274SAndroid Build Coastguard Worker
169*254b1274SAndroid Build Coastguard Worker# TODO: Make these be absolute path
170*254b1274SAndroid Build Coastguard Workerfile(GLOB ALL_GCOV_FILES ${COV_PATH}/*.gcov)
171*254b1274SAndroid Build Coastguard Worker
172*254b1274SAndroid Build Coastguard Worker# Get only the filenames to use for filtering.
173*254b1274SAndroid Build Coastguard Worker#set(COVERAGE_SRCS_NAMES "")
174*254b1274SAndroid Build Coastguard Worker#foreach (COVSRC ${COVERAGE_SRCS})
175*254b1274SAndroid Build Coastguard Worker#	get_filename_component(COVSRC_NAME ${COVSRC} NAME)
176*254b1274SAndroid Build Coastguard Worker#	message("${COVSRC} -> ${COVSRC_NAME}")
177*254b1274SAndroid Build Coastguard Worker#	list(APPEND COVERAGE_SRCS_NAMES "${COVSRC_NAME}")
178*254b1274SAndroid Build Coastguard Worker#endforeach()
179*254b1274SAndroid Build Coastguard Worker
180*254b1274SAndroid Build Coastguard Worker#
181*254b1274SAndroid Build Coastguard Worker# Filter out all but the gcov files we want.
182*254b1274SAndroid Build Coastguard Worker#
183*254b1274SAndroid Build Coastguard Worker# We do this by comparing the list of COVERAGE_SRCS filepaths that the
184*254b1274SAndroid Build Coastguard Worker# user wants the coverage data for with the paths of the generated .gcov files,
185*254b1274SAndroid Build Coastguard Worker# so that we only keep the relevant gcov files.
186*254b1274SAndroid Build Coastguard Worker#
187*254b1274SAndroid Build Coastguard Worker# Example:
188*254b1274SAndroid Build Coastguard Worker# COVERAGE_SRCS =
189*254b1274SAndroid Build Coastguard Worker#				/path/to/project/root/subdir/the_file.c
190*254b1274SAndroid Build Coastguard Worker#
191*254b1274SAndroid Build Coastguard Worker# ALL_GCOV_FILES =
192*254b1274SAndroid Build Coastguard Worker#				/path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
193*254b1274SAndroid Build Coastguard Worker#				/path/to/project/root/build/#path#to#project#root#subdir#other_file.c.gcov
194*254b1274SAndroid Build Coastguard Worker#
195*254b1274SAndroid Build Coastguard Worker# Result should be:
196*254b1274SAndroid Build Coastguard Worker# GCOV_FILES =
197*254b1274SAndroid Build Coastguard Worker#				/path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
198*254b1274SAndroid Build Coastguard Worker#
199*254b1274SAndroid Build Coastguard Workerset(GCOV_FILES "")
200*254b1274SAndroid Build Coastguard Worker#message("Look in coverage sources: ${COVERAGE_SRCS}")
201*254b1274SAndroid Build Coastguard Workermessage("\nFilter out unwanted GCOV files:")
202*254b1274SAndroid Build Coastguard Workermessage("===============================")
203*254b1274SAndroid Build Coastguard Worker
204*254b1274SAndroid Build Coastguard Workerset(COVERAGE_SRCS_REMAINING ${COVERAGE_SRCS})
205*254b1274SAndroid Build Coastguard Worker
206*254b1274SAndroid Build Coastguard Workerforeach (GCOV_FILE ${ALL_GCOV_FILES})
207*254b1274SAndroid Build Coastguard Worker
208*254b1274SAndroid Build Coastguard Worker	#
209*254b1274SAndroid Build Coastguard Worker	# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
210*254b1274SAndroid Build Coastguard Worker	# ->
211*254b1274SAndroid Build Coastguard Worker	# /path/to/project/root/subdir/the_file.c
212*254b1274SAndroid Build Coastguard Worker	get_source_path_from_gcov_filename(GCOV_SRC_PATH ${GCOV_FILE})
213*254b1274SAndroid Build Coastguard Worker
214*254b1274SAndroid Build Coastguard Worker	# Is this in the list of source files?
215*254b1274SAndroid Build Coastguard Worker	# TODO: We want to match against relative path filenames from the source file root...
216*254b1274SAndroid Build Coastguard Worker	list(FIND COVERAGE_SRCS ${GCOV_SRC_PATH} WAS_FOUND)
217*254b1274SAndroid Build Coastguard Worker
218*254b1274SAndroid Build Coastguard Worker	if (NOT WAS_FOUND EQUAL -1)
219*254b1274SAndroid Build Coastguard Worker		message("YES: ${GCOV_FILE}")
220*254b1274SAndroid Build Coastguard Worker		list(APPEND GCOV_FILES ${GCOV_FILE})
221*254b1274SAndroid Build Coastguard Worker
222*254b1274SAndroid Build Coastguard Worker		# We remove it from the list, so we don't bother searching for it again.
223*254b1274SAndroid Build Coastguard Worker		# Also files left in COVERAGE_SRCS_REMAINING after this loop ends should
224*254b1274SAndroid Build Coastguard Worker		# have coverage data generated from them (no lines are covered).
225*254b1274SAndroid Build Coastguard Worker		list(REMOVE_ITEM COVERAGE_SRCS_REMAINING ${GCOV_SRC_PATH})
226*254b1274SAndroid Build Coastguard Worker	else()
227*254b1274SAndroid Build Coastguard Worker		message("NO:  ${GCOV_FILE}")
228*254b1274SAndroid Build Coastguard Worker	endif()
229*254b1274SAndroid Build Coastguard Workerendforeach()
230*254b1274SAndroid Build Coastguard Worker
231*254b1274SAndroid Build Coastguard Worker# TODO: Enable setting these
232*254b1274SAndroid Build Coastguard Workerset(JSON_SERVICE_NAME "travis-ci")
233*254b1274SAndroid Build Coastguard Workerset(JSON_SERVICE_JOB_ID $ENV{TRAVIS_JOB_ID})
234*254b1274SAndroid Build Coastguard Worker
235*254b1274SAndroid Build Coastguard Workerset(JSON_TEMPLATE
236*254b1274SAndroid Build Coastguard Worker"{
237*254b1274SAndroid Build Coastguard Worker  \"service_name\": \"\@JSON_SERVICE_NAME\@\",
238*254b1274SAndroid Build Coastguard Worker  \"service_job_id\": \"\@JSON_SERVICE_JOB_ID\@\",
239*254b1274SAndroid Build Coastguard Worker  \"source_files\": \@JSON_GCOV_FILES\@
240*254b1274SAndroid Build Coastguard Worker}"
241*254b1274SAndroid Build Coastguard Worker)
242*254b1274SAndroid Build Coastguard Worker
243*254b1274SAndroid Build Coastguard Workerset(SRC_FILE_TEMPLATE
244*254b1274SAndroid Build Coastguard Worker"{
245*254b1274SAndroid Build Coastguard Worker      \"name\": \"\@GCOV_SRC_REL_PATH\@\",
246*254b1274SAndroid Build Coastguard Worker      \"source_digest\": \"\@GCOV_CONTENTS_MD5\@\",
247*254b1274SAndroid Build Coastguard Worker      \"coverage\": \@GCOV_FILE_COVERAGE\@
248*254b1274SAndroid Build Coastguard Worker  }"
249*254b1274SAndroid Build Coastguard Worker)
250*254b1274SAndroid Build Coastguard Worker
251*254b1274SAndroid Build Coastguard Workermessage("\nGenerate JSON for files:")
252*254b1274SAndroid Build Coastguard Workermessage("=========================")
253*254b1274SAndroid Build Coastguard Worker
254*254b1274SAndroid Build Coastguard Workerset(JSON_GCOV_FILES "[")
255*254b1274SAndroid Build Coastguard Worker
256*254b1274SAndroid Build Coastguard Worker# Read the GCOV files line by line and get the coverage data.
257*254b1274SAndroid Build Coastguard Workerforeach (GCOV_FILE ${GCOV_FILES})
258*254b1274SAndroid Build Coastguard Worker
259*254b1274SAndroid Build Coastguard Worker	get_source_path_from_gcov_filename(GCOV_SRC_PATH ${GCOV_FILE})
260*254b1274SAndroid Build Coastguard Worker	file(RELATIVE_PATH GCOV_SRC_REL_PATH "${PROJECT_ROOT}" "${GCOV_SRC_PATH}")
261*254b1274SAndroid Build Coastguard Worker
262*254b1274SAndroid Build Coastguard Worker	# The new coveralls API doesn't need the entire source (Yay!)
263*254b1274SAndroid Build Coastguard Worker	# However, still keeping that part for now. Will cleanup in the future.
264*254b1274SAndroid Build Coastguard Worker	file(MD5 "${GCOV_SRC_PATH}" GCOV_CONTENTS_MD5)
265*254b1274SAndroid Build Coastguard Worker	message("MD5: ${GCOV_SRC_PATH} = ${GCOV_CONTENTS_MD5}")
266*254b1274SAndroid Build Coastguard Worker
267*254b1274SAndroid Build Coastguard Worker	# Loads the gcov file as a list of lines.
268*254b1274SAndroid Build Coastguard Worker	# (We first open the file and replace all occurences of [] with _
269*254b1274SAndroid Build Coastguard Worker	#  because CMake will fail to parse a line containing unmatched brackets...
270*254b1274SAndroid Build Coastguard Worker	#  also the \ to escaped \n in macros screws up things.)
271*254b1274SAndroid Build Coastguard Worker	# https://public.kitware.com/Bug/view.php?id=15369
272*254b1274SAndroid Build Coastguard Worker	file(READ ${GCOV_FILE} GCOV_CONTENTS)
273*254b1274SAndroid Build Coastguard Worker	string(REPLACE "[" "_" GCOV_CONTENTS "${GCOV_CONTENTS}")
274*254b1274SAndroid Build Coastguard Worker	string(REPLACE "]" "_" GCOV_CONTENTS "${GCOV_CONTENTS}")
275*254b1274SAndroid Build Coastguard Worker	string(REPLACE "\\" "_" GCOV_CONTENTS "${GCOV_CONTENTS}")
276*254b1274SAndroid Build Coastguard Worker	file(WRITE ${GCOV_FILE}_tmp "${GCOV_CONTENTS}")
277*254b1274SAndroid Build Coastguard Worker
278*254b1274SAndroid Build Coastguard Worker	file(STRINGS ${GCOV_FILE}_tmp GCOV_LINES)
279*254b1274SAndroid Build Coastguard Worker	list(LENGTH GCOV_LINES LINE_COUNT)
280*254b1274SAndroid Build Coastguard Worker
281*254b1274SAndroid Build Coastguard Worker	# Instead of trying to parse the source from the
282*254b1274SAndroid Build Coastguard Worker	# gcov file, simply read the file contents from the source file.
283*254b1274SAndroid Build Coastguard Worker	# (Parsing it from the gcov is hard because C-code uses ; in many places
284*254b1274SAndroid Build Coastguard Worker	#  which also happens to be the same as the CMake list delimeter).
285*254b1274SAndroid Build Coastguard Worker	file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE)
286*254b1274SAndroid Build Coastguard Worker
287*254b1274SAndroid Build Coastguard Worker	string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
288*254b1274SAndroid Build Coastguard Worker	string(REGEX REPLACE "\"" "\\\\\"" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
289*254b1274SAndroid Build Coastguard Worker	string(REPLACE "\t" "\\\\t" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
290*254b1274SAndroid Build Coastguard Worker	string(REPLACE "\r" "\\\\r" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
291*254b1274SAndroid Build Coastguard Worker	string(REPLACE "\n" "\\\\n" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
292*254b1274SAndroid Build Coastguard Worker	# According to http://json.org/ these should be escaped as well.
293*254b1274SAndroid Build Coastguard Worker	# Don't know how to do that in CMake however...
294*254b1274SAndroid Build Coastguard Worker	#string(REPLACE "\b" "\\\\b" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
295*254b1274SAndroid Build Coastguard Worker	#string(REPLACE "\f" "\\\\f" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
296*254b1274SAndroid Build Coastguard Worker	#string(REGEX REPLACE "\u([a-fA-F0-9]{4})" "\\\\u\\1" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
297*254b1274SAndroid Build Coastguard Worker
298*254b1274SAndroid Build Coastguard Worker	# We want a json array of coverage data as a single string
299*254b1274SAndroid Build Coastguard Worker	# start building them from the contents of the .gcov
300*254b1274SAndroid Build Coastguard Worker	set(GCOV_FILE_COVERAGE "[")
301*254b1274SAndroid Build Coastguard Worker
302*254b1274SAndroid Build Coastguard Worker	set(GCOV_LINE_COUNT 1) # Line number for the .gcov.
303*254b1274SAndroid Build Coastguard Worker	set(DO_SKIP 0)
304*254b1274SAndroid Build Coastguard Worker	foreach (GCOV_LINE ${GCOV_LINES})
305*254b1274SAndroid Build Coastguard Worker		#message("${GCOV_LINE}")
306*254b1274SAndroid Build Coastguard Worker		# Example of what we're parsing:
307*254b1274SAndroid Build Coastguard Worker		# Hitcount  |Line | Source
308*254b1274SAndroid Build Coastguard Worker		# "        8:   26:        if (!allowed || (strlen(allowed) == 0))"
309*254b1274SAndroid Build Coastguard Worker		string(REGEX REPLACE
310*254b1274SAndroid Build Coastguard Worker			"^([^:]*):([^:]*):(.*)$"
311*254b1274SAndroid Build Coastguard Worker			"\\1;\\2;\\3"
312*254b1274SAndroid Build Coastguard Worker			RES
313*254b1274SAndroid Build Coastguard Worker			"${GCOV_LINE}")
314*254b1274SAndroid Build Coastguard Worker
315*254b1274SAndroid Build Coastguard Worker		# Check if we should exclude lines using the Lcov syntax.
316*254b1274SAndroid Build Coastguard Worker		string(REGEX MATCH "LCOV_EXCL_START" START_SKIP "${GCOV_LINE}")
317*254b1274SAndroid Build Coastguard Worker		string(REGEX MATCH "LCOV_EXCL_END" END_SKIP "${GCOV_LINE}")
318*254b1274SAndroid Build Coastguard Worker		string(REGEX MATCH "LCOV_EXCL_LINE" LINE_SKIP "${GCOV_LINE}")
319*254b1274SAndroid Build Coastguard Worker
320*254b1274SAndroid Build Coastguard Worker		set(RESET_SKIP 0)
321*254b1274SAndroid Build Coastguard Worker		if (LINE_SKIP AND NOT DO_SKIP)
322*254b1274SAndroid Build Coastguard Worker			set(DO_SKIP 1)
323*254b1274SAndroid Build Coastguard Worker			set(RESET_SKIP 1)
324*254b1274SAndroid Build Coastguard Worker		endif()
325*254b1274SAndroid Build Coastguard Worker
326*254b1274SAndroid Build Coastguard Worker		if (START_SKIP)
327*254b1274SAndroid Build Coastguard Worker			set(DO_SKIP 1)
328*254b1274SAndroid Build Coastguard Worker			message("${GCOV_LINE_COUNT}: Start skip")
329*254b1274SAndroid Build Coastguard Worker		endif()
330*254b1274SAndroid Build Coastguard Worker
331*254b1274SAndroid Build Coastguard Worker		if (END_SKIP)
332*254b1274SAndroid Build Coastguard Worker			set(DO_SKIP 0)
333*254b1274SAndroid Build Coastguard Worker		endif()
334*254b1274SAndroid Build Coastguard Worker
335*254b1274SAndroid Build Coastguard Worker		list(LENGTH RES RES_COUNT)
336*254b1274SAndroid Build Coastguard Worker
337*254b1274SAndroid Build Coastguard Worker		if (RES_COUNT GREATER 2)
338*254b1274SAndroid Build Coastguard Worker			list(GET RES 0 HITCOUNT)
339*254b1274SAndroid Build Coastguard Worker			list(GET RES 1 LINE)
340*254b1274SAndroid Build Coastguard Worker			list(GET RES 2 SOURCE)
341*254b1274SAndroid Build Coastguard Worker
342*254b1274SAndroid Build Coastguard Worker			string(STRIP ${HITCOUNT} HITCOUNT)
343*254b1274SAndroid Build Coastguard Worker			string(STRIP ${LINE} LINE)
344*254b1274SAndroid Build Coastguard Worker
345*254b1274SAndroid Build Coastguard Worker			# Lines with 0 line numbers are metadata and can be ignored.
346*254b1274SAndroid Build Coastguard Worker			if (NOT ${LINE} EQUAL 0)
347*254b1274SAndroid Build Coastguard Worker
348*254b1274SAndroid Build Coastguard Worker				if (DO_SKIP)
349*254b1274SAndroid Build Coastguard Worker					set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}null, ")
350*254b1274SAndroid Build Coastguard Worker				else()
351*254b1274SAndroid Build Coastguard Worker					# Translate the hitcount into valid JSON values.
352*254b1274SAndroid Build Coastguard Worker					if (${HITCOUNT} STREQUAL "#####")
353*254b1274SAndroid Build Coastguard Worker						set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}0, ")
354*254b1274SAndroid Build Coastguard Worker					elseif (${HITCOUNT} STREQUAL "-")
355*254b1274SAndroid Build Coastguard Worker						set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}null, ")
356*254b1274SAndroid Build Coastguard Worker					else()
357*254b1274SAndroid Build Coastguard Worker						set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}${HITCOUNT}, ")
358*254b1274SAndroid Build Coastguard Worker					endif()
359*254b1274SAndroid Build Coastguard Worker				endif()
360*254b1274SAndroid Build Coastguard Worker			endif()
361*254b1274SAndroid Build Coastguard Worker		else()
362*254b1274SAndroid Build Coastguard Worker			message(WARNING "Failed to properly parse line (RES_COUNT = ${RES_COUNT}) ${GCOV_FILE}:${GCOV_LINE_COUNT}\n-->${GCOV_LINE}")
363*254b1274SAndroid Build Coastguard Worker		endif()
364*254b1274SAndroid Build Coastguard Worker
365*254b1274SAndroid Build Coastguard Worker		if (RESET_SKIP)
366*254b1274SAndroid Build Coastguard Worker			set(DO_SKIP 0)
367*254b1274SAndroid Build Coastguard Worker		endif()
368*254b1274SAndroid Build Coastguard Worker		math(EXPR GCOV_LINE_COUNT "${GCOV_LINE_COUNT}+1")
369*254b1274SAndroid Build Coastguard Worker	endforeach()
370*254b1274SAndroid Build Coastguard Worker
371*254b1274SAndroid Build Coastguard Worker	message("${GCOV_LINE_COUNT} of ${LINE_COUNT} lines read!")
372*254b1274SAndroid Build Coastguard Worker
373*254b1274SAndroid Build Coastguard Worker	# Advanced way of removing the trailing comma in the JSON array.
374*254b1274SAndroid Build Coastguard Worker	# "[1, 2, 3, " -> "[1, 2, 3"
375*254b1274SAndroid Build Coastguard Worker	string(REGEX REPLACE ",[ ]*$" "" GCOV_FILE_COVERAGE ${GCOV_FILE_COVERAGE})
376*254b1274SAndroid Build Coastguard Worker
377*254b1274SAndroid Build Coastguard Worker	# Append the trailing ] to complete the JSON array.
378*254b1274SAndroid Build Coastguard Worker	set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
379*254b1274SAndroid Build Coastguard Worker
380*254b1274SAndroid Build Coastguard Worker	# Generate the final JSON for this file.
381*254b1274SAndroid Build Coastguard Worker	message("Generate JSON for file: ${GCOV_SRC_REL_PATH}...")
382*254b1274SAndroid Build Coastguard Worker	string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
383*254b1274SAndroid Build Coastguard Worker
384*254b1274SAndroid Build Coastguard Worker	set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
385*254b1274SAndroid Build Coastguard Workerendforeach()
386*254b1274SAndroid Build Coastguard Worker
387*254b1274SAndroid Build Coastguard Worker# Loop through all files we couldn't find any coverage for
388*254b1274SAndroid Build Coastguard Worker# as well, and generate JSON for those as well with 0% coverage.
389*254b1274SAndroid Build Coastguard Workerforeach(NOT_COVERED_SRC ${COVERAGE_SRCS_REMAINING})
390*254b1274SAndroid Build Coastguard Worker
391*254b1274SAndroid Build Coastguard Worker	# Loads the source file as a list of lines.
392*254b1274SAndroid Build Coastguard Worker	file(STRINGS ${NOT_COVERED_SRC} SRC_LINES)
393*254b1274SAndroid Build Coastguard Worker
394*254b1274SAndroid Build Coastguard Worker	set(GCOV_FILE_COVERAGE "[")
395*254b1274SAndroid Build Coastguard Worker	set(GCOV_FILE_SOURCE "")
396*254b1274SAndroid Build Coastguard Worker
397*254b1274SAndroid Build Coastguard Worker	foreach (SOURCE ${SRC_LINES})
398*254b1274SAndroid Build Coastguard Worker		set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}0, ")
399*254b1274SAndroid Build Coastguard Worker
400*254b1274SAndroid Build Coastguard Worker		string(REPLACE "\\" "\\\\" SOURCE "${SOURCE}")
401*254b1274SAndroid Build Coastguard Worker		string(REGEX REPLACE "\"" "\\\\\"" SOURCE "${SOURCE}")
402*254b1274SAndroid Build Coastguard Worker		string(REPLACE "\t" "\\\\t" SOURCE "${SOURCE}")
403*254b1274SAndroid Build Coastguard Worker		string(REPLACE "\r" "\\\\r" SOURCE "${SOURCE}")
404*254b1274SAndroid Build Coastguard Worker		set(GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}${SOURCE}\\n")
405*254b1274SAndroid Build Coastguard Worker	endforeach()
406*254b1274SAndroid Build Coastguard Worker
407*254b1274SAndroid Build Coastguard Worker	# Remove trailing comma, and complete JSON array with ]
408*254b1274SAndroid Build Coastguard Worker	string(REGEX REPLACE ",[ ]*$" "" GCOV_FILE_COVERAGE ${GCOV_FILE_COVERAGE})
409*254b1274SAndroid Build Coastguard Worker	set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
410*254b1274SAndroid Build Coastguard Worker
411*254b1274SAndroid Build Coastguard Worker	# Generate the final JSON for this file.
412*254b1274SAndroid Build Coastguard Worker	message("Generate JSON for non-gcov file: ${NOT_COVERED_SRC}...")
413*254b1274SAndroid Build Coastguard Worker	string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
414*254b1274SAndroid Build Coastguard Worker	set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
415*254b1274SAndroid Build Coastguard Workerendforeach()
416*254b1274SAndroid Build Coastguard Worker
417*254b1274SAndroid Build Coastguard Worker# Get rid of trailing comma.
418*254b1274SAndroid Build Coastguard Workerstring(REGEX REPLACE ",[ ]*$" "" JSON_GCOV_FILES ${JSON_GCOV_FILES})
419*254b1274SAndroid Build Coastguard Workerset(JSON_GCOV_FILES "${JSON_GCOV_FILES}]")
420*254b1274SAndroid Build Coastguard Worker
421*254b1274SAndroid Build Coastguard Worker# Generate the final complete JSON!
422*254b1274SAndroid Build Coastguard Workermessage("Generate final JSON...")
423*254b1274SAndroid Build Coastguard Workerstring(CONFIGURE ${JSON_TEMPLATE} JSON)
424*254b1274SAndroid Build Coastguard Worker
425*254b1274SAndroid Build Coastguard Workerfile(WRITE "${COVERALLS_OUTPUT_FILE}" "${JSON}")
426*254b1274SAndroid Build Coastguard Workermessage("###########################################################################")
427*254b1274SAndroid Build Coastguard Workermessage("Generated coveralls JSON containing coverage data:")
428*254b1274SAndroid Build Coastguard Workermessage("${COVERALLS_OUTPUT_FILE}")
429*254b1274SAndroid Build Coastguard Workermessage("###########################################################################")
430