diff options
author | Wolfgang Schupp <w.schupp@a1.net> | 2016-07-19 12:10:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-19 12:10:38 +0200 |
commit | 82e30af27000e47abff3fb687135d70d6b90ad2e (patch) | |
tree | 11efd0934fcbcaa91aa85b2a1764abd1d9ef99c7 | |
parent | 2cac3e385eda993bc3557b10f37fcc8673336aa5 (diff) | |
parent | d510c7d4b64cfa184b923d3cd0aa9218a3f5881a (diff) |
Merge pull request #10095 from fetzerch/cmake_codecoverage
[cmake/linux] Code coverage
-rw-r--r-- | project/cmake/CMakeLists.txt | 9 | ||||
-rw-r--r-- | project/cmake/README.md | 6 | ||||
-rw-r--r-- | project/cmake/scripts/linux/ArchSetup.cmake | 8 | ||||
-rw-r--r-- | project/cmake/scripts/linux/CodeCoverage.cmake | 97 | ||||
-rw-r--r-- | project/cmake/scripts/linux/Macros.cmake | 8 | ||||
-rwxr-xr-x | tools/buildsteps/linux64/run-tests | 6 | ||||
-rw-r--r-- | tools/depends/target/cmakebuildsys/Makefile | 2 | ||||
-rw-r--r-- | xbmc/network/cddb.cpp | 4 |
8 files changed, 135 insertions, 5 deletions
diff --git a/project/cmake/CMakeLists.txt b/project/cmake/CMakeLists.txt index e209ed9791..7017a9bf21 100644 --- a/project/cmake/CMakeLists.txt +++ b/project/cmake/CMakeLists.txt @@ -358,6 +358,15 @@ if(NOT CMAKE_CROSSCOMPILING) -DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}) endif() +# code coverage +if(CMAKE_BUILD_TYPE STREQUAL Coverage) + if(EXISTS ${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/CodeCoverage.cmake) + include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/CodeCoverage.cmake) + else() + message(FATAL_ERROR "Code coverage not (yet) implemented for platform ${CORE_SYSTEM_NAME}") + endif() +endif() + # link wrapper if(FFMPEG_LINK_EXECUTABLE) set(CMAKE_CXX_LINK_EXECUTABLE "${FFMPEG_LINK_EXECUTABLE}") diff --git a/project/cmake/README.md b/project/cmake/README.md index fafd07885a..2ac01f1689 100644 --- a/project/cmake/README.md +++ b/project/cmake/README.md @@ -152,6 +152,12 @@ When using the makefile builds a few extra targets are defined: - `make check` builds and executes the test suite. +Code coverage (with Gcov, LCOV and Gcovr) can be built on Linux: + +- CMake has to be executed with `-DCMAKE_BUILD_TYPE=Coverage` +- `make coverage` generates an HTML code coverage report. +- `make coverage_xml` generates an XML code coverage report. + ## Sanitizers Clang and GCC support different kinds of Sanitizers. To enable a Sanitizer call CMake with the diff --git a/project/cmake/scripts/linux/ArchSetup.cmake b/project/cmake/scripts/linux/ArchSetup.cmake index e2adf5bb3b..09675f19b2 100644 --- a/project/cmake/scripts/linux/ArchSetup.cmake +++ b/project/cmake/scripts/linux/ArchSetup.cmake @@ -22,3 +22,11 @@ if(ENABLE_LIRC) set(LIRC_DEVICE "\"/dev/lircd\"" CACHE STRING "LIRC device to use") set(DEP_DEFINES -DLIRC_DEVICE=${LIRC_DEVICE} -DHAVE_LIRC=1) endif() + +# Code Coverage +if(CMAKE_BUILD_TYPE STREQUAL Coverage) + set(COVERAGE_TEST_BINARY ${APP_NAME_LC}-test) + set(COVERAGE_SOURCE_DIR ${CORE_SOURCE_DIR}) + set(COVERAGE_DEPENDS "\${APP_NAME_LC}" "\${APP_NAME_LC}-test") + set(COVERAGE_EXCLUDES */test/* lib/* */lib/*) +endif() diff --git a/project/cmake/scripts/linux/CodeCoverage.cmake b/project/cmake/scripts/linux/CodeCoverage.cmake new file mode 100644 index 0000000000..efc2208b07 --- /dev/null +++ b/project/cmake/scripts/linux/CodeCoverage.cmake @@ -0,0 +1,97 @@ +# - CodeCoverage +# Generate code coverage reports with LCOV and GCovr. +# +# Configuration: +# COVERAGE_SOURCE_DIR - Source root directory (default ${CMAKE_SOURCE_DIR}). +# COVERAGE_BINARY_DIR - Directory where the coverage reports (and intermediate files) +# are generated to. +# COVERAGE_EXCLUDES - List of exclude patterns (for example '*/tests/*'). +# +# The following targets will be generated: +# coverage - Builds an html report. Requires LCOV. +# coverage_xml - Builds an xml report (in Cobertura format for Jenkins). +# Requires Gcovr. +# +# Inspired by https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake + +# Comiler and linker setup +set(CMAKE_C_FLAGS_COVERAGE "-g -O0 --coverage" CACHE STRING + "Flags used by the C compiler during coverage builds." FORCE) +set(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 --coverage" CACHE STRING + "Flags used by the C++ compiler during coverage builds." FORCE) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage" CACHE STRING + "Flags used for linking binaries during coverage builds." FORCE) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage" CACHE STRING + "Flags used by the shared libraries linker during coverage builds." FORCE) +mark_as_advanced( + CMAKE_C_FLAGS_COVERAGE CMAKE_CXX_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE CMAKE_STATIC_LINKER_FLAGS_COVERAGE +) + +find_program(LCOV_EXECUTABLE lcov) +find_program(GENINFO_EXECUTABLE geninfo) +find_program(GENHTML_EXECUTABLE genhtml) +find_program(GCOVR_EXECUTABLE gcovr) +mark_as_advanced(LCOV_EXECUTABLE GENINFO_EXECUTABLE GENHTML_EXECUTABLE GCOVR_EXECUTABLE) + +# Default options +if(NOT COVERAGE_SOURCE_DIR) + set(COVERAGE_SOURCE_DIR ${CMAKE_SOURCE_DIR}) +endif() +if(NOT COVERAGE_BINARY_DIR) + set(COVERAGE_BINARY_DIR ${CMAKE_BINARY_DIR}/coverage) +endif() +if(NOT COVERAGE_EXCLUDES) + set(COVERAGE_EXCLUDES) +endif() + +# Allow variables in COVERAGE_DEPENDS that are not evaluated before this file is included. +string(CONFIGURE "${COVERAGE_DEPENDS}" COVERAGE_DEPENDS) + +# Add coverage target that generates an HTML report using LCOV +if(LCOV_EXECUTABLE AND GENINFO_EXECUTABLE AND GENHTML_EXECUTABLE) + file(MAKE_DIRECTORY ${COVERAGE_BINARY_DIR}) + add_custom_target(coverage + COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_BINARY_DIR} + COMMAND ${LCOV_EXECUTABLE} -z -q -d ${CMAKE_BINARY_DIR} + COMMAND ${LCOV_EXECUTABLE} -c -q -i -d ${CMAKE_BINARY_DIR} -b ${COVERAGE_SOURCE_DIR} + -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_base.info + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test || true + COMMAND ${LCOV_EXECUTABLE} -c -q -d ${CMAKE_BINARY_DIR} -b ${COVERAGE_SOURCE_DIR} + -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_test.info + COMMAND ${LCOV_EXECUTABLE} -a ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_base.info + -a ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_test.info + -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info -q + COMMAND ${LCOV_EXECUTABLE} -q -r ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info + /usr/include/* ${CMAKE_BINARY_DIR}/* ${COVERAGE_EXCLUDES} + -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info + COMMAND ${GENHTML_EXECUTABLE} ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info + -o ${COVERAGE_BINARY_DIR}/html -s --legend --highlight --demangle-cpp + COMMAND ${CMAKE_COMMAND} -E echo "Coverage report: file://${COVERAGE_BINARY_DIR}/html/index.html" + WORKING_DIRECTORY ${COVERAGE_BINARY_DIR} + VERBATIM + DEPENDS ${COVERAGE_DEPENDS} + COMMENT "Generate code coverage html report" + ) +else() + message(WARNING "Target coverage not available (lcov, geninfo and genhtml needed).") +endif() + +# Add coverage target that generates an XML report using Gcovr +if(GCOVR_EXECUTABLE) + file(MAKE_DIRECTORY ${COVERAGE_BINARY_DIR}) + string(REGEX REPLACE "([^;]+)" "--exclude=\"\\1\"" _gcovr_excludes "${COVERAGE_EXCLUDES}") + string(REPLACE "*" ".*" _gcovr_excludes "${_gcovr_excludes}") + add_custom_target(coverage_xml + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test || true + COMMAND ${GCOVR_EXECUTABLE} -x -r ${COVERAGE_SOURCE_DIR} -o ${COVERAGE_BINARY_DIR}/coverage.xml + --object-directory ${CMAKE_BINARY_DIR} ${_gcovr_excludes} ${CMAKE_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E echo "Coverage report: file://${COVERAGE_BINARY_DIR}/coverage.xml" + WORKING_DIRECTORY ${COVERAGE_BINARY_DIR} + DEPENDS ${COVERAGE_DEPENDS} + COMMENT "Generate code coverage xml report" + ) + unset(_gcovr_excludes) +else() + message(WARNING "Target coverage_xml not available (gcovr needed).") +endif() diff --git a/project/cmake/scripts/linux/Macros.cmake b/project/cmake/scripts/linux/Macros.cmake index 7453a1c03d..9d8c00a984 100644 --- a/project/cmake/scripts/linux/Macros.cmake +++ b/project/cmake/scripts/linux/Macros.cmake @@ -14,8 +14,14 @@ function(core_link_library lib wraplib) set(check_arg ${ARGV3}) set(data_arg ${ARGV4}) endif() + + # wrapper has to be adapted in order to support coverage. + if(CMAKE_BUILD_TYPE STREQUAL Coverage) + set(export "") + endif() + if(check_arg STREQUAL export) - set(export ${export} + set(export ${export} -Wl,--version-script=${ARGV3}) elseif(check_arg STREQUAL nowrap) set(export ${data_arg}) diff --git a/tools/buildsteps/linux64/run-tests b/tools/buildsteps/linux64/run-tests index 265ff01985..abcaea49fa 100755 --- a/tools/buildsteps/linux64/run-tests +++ b/tools/buildsteps/linux64/run-tests @@ -4,7 +4,11 @@ XBMC_PLATFORM_DIR=linux64 if [ "$CMAKE_BUILD" = true ]; then cd $WORKSPACE/build;make -j$BUILDTHREADS kodi-test - cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml + if [ "$Configuration" != "Coverage" ]; then + cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml + else + cd $WORKSPACE/build;GTEST_OUTPUT="xml:$WORKSPACE/gtestresults.xml" make coverage + fi else cd $WORKSPACE;make -j$BUILDTHREADS testsuite cd $WORKSPACE;./kodi-test --gtest_output=xml:gtestresults.xml diff --git a/tools/depends/target/cmakebuildsys/Makefile b/tools/depends/target/cmakebuildsys/Makefile index 60a88e153d..1b3207eafa 100644 --- a/tools/depends/target/cmakebuildsys/Makefile +++ b/tools/depends/target/cmakebuildsys/Makefile @@ -5,7 +5,7 @@ APP_NAME=$(shell awk '/APP_NAME/ {print tolower($$2)}' $(VERSION.TXT)) all: mkdir -p $(XBMCROOT)/build - cd $(XBMCROOT)/build; $(CMAKE) $(XBMCROOT)/project/cmake + cd $(XBMCROOT)/build; $(CMAKE) -DCMAKE_BUILD_TYPE=$(Configuration) $(XBMCROOT)/project/cmake clean: cd $(XBMCROOT)/build; $(MAKE) clean diff --git a/xbmc/network/cddb.cpp b/xbmc/network/cddb.cpp index 3878bfcef5..4267697bfc 100644 --- a/xbmc/network/cddb.cpp +++ b/xbmc/network/cddb.cpp @@ -219,8 +219,8 @@ bool Xcddb::queryCDinfo(CCdInfo* pInfo, int inexact_list_select) //########################################################## // Read the data from cddb - Recv(false); //erstmal den Müll abholen - if ( !Send(read_buffer.c_str()) ) + Recv(false); // Clear pending data on our connection + if (!Send(read_buffer.c_str())) { CLog::Log(LOGERROR, "Xcddb::queryCDinfo_inexaxt_list_select Error sending \"%s\"", read_buffer.c_str()); CLog::Log(LOGERROR, "Xcddb::queryCDinfo_inexaxt_list_select pInfo == NULL"); |