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