1# This file is part of CMake-codecov. 2# 3# Copyright (c) 4# 2015-2017 RWTH Aachen University, Federal Republic of Germany 5# 6# See the LICENSE file in the package base directory for details 7# 8# Written by Alexander Haase, alexander.haase@rwth-aachen.de 9# 10 11 12# include required Modules 13include(FindPackageHandleStandardArgs) 14 15 16# Search for gcov binary. 17set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) 18set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY}) 19 20get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) 21foreach (LANG ${ENABLED_LANGUAGES}) 22 # Gcov evaluation is dependent on the used compiler. Check gcov support for 23 # each compiler that is used. If gcov binary was already found for this 24 # compiler, do not try to find it again. 25 if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN) 26 get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH) 27 28 if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU") 29 # Some distributions like OSX (homebrew) ship gcov with the compiler 30 # version appended as gcov-x. To find this binary we'll build the 31 # suggested binary name with the compiler version. 32 string(REGEX MATCH "^[0-9]+" GCC_VERSION 33 "${CMAKE_${LANG}_COMPILER_VERSION}") 34 35 find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov 36 HINTS ${COMPILER_PATH}) 37 38 elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang") 39 # Some distributions like Debian ship llvm-cov with the compiler 40 # version appended as llvm-cov-x.y. To find this binary we'll build 41 # the suggested binary name with the compiler version. 42 string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION 43 "${CMAKE_${LANG}_COMPILER_VERSION}") 44 45 # llvm-cov prior version 3.5 seems to be not working with coverage 46 # evaluation tools, but these versions are compatible with the gcc 47 # gcov tool. 48 if(LLVM_VERSION VERSION_GREATER 3.4) 49 find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}" 50 "llvm-cov" HINTS ${COMPILER_PATH}) 51 mark_as_advanced(LLVM_COV_BIN) 52 53 if (LLVM_COV_BIN) 54 find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS 55 ${CMAKE_MODULE_PATH}) 56 if (LLVM_COV_WRAPPER) 57 set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "") 58 59 # set additional parameters 60 set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV 61 "LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING 62 "Environment variables for llvm-cov-wrapper.") 63 mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV) 64 endif () 65 endif () 66 endif () 67 68 if (NOT GCOV_BIN) 69 # Fall back to gcov binary if llvm-cov was not found or is 70 # incompatible. This is the default on OSX, but may crash on 71 # recent Linux versions. 72 find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH}) 73 endif () 74 endif () 75 76 77 if (GCOV_BIN) 78 set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING 79 "${LANG} gcov binary.") 80 81 if (NOT CMAKE_REQUIRED_QUIET) 82 message("-- Found gcov evaluation for " 83 "${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}") 84 endif() 85 86 unset(GCOV_BIN CACHE) 87 endif () 88 endif () 89endforeach () 90 91 92 93 94# Add a new global target for all gcov targets. This target could be used to 95# generate the gcov files for the whole project instead of calling <TARGET>-gcov 96# for each target. 97if (NOT TARGET gcov) 98 add_custom_target(gcov) 99endif (NOT TARGET gcov) 100 101 102 103# This function will add gcov evaluation for target <TNAME>. Only sources of 104# this target will be evaluated and no dependencies will be added. It will call 105# Gcov on any source file of <TNAME> once and store the gcov file in the same 106# directory. 107function (add_gcov_target TNAME) 108 set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir) 109 110 # We don't have to check, if the target has support for coverage, thus this 111 # will be checked by add_coverage_target in Findcoverage.cmake. Instead we 112 # have to determine which gcov binary to use. 113 get_target_property(TSOURCES ${TNAME} SOURCES) 114 set(SOURCES "") 115 set(TCOMPILER "") 116 foreach (FILE ${TSOURCES}) 117 codecov_path_of_source(${FILE} FILE) 118 if (NOT "${FILE}" STREQUAL "") 119 codecov_lang_of_source(${FILE} LANG) 120 if (NOT "${LANG}" STREQUAL "") 121 list(APPEND SOURCES "${FILE}") 122 set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID}) 123 endif () 124 endif () 125 endforeach () 126 127 # If no gcov binary was found, coverage data can't be evaluated. 128 if (NOT GCOV_${TCOMPILER}_BIN) 129 message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.") 130 return() 131 endif () 132 133 set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}") 134 set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}") 135 136 137 set(BUFFER "") 138 foreach(FILE ${SOURCES}) 139 get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH) 140 141 # call gcov 142 add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov 143 COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null 144 DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno 145 WORKING_DIRECTORY ${FILE_PATH} 146 ) 147 148 list(APPEND BUFFER ${TDIR}/${FILE}.gcov) 149 endforeach() 150 151 152 # add target for gcov evaluation of <TNAME> 153 add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER}) 154 155 # add evaluation target to the global gcov target. 156 add_dependencies(gcov ${TNAME}-gcov) 157endfunction (add_gcov_target) 158