diff options
Diffstat (limited to 'CMake')
| -rw-r--r-- | CMake/Catch2Config.cmake.in | 10 | ||||
| -rw-r--r-- | CMake/CatchConfigOptions.cmake | 90 | ||||
| -rw-r--r-- | CMake/CatchMiscFunctions.cmake | 122 | ||||
| -rw-r--r-- | CMake/FindGcov.cmake | 157 | ||||
| -rw-r--r-- | CMake/FindLcov.cmake | 354 | ||||
| -rw-r--r-- | CMake/Findcodecov.cmake | 258 | ||||
| -rw-r--r-- | CMake/catch2-with-main.pc.in | 10 | ||||
| -rw-r--r-- | CMake/catch2.pc.in | 11 | ||||
| -rwxr-xr-x | CMake/llvm-cov-wrapper | 56 |
9 files changed, 1068 insertions, 0 deletions
diff --git a/CMake/Catch2Config.cmake.in b/CMake/Catch2Config.cmake.in new file mode 100644 index 0000000..c485219 --- /dev/null +++ b/CMake/Catch2Config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + + +# Avoid repeatedly including the targets +if(NOT TARGET Catch2::Catch2) + # Provide path for scripts + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") + + include(${CMAKE_CURRENT_LIST_DIR}/Catch2Targets.cmake) +endif() diff --git a/CMake/CatchConfigOptions.cmake b/CMake/CatchConfigOptions.cmake new file mode 100644 index 0000000..a2f2870 --- /dev/null +++ b/CMake/CatchConfigOptions.cmake @@ -0,0 +1,90 @@ + +# Copyright Catch2 Authors +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at +# https://www.boost.org/LICENSE_1_0.txt) + +# SPDX-License-Identifier: BSL-1.0 + +## +# This file contains options that are materialized into the Catch2 +# compiled library. All of them default to OFF, as even the positive +# forms correspond to the user _forcing_ them to ON, while being OFF +# means that Catch2 can use its own autodetection. +# +# For detailed docs look into docs/configuration.md + + +macro(AddOverridableConfigOption OptionBaseName) + option(CATCH_CONFIG_${OptionBaseName} "Read docs/configuration.md for details" OFF) + option(CATCH_CONFIG_NO_${OptionBaseName} "Read docs/configuration.md for details" OFF) + mark_as_advanced(CATCH_CONFIG_${OptionBaseName} CATCH_CONFIG_NO_${OptionBaseName}) +endmacro() + +macro(AddConfigOption OptionBaseName) + option(CATCH_CONFIG_${OptionBaseName} "Read docs/configuration.md for details" OFF) + mark_as_advanced(CATCH_CONFIG_${OptionBaseName}) +endmacro() + +set(_OverridableOptions + "ANDROID_LOGWRITE" + "BAZEL_SUPPORT" + "COLOUR_WIN32" + "COUNTER" + "CPP11_TO_STRING" + "CPP17_BYTE" + "CPP17_OPTIONAL" + "CPP17_STRING_VIEW" + "CPP17_UNCAUGHT_EXCEPTIONS" + "CPP17_VARIANT" + "GLOBAL_NEXTAFTER" + "POSIX_SIGNALS" + "USE_ASYNC" + "WCHAR" + "WINDOWS_SEH" + "GETENV" + "EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT" + "USE_BUILTIN_CONSTANT_P" +) + +foreach(OptionName ${_OverridableOptions}) + AddOverridableConfigOption(${OptionName}) +endforeach() + +set(_OtherConfigOptions + "DISABLE_EXCEPTIONS" + "DISABLE_EXCEPTIONS_CUSTOM_HANDLER" + "DISABLE" + "DISABLE_STRINGIFICATION" + "ENABLE_ALL_STRINGMAKERS" + "ENABLE_OPTIONAL_STRINGMAKER" + "ENABLE_PAIR_STRINGMAKER" + "ENABLE_TUPLE_STRINGMAKER" + "ENABLE_VARIANT_STRINGMAKER" + "EXPERIMENTAL_REDIRECT" + "FAST_COMPILE" + "NOSTDOUT" + "PREFIX_ALL" + "PREFIX_MESSAGES" + "WINDOWS_CRTDBG" +) + + +foreach(OptionName ${_OtherConfigOptions}) + AddConfigOption(${OptionName}) +endforeach() +if(DEFINED BUILD_SHARED_LIBS) + set(CATCH_CONFIG_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) +else() + set(CATCH_CONFIG_SHARED_LIBRARY "") +endif() + +set(CATCH_CONFIG_DEFAULT_REPORTER "console" CACHE STRING "Read docs/configuration.md for details. The name of the reporter should be without quotes.") +set(CATCH_CONFIG_CONSOLE_WIDTH "80" CACHE STRING "Read docs/configuration.md for details. Must form a valid integer literal.") + +mark_as_advanced(CATCH_CONFIG_SHARED_LIBRARY CATCH_CONFIG_DEFAULT_REPORTER CATCH_CONFIG_CONSOLE_WIDTH) + +# There is no good way to both turn this into a CMake cache variable, +# and keep reasonable default semantics inside the project. Thus we do +# not define it and users have to provide it as an outside variable. +#set(CATCH_CONFIG_FALLBACK_STRINGIFIER "" CACHE STRING "Read docs/configuration.md for details.") diff --git a/CMake/CatchMiscFunctions.cmake b/CMake/CatchMiscFunctions.cmake new file mode 100644 index 0000000..05bc83c --- /dev/null +++ b/CMake/CatchMiscFunctions.cmake @@ -0,0 +1,122 @@ + +# Copyright Catch2 Authors +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at +# https://www.boost.org/LICENSE_1_0.txt) + +# SPDX-License-Identifier: BSL-1.0 + +include(CheckCXXCompilerFlag) +function(add_cxx_flag_if_supported_to_targets flagname targets) + string(MAKE_C_IDENTIFIER ${flagname} flag_identifier ) + check_cxx_compiler_flag("${flagname}" HAVE_FLAG_${flag_identifier}) + + if (HAVE_FLAG_${flag_identifier}) + foreach(target ${targets}) + target_compile_options(${target} PRIVATE ${flagname}) + endforeach() + endif() +endfunction() + +# Assumes that it is only called for development builds, where warnings +# and Werror is desired, so it also enables Werror. +function(add_warnings_to_targets targets) + LIST(LENGTH targets TARGETS_LEN) + # For now we just assume 2 possibilities: msvc and msvc-like compilers, + # and other. + if (MSVC) + foreach(target ${targets}) + # Force MSVC to consider everything as encoded in utf-8 + target_compile_options( ${target} PRIVATE /utf-8 ) + # Enable Werror equivalent + if (CATCH_ENABLE_WERROR) + target_compile_options( ${target} PRIVATE /WX ) + endif() + + # MSVC is currently handled specially + if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) + STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level + target_compile_options( ${target} PRIVATE /w44265 /w44061 /w44062 /w45038 ) + endif() + endforeach() + + endif() + + if (NOT MSVC) + set(CHECKED_WARNING_FLAGS + "-Wabsolute-value" + "-Wall" + "-Wcall-to-pure-virtual-from-ctor-dtor" + "-Wcast-align" + "-Wcatch-value" + "-Wdangling" + "-Wdeprecated" + "-Wdeprecated-register" + "-Wexceptions" + "-Wexit-time-destructors" + "-Wextra" + "-Wextra-semi" + "-Wfloat-equal" + "-Wglobal-constructors" + "-Winit-self" + "-Wmisleading-indentation" + "-Wmismatched-new-delete" + "-Wmismatched-return-types" + "-Wmismatched-tags" + "-Wmissing-braces" + "-Wmissing-declarations" + "-Wmissing-noreturn" + "-Wmissing-prototypes" + "-Wmissing-variable-declarations" + "-Wnon-virtual-dtor" + "-Wnull-dereference" + "-Wold-style-cast" + "-Woverloaded-virtual" + "-Wparentheses" + "-Wpedantic" + "-Wredundant-decls" + "-Wreorder" + "-Wreturn-std-move" + "-Wshadow" + "-Wstrict-aliasing" + "-Wsubobject-linkage" + "-Wsuggest-destructor-override" + "-Wsuggest-override" + "-Wundef" + "-Wuninitialized" + "-Wunneeded-internal-declaration" + "-Wunreachable-code-aggressive" + "-Wunused" + "-Wunused-function" + "-Wunused-parameter" + "-Wvla" + "-Wweak-vtables" + + # This is a useful warning, but our tests sometimes rely on + # functions being present, but not picked (e.g. various checks + # for stringification implementation ordering). + # Ergo, we should use it every now and then, but we cannot + # enable it by default. + # "-Wunused-member-function" + ) + foreach(warning ${CHECKED_WARNING_FLAGS}) + add_cxx_flag_if_supported_to_targets(${warning} "${targets}") + endforeach() + + if (CATCH_ENABLE_WERROR) + foreach(target ${targets}) + # Enable Werror equivalent + target_compile_options( ${target} PRIVATE -Werror ) + endforeach() + endif() + endif() +endfunction() + +# Adds flags required for reproducible build to the target +# Currently only supports GCC and Clang +function(add_build_reproducibility_settings target) + # Make the build reproducible on versions of g++ and clang that supports -ffile-prefix-map + if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_cxx_flag_if_supported_to_targets("-ffile-prefix-map=${CATCH_DIR}/=" "${target}") + endif() +endfunction() diff --git a/CMake/FindGcov.cmake b/CMake/FindGcov.cmake new file mode 100644 index 0000000..4141711 --- /dev/null +++ b/CMake/FindGcov.cmake @@ -0,0 +1,157 @@ +# 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 +# + + +# include required Modules +include(FindPackageHandleStandardArgs) + + +# Search for gcov binary. +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}) + # Gcov evaluation is dependent on the used compiler. Check gcov support for + # each compiler that is used. If gcov binary was already found for this + # compiler, do not try to find it again. + if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN) + get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH) + + if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU") + # Some distributions like OSX (homebrew) ship gcov with the compiler + # version appended as gcov-x. To find this binary we'll build the + # suggested binary name with the compiler version. + string(REGEX MATCH "^[0-9]+" GCC_VERSION + "${CMAKE_${LANG}_COMPILER_VERSION}") + + find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov + HINTS ${COMPILER_PATH}) + + elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang") + # Some distributions like Debian ship llvm-cov with the compiler + # version appended as llvm-cov-x.y. To find this binary we'll build + # the suggested binary name with the compiler version. + string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION + "${CMAKE_${LANG}_COMPILER_VERSION}") + + # llvm-cov prior version 3.5 seems to be not working with coverage + # evaluation tools, but these versions are compatible with the gcc + # gcov tool. + if(LLVM_VERSION VERSION_GREATER 3.4) + find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}" + "llvm-cov" HINTS ${COMPILER_PATH}) + mark_as_advanced(LLVM_COV_BIN) + + if (LLVM_COV_BIN) + find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS + ${CMAKE_MODULE_PATH}) + if (LLVM_COV_WRAPPER) + set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "") + + # set additional parameters + set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV + "LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING + "Environment variables for llvm-cov-wrapper.") + mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV) + endif () + endif () + endif () + + if (NOT GCOV_BIN) + # Fall back to gcov binary if llvm-cov was not found or is + # incompatible. This is the default on OSX, but may crash on + # recent Linux versions. + find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH}) + endif () + endif () + + + if (GCOV_BIN) + set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING + "${LANG} gcov binary.") + + if (NOT CMAKE_REQUIRED_QUIET) + message("-- Found gcov evaluation for " + "${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}") + endif() + + unset(GCOV_BIN CACHE) + endif () + endif () +endforeach () + + + + +# Add a new global target for all gcov targets. This target could be used to +# generate the gcov files for the whole project instead of calling <TARGET>-gcov +# for each target. +if (NOT TARGET gcov) + add_custom_target(gcov) +endif (NOT TARGET gcov) + + + +# This function will add gcov evaluation for target <TNAME>. Only sources of +# this target will be evaluated and no dependencies will be added. It will call +# Gcov on any source file of <TNAME> once and store the gcov file in the same +# directory. +function (add_gcov_target TNAME) + set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir) + + # 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(BUFFER "") + foreach(FILE ${SOURCES}) + get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH) + + # call gcov + add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov + COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null + DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno + WORKING_DIRECTORY ${FILE_PATH} + ) + + list(APPEND BUFFER ${TDIR}/${FILE}.gcov) + endforeach() + + + # add target for gcov evaluation of <TNAME> + add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER}) + + # add evaluation target to the global gcov target. + add_dependencies(gcov ${TNAME}-gcov) +endfunction (add_gcov_target) diff --git a/CMake/FindLcov.cmake b/CMake/FindLcov.cmake new file mode 100644 index 0000000..beb925a --- /dev/null +++ b/CMake/FindLcov.cmake @@ -0,0 +1,354 @@ +# 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 +# + + +# configuration +set(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 Modules +include(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) diff --git a/CMake/Findcodecov.cmake b/CMake/Findcodecov.cmake new file mode 100644 index 0000000..2c0f2fe --- /dev/null +++ b/CMake/Findcodecov.cmake @@ -0,0 +1,258 @@ +# 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) diff --git a/CMake/catch2-with-main.pc.in b/CMake/catch2-with-main.pc.in new file mode 100644 index 0000000..69a790b --- /dev/null +++ b/CMake/catch2-with-main.pc.in @@ -0,0 +1,10 @@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +pkg_version=@Catch2_VERSION@ + +Name: Catch2-With-Main +Description: A modern, C++-native test framework for C++14 and above (links in default main) +Version: ${pkg_version} +Requires: catch2 = ${pkg_version} +Cflags: -I${includedir} +Libs: -L${libdir} -lCatch2Main diff --git a/CMake/catch2.pc.in b/CMake/catch2.pc.in new file mode 100644 index 0000000..bd1c95a --- /dev/null +++ b/CMake/catch2.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ + +Name: Catch2 +Description: A modern, C++-native, test framework for C++14 and above +URL: https://github.com/catchorg/Catch2 +Version: @Catch2_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lCatch2 diff --git a/CMake/llvm-cov-wrapper b/CMake/llvm-cov-wrapper new file mode 100755 index 0000000..2ac3310 --- /dev/null +++ b/CMake/llvm-cov-wrapper @@ -0,0 +1,56 @@ +#!/bin/sh + +# 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 +# + +if [ -z "$LLVM_COV_BIN" ] +then + echo "LLVM_COV_BIN not set!" >& 2 + exit 1 +fi + + +# Get LLVM version to find out. +LLVM_VERSION=$($LLVM_COV_BIN -version | grep -i "LLVM version" \ + | sed "s/^\([A-Za-z ]*\)\([0-9]\).\([0-9]\).*$/\2.\3/g") + +if [ "$1" = "-v" ] +then + echo "llvm-cov-wrapper $LLVM_VERSION" + exit 0 +fi + + +if [ -n "$LLVM_VERSION" ] +then + MAJOR=$(echo $LLVM_VERSION | cut -d'.' -f1) + MINOR=$(echo $LLVM_VERSION | cut -d'.' -f2) + + if [ $MAJOR -eq 3 ] && [ $MINOR -le 4 ] + then + if [ -f "$1" ] + then + filename=$(basename "$1") + extension="${filename##*.}" + + case "$extension" in + "gcno") exec $LLVM_COV_BIN --gcno="$1" ;; + "gcda") exec $LLVM_COV_BIN --gcda="$1" ;; + esac + fi + fi + + if [ $MAJOR -eq 3 ] && [ $MINOR -le 5 ] + then + exec $LLVM_COV_BIN $@ + fi +fi + +exec $LLVM_COV_BIN gcov $@ |
