Home | History | Annotate | Download | only in CMake
      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 (a] rwth-aachen.de
      9 #
     10 
     11 
     12 # include required Modules
     13 include(FindPackageHandleStandardArgs)
     14 
     15 
     16 # Search for gcov binary.
     17 set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
     18 set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
     19 
     20 get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
     21 foreach (LANG ${ENABLED_LANGUAGES})
     22 	# Gcov evaluation is dependend 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 ()
     89 endforeach ()
     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.
     97 if (NOT TARGET gcov)
     98 	add_custom_target(gcov)
     99 endif (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.
    107 function (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)
    157 endfunction (add_gcov_target)
    158