FindGcov.cmake 5.0 KB

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