You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Findcodecov.cmake 6.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. # This file is part of CMake-codecov.
  2. #
  3. # https://github.com/RWTH-ELP/CMake-codecov
  4. #
  5. # Copyright (c)
  6. # 2015-2016 RWTH Aachen University, Federal Republic of Germany
  7. #
  8. # LICENSE : BSD 3-Clause License
  9. #
  10. # Written by Alexander Haase, alexander.haase@rwth-aachen.de
  11. # Updated by Guillaume Jacquenot, guillaume.jacquenot@gmail.com
  12. set(COVERAGE_FLAG_CANDIDATES
  13. # gcc and clang
  14. "-O0 -g -fprofile-arcs -ftest-coverage"
  15. # gcc and clang fallback
  16. "-O0 -g --coverage"
  17. )
  18. # To avoid error messages about CMP0051, this policy will be set to new. There
  19. # will be no problem, as TARGET_OBJECTS generator expressions will be filtered
  20. # with a regular expression from the sources.
  21. if(POLICY CMP0051)
  22. cmake_policy(SET CMP0051 NEW)
  23. endif()
  24. # Add coverage support for target ${TNAME} and register target for coverage
  25. # evaluation.
  26. function(add_coverage TNAME)
  27. foreach (TNAME ${ARGV})
  28. add_coverage_target(${TNAME})
  29. endforeach()
  30. endfunction()
  31. # Find the reuired flags foreach language.
  32. set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
  33. set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
  34. get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
  35. foreach (LANG ${ENABLED_LANGUAGES})
  36. # Coverage flags are not dependent on language, but the used compiler. So
  37. # instead of searching flags foreach language, search flags foreach compiler
  38. # used.
  39. set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
  40. if(NOT COVERAGE_${COMPILER}_FLAGS)
  41. foreach (FLAG ${COVERAGE_FLAG_CANDIDATES})
  42. if(NOT CMAKE_REQUIRED_QUIET)
  43. message(STATUS "Try ${COMPILER} code coverage flag = [${FLAG}]")
  44. endif()
  45. set(CMAKE_REQUIRED_FLAGS "${FLAG}")
  46. unset(COVERAGE_FLAG_DETECTED CACHE)
  47. if(${LANG} STREQUAL "C")
  48. include(CheckCCompilerFlag)
  49. check_c_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
  50. elseif(${LANG} STREQUAL "CXX")
  51. include(CheckCXXCompilerFlag)
  52. check_cxx_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED)
  53. elseif(${LANG} STREQUAL "Fortran")
  54. # CheckFortranCompilerFlag was introduced in CMake 3.x. To be
  55. # compatible with older Cmake versions, we will check if this
  56. # module is present before we use it. Otherwise we will define
  57. # Fortran coverage support as not available.
  58. include(CheckFortranCompilerFlag OPTIONAL
  59. RESULT_VARIABLE INCLUDED)
  60. if(INCLUDED)
  61. check_fortran_compiler_flag("${FLAG}"
  62. COVERAGE_FLAG_DETECTED)
  63. elseif(NOT CMAKE_REQUIRED_QUIET)
  64. message("-- Performing Test COVERAGE_FLAG_DETECTED")
  65. message("-- Performing Test COVERAGE_FLAG_DETECTED - Failed"
  66. " (Check not supported)")
  67. endif()
  68. endif()
  69. if(COVERAGE_FLAG_DETECTED)
  70. set(COVERAGE_${COMPILER}_FLAGS "${FLAG}"
  71. CACHE STRING "${COMPILER} flags for code coverage.")
  72. mark_as_advanced(COVERAGE_${COMPILER}_FLAGS)
  73. break()
  74. endif()
  75. endforeach()
  76. endif()
  77. endforeach()
  78. set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
  79. # Helper function to get the language of a source file.
  80. function (codecov_lang_of_source FILE RETURN_VAR)
  81. get_filename_component(FILE_EXT "${FILE}" EXT)
  82. string(TOLOWER "${FILE_EXT}" FILE_EXT)
  83. string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
  84. get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
  85. foreach (LANG ${ENABLED_LANGUAGES})
  86. list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
  87. if(NOT ${TEMP} EQUAL -1)
  88. set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
  89. return()
  90. endif()
  91. endforeach()
  92. set(${RETURN_VAR} "" PARENT_SCOPE)
  93. endfunction()
  94. # Helper function to get the relative path of the source file destination path.
  95. # This path is needed by FindGcov and FindLcov cmake files to locate the
  96. # captured data.
  97. function (codecov_path_of_source FILE RETURN_VAR)
  98. string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _source ${FILE})
  99. # If expression was found, SOURCEFILE is a generator-expression for an
  100. # object library. Currently we found no way to call this function automatic
  101. # for the referenced target, so it must be called in the directoryso of the
  102. # object library definition.
  103. if(NOT "${_source}" STREQUAL "")
  104. set(${RETURN_VAR} "" PARENT_SCOPE)
  105. return()
  106. endif()
  107. string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" FILE "${FILE}")
  108. if(IS_ABSOLUTE ${FILE})
  109. file(RELATIVE_PATH FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
  110. endif()
  111. # get the right path for file
  112. string(REPLACE ".." "__" PATH "${FILE}")
  113. set(${RETURN_VAR} "${PATH}" PARENT_SCOPE)
  114. endfunction()
  115. # Add coverage support for target ${TNAME} and register target for coverage
  116. # evaluation.
  117. function(add_coverage_target TNAME)
  118. # Check if all sources for target use the same compiler. If a target uses
  119. # e.g. C and Fortran mixed and uses different compilers (e.g. clang and
  120. # gfortran) this can trigger huge problems, because different compilers may
  121. # use different implementations for code coverage.
  122. get_target_property(TSOURCES ${TNAME} SOURCES)
  123. set(TARGET_COMPILER "")
  124. set(ADDITIONAL_FILES "")
  125. foreach (FILE ${TSOURCES})
  126. # If expression was found, FILE is a generator-expression for an object
  127. # library. Object libraries will be ignored.
  128. string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
  129. if("${_file}" STREQUAL "")
  130. codecov_lang_of_source(${FILE} LANG)
  131. if(LANG)
  132. list(APPEND TARGET_COMPILER ${CMAKE_${LANG}_COMPILER_ID})
  133. list(APPEND ADDITIONAL_FILES "${FILE}.gcno")
  134. list(APPEND ADDITIONAL_FILES "${FILE}.gcda")
  135. endif()
  136. endif()
  137. endforeach ()
  138. list(REMOVE_DUPLICATES TARGET_COMPILER)
  139. list(LENGTH TARGET_COMPILER NUM_COMPILERS)
  140. if(NUM_COMPILERS GREATER 1)
  141. message(AUTHOR_WARNING "Coverage disabled for target ${TNAME} because "
  142. "it will be compiled by different compilers.")
  143. return()
  144. elseif((NUM_COMPILERS EQUAL 0) OR
  145. (NOT DEFINED "COVERAGE_${TARGET_COMPILER}_FLAGS"))
  146. message(AUTHOR_WARNING "Coverage disabled for target ${TNAME} "
  147. "because there is no sanitizer available for target sources.")
  148. return()
  149. endif()
  150. # enable coverage for target
  151. set_property(TARGET ${TNAME} APPEND_STRING
  152. PROPERTY COMPILE_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
  153. set_property(TARGET ${TNAME} APPEND_STRING
  154. PROPERTY LINK_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}")
  155. # Add gcov files generated by compiler to clean target.
  156. set(CLEAN_FILES "")
  157. foreach (FILE ${ADDITIONAL_FILES})
  158. codecov_path_of_source(${FILE} FILE)
  159. list(APPEND CLEAN_FILES "CMakeFiles/${TNAME}.dir/${FILE}")
  160. endforeach()
  161. set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
  162. "${CLEAN_FILES}")
  163. add_gcov_target(${TNAME})
  164. endfunction()
  165. # Include modules for parsing the collected data and output it in a readable
  166. # format (like gcov).
  167. find_package(Gcov)