| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 | # 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## configurationset(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data")set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init")set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture")set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html")# Search for Gcov which is used by Lcov.find_package(Gcov)# This function will add lcov evaluation for target <TNAME>. Only sources of# this target will be evaluated and no dependencies will be added. It will call# geninfo on any source file of <TNAME> once and store the info file in the same# directory.## 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_lcov_target TNAME)	if (LCOV_FOUND)		# capture initial coverage data		lcov_capture_initial_tgt(${TNAME})		# capture coverage data after execution		lcov_capture_tgt(${TNAME})	endif ()endfunction (add_lcov_target)# include required Modulesinclude(FindPackageHandleStandardArgs)# Search for required lcov binaries.find_program(LCOV_BIN lcov)find_program(GENINFO_BIN geninfo)find_program(GENHTML_BIN genhtml)find_package_handle_standard_args(lcov	REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN)# enable genhtml C++ demangeling, if c++filt is found.set(GENHTML_CPPFILT_FLAG "")find_program(CPPFILT_BIN c++filt)if (NOT CPPFILT_BIN STREQUAL "")	set(GENHTML_CPPFILT_FLAG "--demangle-cpp")endif (NOT CPPFILT_BIN STREQUAL "")# enable no-external flag for lcov, if available.if (GENINFO_BIN AND NOT DEFINED GENINFO_EXTERN_FLAG)	set(FLAG "")	execute_process(COMMAND ${GENINFO_BIN} --help OUTPUT_VARIABLE GENINFO_HELP)	string(REGEX MATCH "external" GENINFO_RES "${GENINFO_HELP}")	if (GENINFO_RES)		set(FLAG "--no-external")	endif ()	set(GENINFO_EXTERN_FLAG "${FLAG}"		CACHE STRING "Geninfo flag to exclude system sources.")endif ()# If Lcov was not found, exit module now.if (NOT LCOV_FOUND)	return()endif (NOT LCOV_FOUND)# Create directories to be used.file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT})file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE})set(LCOV_REMOVE_PATTERNS "")# This function will merge lcov files to a single target file. Additional lcov# flags may be set with setting LCOV_EXTRA_FLAGS before calling this function.function (lcov_merge_files OUTFILE ...)	# Remove ${OUTFILE} from ${ARGV} and generate lcov parameters with files.	list(REMOVE_AT ARGV 0)	# Generate merged file.	string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}")	add_custom_command(OUTPUT "${OUTFILE}.raw"		COMMAND cat ${ARGV} > ${OUTFILE}.raw		DEPENDS ${ARGV}		COMMENT "Generating ${FILE_REL}"	)	add_custom_command(OUTPUT "${OUTFILE}"		COMMAND ${LCOV_BIN} --quiet -a ${OUTFILE}.raw --output-file ${OUTFILE}			--base-directory ${PROJECT_SOURCE_DIR} ${LCOV_EXTRA_FLAGS}		COMMAND ${LCOV_BIN} --quiet -r ${OUTFILE} ${LCOV_REMOVE_PATTERNS}			--output-file ${OUTFILE} ${LCOV_EXTRA_FLAGS}		DEPENDS ${OUTFILE}.raw		COMMENT "Post-processing ${FILE_REL}"	)endfunction ()# Add a new global target to generate initial coverage reports for all targets.# This target will be used to generate the global initial info file, which is# used to gather even empty report data.if (NOT TARGET lcov-capture-init)	add_custom_target(lcov-capture-init)	set(LCOV_CAPTURE_INIT_FILES "" CACHE INTERNAL "")endif (NOT TARGET lcov-capture-init)# This function will add initial capture of coverage data for target <TNAME>,# which is needed to get also data for objects, which were not loaded at# execution time. It will call geninfo for every source file of <TNAME> once and# store the info file in the same directory.function (lcov_capture_initial_tgt TNAME)	# We don't have to check, if the target has support for coverage, thus this	# will be checked by add_coverage_target in Findcoverage.cmake. Instead we	# have to determine which gcov binary to use.	get_target_property(TSOURCES ${TNAME} SOURCES)	set(SOURCES "")	set(TCOMPILER "")	foreach (FILE ${TSOURCES})		codecov_path_of_source(${FILE} FILE)		if (NOT "${FILE}" STREQUAL "")			codecov_lang_of_source(${FILE} LANG)			if (NOT "${LANG}" STREQUAL "")				list(APPEND SOURCES "${FILE}")				set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})			endif ()		endif ()	endforeach ()	# If no gcov binary was found, coverage data can't be evaluated.	if (NOT GCOV_${TCOMPILER}_BIN)		message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")		return()	endif ()	set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")	set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")	set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)	set(GENINFO_FILES "")	foreach(FILE ${SOURCES})		# generate empty coverage files		set(OUTFILE "${TDIR}/${FILE}.info.init")		list(APPEND GENINFO_FILES ${OUTFILE})		add_custom_command(OUTPUT ${OUTFILE} COMMAND ${GCOV_ENV} ${GENINFO_BIN}				--quiet --base-directory ${PROJECT_SOURCE_DIR} --initial				--gcov-tool ${GCOV_BIN} --output-filename ${OUTFILE}				${GENINFO_EXTERN_FLAG} ${TDIR}/${FILE}.gcno			DEPENDS ${TNAME}			COMMENT "Capturing initial coverage data for ${FILE}"		)	endforeach()	# Concatenate all files generated by geninfo to a single file per target.	set(OUTFILE "${LCOV_DATA_PATH_INIT}/${TNAME}.info")	set(LCOV_EXTRA_FLAGS "--initial")	lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})	add_custom_target(${TNAME}-capture-init ALL DEPENDS ${OUTFILE})	# add geninfo file generation to global lcov-geninfo target	add_dependencies(lcov-capture-init ${TNAME}-capture-init)	set(LCOV_CAPTURE_INIT_FILES "${LCOV_CAPTURE_INIT_FILES}"		"${OUTFILE}" CACHE INTERNAL ""	)endfunction (lcov_capture_initial_tgt)# This function will generate the global info file for all targets. It has to be# called after all other CMake functions in the root CMakeLists.txt file, to get# a full list of all targets that generate coverage data.function (lcov_capture_initial)	# Skip this function (and do not create the following targets), if there are	# no input files.	if ("${LCOV_CAPTURE_INIT_FILES}" STREQUAL "")		return()	endif ()	# Add a new target to merge the files of all targets.	set(OUTFILE "${LCOV_DATA_PATH_INIT}/all_targets.info")	lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_INIT_FILES})	add_custom_target(lcov-geninfo-init ALL	DEPENDS ${OUTFILE}		lcov-capture-init	)endfunction (lcov_capture_initial)# Add a new global target to generate coverage reports for all targets. This# target will be used to generate the global info file.if (NOT TARGET lcov-capture)	add_custom_target(lcov-capture)	set(LCOV_CAPTURE_FILES "" CACHE INTERNAL "")endif (NOT TARGET lcov-capture)# This function will add capture of coverage data for target <TNAME>, which is# needed to get also data for objects, which were not loaded at execution time.# It will call geninfo for every source file of <TNAME> once and store the info# file in the same directory.function (lcov_capture_tgt TNAME)	# We don't have to check, if the target has support for coverage, thus this	# will be checked by add_coverage_target in Findcoverage.cmake. Instead we	# have to determine which gcov binary to use.	get_target_property(TSOURCES ${TNAME} SOURCES)	set(SOURCES "")	set(TCOMPILER "")	foreach (FILE ${TSOURCES})		codecov_path_of_source(${FILE} FILE)		if (NOT "${FILE}" STREQUAL "")			codecov_lang_of_source(${FILE} LANG)			if (NOT "${LANG}" STREQUAL "")				list(APPEND SOURCES "${FILE}")				set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})			endif ()		endif ()	endforeach ()	# If no gcov binary was found, coverage data can't be evaluated.	if (NOT GCOV_${TCOMPILER}_BIN)		message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")		return()	endif ()	set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")	set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")	set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)	set(GENINFO_FILES "")	foreach(FILE ${SOURCES})		# Generate coverage files. If no .gcda file was generated during		# execution, the empty coverage file will be used instead.		set(OUTFILE "${TDIR}/${FILE}.info")		list(APPEND GENINFO_FILES ${OUTFILE})		add_custom_command(OUTPUT ${OUTFILE}			COMMAND test -f "${TDIR}/${FILE}.gcda"				&& ${GCOV_ENV} ${GENINFO_BIN} --quiet --base-directory					${PROJECT_SOURCE_DIR} --gcov-tool ${GCOV_BIN}					--output-filename ${OUTFILE} ${GENINFO_EXTERN_FLAG}					${TDIR}/${FILE}.gcda				|| cp ${OUTFILE}.init ${OUTFILE}			DEPENDS ${TNAME} ${TNAME}-capture-init			COMMENT "Capturing coverage data for ${FILE}"		)	endforeach()	# Concatenate all files generated by geninfo to a single file per target.	set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info")	lcov_merge_files("${OUTFILE}" ${GENINFO_FILES})	add_custom_target(${TNAME}-geninfo DEPENDS ${OUTFILE})	# add geninfo file generation to global lcov-capture target	add_dependencies(lcov-capture ${TNAME}-geninfo)	set(LCOV_CAPTURE_FILES "${LCOV_CAPTURE_FILES}" "${OUTFILE}" CACHE INTERNAL		""	)	# Add target for generating html output for this target only.	file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/${TNAME})	add_custom_target(${TNAME}-genhtml		COMMAND ${GENHTML_BIN} --quiet --sort --prefix ${PROJECT_SOURCE_DIR}			--baseline-file ${LCOV_DATA_PATH_INIT}/${TNAME}.info			--output-directory ${LCOV_HTML_PATH}/${TNAME}			--title "${CMAKE_PROJECT_NAME} - target ${TNAME}"			${GENHTML_CPPFILT_FLAG} ${OUTFILE}		DEPENDS ${TNAME}-geninfo ${TNAME}-capture-init	)endfunction (lcov_capture_tgt)# This function will generate the global info file for all targets. It has to be# called after all other CMake functions in the root CMakeLists.txt file, to get# a full list of all targets that generate coverage data.function (lcov_capture)	# Skip this function (and do not create the following targets), if there are	# no input files.	if ("${LCOV_CAPTURE_FILES}" STREQUAL "")		return()	endif ()	# Add a new target to merge the files of all targets.	set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info")	lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_FILES})	add_custom_target(lcov-geninfo DEPENDS ${OUTFILE} lcov-capture)	# Add a new global target for all lcov targets. This target could be used to	# generate the lcov html output for the whole project instead of calling	# <TARGET>-geninfo and <TARGET>-genhtml for each target. It will also be	# used to generate a html site for all project data together instead of one	# for each target.	if (NOT TARGET lcov)		file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/all_targets)		add_custom_target(lcov			COMMAND ${GENHTML_BIN} --quiet --sort				--baseline-file ${LCOV_DATA_PATH_INIT}/all_targets.info				--output-directory ${LCOV_HTML_PATH}/all_targets				--title "${CMAKE_PROJECT_NAME}" --prefix "${PROJECT_SOURCE_DIR}"				${GENHTML_CPPFILT_FLAG} ${OUTFILE}			DEPENDS lcov-geninfo-init lcov-geninfo		)	endif ()endfunction (lcov_capture)# Add a new global target to generate the lcov html report for the whole project# instead of calling <TARGET>-genhtml for each target (to create an own report# for each target). Instead of the lcov target it does not require geninfo for# all targets, so you have to call <TARGET>-geninfo to generate the info files# the targets you'd like to have in your report or lcov-geninfo for generating# info files for all targets before calling lcov-genhtml.file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/selected_targets)if (NOT TARGET lcov-genhtml)	add_custom_target(lcov-genhtml		COMMAND ${GENHTML_BIN}			--quiet			--output-directory ${LCOV_HTML_PATH}/selected_targets			--title \"${CMAKE_PROJECT_NAME} - targets  `find				${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name				\"all_targets.info\" -exec basename {} .info \\\;`\"			--prefix ${PROJECT_SOURCE_DIR}			--sort			${GENHTML_CPPFILT_FLAG}			`find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name				\"all_targets.info\"`	)endif (NOT TARGET lcov-genhtml)
 |