| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 | 
							- # This file is part of CMake-codecov.
 
- #
 
- # Copyright (c)
 
- #   2015-2017 RWTH Aachen University, Federal Republic of Germany
 
- #
 
- # See the LICENSE file in the package base directory for details
 
- #
 
- # Written by Alexander Haase, alexander.haase@rwth-aachen.de
 
- #
 
- # Add an option to choose, if coverage should be enabled or not. If enabled
 
- # marked targets will be build with coverage support and appropriate targets
 
- # will be added. If disabled coverage will be ignored for *ALL* targets.
 
- option(ENABLE_COVERAGE "Enable coverage build." OFF)
 
- set(COVERAGE_FLAG_CANDIDATES
 
- 	# gcc and clang
 
- 	"-O0 -g -fprofile-arcs -ftest-coverage"
 
- 	# gcc and clang fallback
 
- 	"-O0 -g --coverage"
 
- )
 
- # Add coverage support for target ${TNAME} and register target for coverage
 
- # evaluation. If coverage is disabled or not supported, this function will
 
- # simply do nothing.
 
- #
 
- # Note: This function is only a wrapper to define this function always, even if
 
- #   coverage is not supported by the compiler or disabled. This function must
 
- #   be defined here, because the module will be exited, if there is no coverage
 
- #   support by the compiler or it is disabled by the user.
 
- function (add_coverage TNAME)
 
- 	# only add coverage for target, if coverage is support and enabled.
 
- 	if (ENABLE_COVERAGE)
 
- 		foreach (TNAME ${ARGV})
 
- 			add_coverage_target(${TNAME})
 
- 		endforeach ()
 
- 	endif ()
 
- endfunction (add_coverage)
 
- # Add global target to gather coverage information after all targets have been
 
- # added. Other evaluation functions could be added here, after checks for the
 
- # specific module have been passed.
 
- #
 
- # Note: This function is only a wrapper to define this function always, even if
 
- #   coverage is not supported by the compiler or disabled. This function must
 
- #   be defined here, because the module will be exited, if there is no coverage
 
- #   support by the compiler or it is disabled by the user.
 
- function (coverage_evaluate)
 
- 	# add lcov evaluation
 
- 	if (LCOV_FOUND)
 
- 		lcov_capture_initial()
 
- 		lcov_capture()
 
- 	endif (LCOV_FOUND)
 
- endfunction ()
 
- # Exit this module, if coverage is disabled. add_coverage is defined before this
 
- # return, so this module can be exited now safely without breaking any build-
 
- # scripts.
 
- if (NOT ENABLE_COVERAGE)
 
- 	return()
 
- endif ()
 
- # Find the reuired flags foreach language.
 
- set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
 
- set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
 
- get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
 
- foreach (LANG ${ENABLED_LANGUAGES})
 
- 	# Coverage flags are not dependent on language, but the used compiler. So
 
- 	# instead of searching flags foreach language, search flags foreach compiler
 
- 	# used.
 
- 	set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
 
- 	if (NOT COVERAGE_${COMPILER}_FLAGS)
 
- 		foreach (FLAG ${COVERAGE_FLAG_CANDIDATES})
 
- 			if(NOT CMAKE_REQUIRED_QUIET)
 
- 				message(STATUS "Try ${COMPILER} code coverage flag = [${FLAG}]")
 
- 			endif()
 
- 			set(CMAKE_REQUIRED_FLAGS "${FLAG}")
 
- 			unset(COVERAGE_FLAG_DETECTED CACHE)
 
- 			if (${LANG} STREQUAL "C")
 
- 				include(CheckCCompilerFlag)
 
- 				check_c_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
 
- 			elseif (${LANG} STREQUAL "CXX")
 
- 				include(CheckCXXCompilerFlag)
 
- 				check_cxx_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
 
- 			elseif (${LANG} STREQUAL "Fortran")
 
- 				# CheckFortranCompilerFlag was introduced in CMake 3.x. To be
 
- 				# compatible with older Cmake versions, we will check if this
 
- 				# module is present before we use it. Otherwise we will define
 
- 				# Fortran coverage support as not available.
 
- 				include(CheckFortranCompilerFlag OPTIONAL
 
- 					RESULT_VARIABLE INCLUDED)
 
- 				if (INCLUDED)
 
- 					check_fortran_compiler_flag("${FLAG}"
 
- 						COVERAGE_FLAG_DETECTED)
 
- 				elseif (NOT CMAKE_REQUIRED_QUIET)
 
- 					message("-- Performing Test COVERAGE_FLAG_DETECTED")
 
- 					message("-- Performing Test COVERAGE_FLAG_DETECTED - Failed"
 
- 						" (Check not supported)")
 
- 				endif ()
 
- 			endif()
 
- 			if (COVERAGE_FLAG_DETECTED)
 
- 				set(COVERAGE_${COMPILER}_FLAGS "${FLAG}"
 
- 					CACHE STRING "${COMPILER} flags for code coverage.")
 
- 				mark_as_advanced(COVERAGE_${COMPILER}_FLAGS)
 
- 				break()
 
- 			else ()
 
- 				message(WARNING "Code coverage is not available for ${COMPILER}"
 
- 				        " compiler. Targets using this compiler will be "
 
- 				        "compiled without it.")
 
- 			endif ()
 
- 		endforeach ()
 
- 	endif ()
 
- endforeach ()
 
- set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
 
- # Helper function to get the language of a source file.
 
- function (codecov_lang_of_source FILE RETURN_VAR)
 
- 	get_filename_component(FILE_EXT "${FILE}" EXT)
 
- 	string(TOLOWER "${FILE_EXT}" FILE_EXT)
 
- 	string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
 
- 	get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
 
- 	foreach (LANG ${ENABLED_LANGUAGES})
 
- 		list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
 
- 		if (NOT ${TEMP} EQUAL -1)
 
- 			set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
 
- 			return()
 
- 		endif ()
 
- 	endforeach()
 
- 	set(${RETURN_VAR} "" PARENT_SCOPE)
 
- endfunction ()
 
- # Helper function to get the relative path of the source file destination path.
 
- # This path is needed by FindGcov and FindLcov cmake files to locate the
 
- # captured data.
 
- function (codecov_path_of_source FILE RETURN_VAR)
 
- 	string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _source ${FILE})
 
- 	# If expression was found, SOURCEFILE is a generator-expression for an
 
- 	# object library. Currently we found no way to call this function automatic
 
- 	# for the referenced target, so it must be called in the directoryso of the
 
- 	# object library definition.
 
- 	if (NOT "${_source}" STREQUAL "")
 
- 		set(${RETURN_VAR} "" PARENT_SCOPE)
 
- 		return()
 
- 	endif ()
 
- 	string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" FILE "${FILE}")
 
- 	if(IS_ABSOLUTE ${FILE})
 
- 		file(RELATIVE_PATH FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
 
- 	endif()
 
- 	# get the right path for file
 
- 	string(REPLACE ".." "__" PATH "${FILE}")
 
- 	set(${RETURN_VAR} "${PATH}" PARENT_SCOPE)
 
- endfunction()
 
- # Add coverage support for target ${TNAME} and register target for coverage
 
- # evaluation.
 
- function(add_coverage_target TNAME)
 
- 	# Check if all sources for target use the same compiler. If a target uses
 
- 	# e.g. C and Fortran mixed and uses different compilers (e.g. clang and
 
- 	# gfortran) this can trigger huge problems, because different compilers may
 
- 	# use different implementations for code coverage.
 
- 	get_target_property(TSOURCES ${TNAME} SOURCES)
 
- 	set(TARGET_COMPILER "")
 
- 	set(ADDITIONAL_FILES "")
 
- 	foreach (FILE ${TSOURCES})
 
- 		# If expression was found, FILE is a generator-expression for an object
 
- 		# library. Object libraries will be ignored.
 
- 		string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
 
- 		if ("${_file}" STREQUAL "")
 
- 			codecov_lang_of_source(${FILE} LANG)
 
- 			if (LANG)
 
- 				list(APPEND TARGET_COMPILER ${CMAKE_${LANG}_COMPILER_ID})
 
- 				list(APPEND ADDITIONAL_FILES "${FILE}.gcno")
 
- 				list(APPEND ADDITIONAL_FILES "${FILE}.gcda")
 
- 			endif ()
 
- 		endif ()
 
- 	endforeach ()
 
- 	list(REMOVE_DUPLICATES TARGET_COMPILER)
 
- 	list(LENGTH TARGET_COMPILER NUM_COMPILERS)
 
- 	if (NUM_COMPILERS GREATER 1)
 
- 		message(WARNING "Can't use code coverage for target ${TNAME}, because "
 
- 		        "it will be compiled by incompatible compilers. Target will be "
 
- 		        "compiled without code coverage.")
 
- 		return()
 
- 	elseif (NUM_COMPILERS EQUAL 0)
 
- 		message(WARNING "Can't use code coverage for target ${TNAME}, because "
 
- 		        "it uses an unknown compiler. Target will be compiled without "
 
- 		        "code coverage.")
 
- 		return()
 
- 	elseif (NOT DEFINED "COVERAGE_${TARGET_COMPILER}_FLAGS")
 
- 		# A warning has been printed before, so just return if flags for this
 
- 		# compiler aren't available.
 
- 		return()
 
- 	endif()
 
- 	# enable coverage for target
 
- 	set_property(TARGET ${TNAME} APPEND_STRING
 
- 		PROPERTY COMPILE_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
 
- 	set_property(TARGET ${TNAME} APPEND_STRING
 
- 		PROPERTY LINK_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
 
- 	# Add gcov files generated by compiler to clean target.
 
- 	set(CLEAN_FILES "")
 
- 	foreach (FILE ${ADDITIONAL_FILES})
 
- 		codecov_path_of_source(${FILE} FILE)
 
- 		list(APPEND CLEAN_FILES "CMakeFiles/${TNAME}.dir/${FILE}")
 
- 	endforeach()
 
- 	set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
 
- 		"${CLEAN_FILES}")
 
- 	add_gcov_target(${TNAME})
 
- 	add_lcov_target(${TNAME})
 
- endfunction(add_coverage_target)
 
- # Include modules for parsing the collected data and output it in a readable
 
- # format (like gcov and lcov).
 
- find_package(Gcov)
 
- find_package(Lcov)
 
 
  |