diff --git a/.travis.yml b/.travis.yml index 0b28bc5e..25f2f895 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,16 @@ language: cpp -git: - depth: 3 - matrix: include: - os: linux compiler: gcc - env: NAME="Ubuntu Linux (Latest)" NAME_SUFFIX="ubuntu" + env: NAME="Ubuntu Linux (Latest)" NAME_SUFFIX="ubuntu" TEST_COVERAGE=1 services: docker script: - scripts/docker/docker_travis.sh "ubuntu_latest.docker" - os: linux compiler: clang - env: NAME="Fedora Linux (Latest)" NAME_SUFFIX="fedora-llvm" + env: NAME="Fedora Linux (Latest)" NAME_SUFFIX="fedora-llvm" TEST_COVERAGE=1 services: docker script: - scripts/docker/docker_travis.sh "fedora_latest.docker" diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d5fa344..cdde669c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,6 @@ if(BUILD_VIEWER) endif() if(BUILD_TESTS) enable_testing() - include(CTest) add_subdirectory(tests) endif() if(BUILD_TOOLS) @@ -94,3 +93,7 @@ file(COPY COPYING ) include(CMakeCPack.cmake) + +if(TEST_COVERAGE) + coverage_collect() +endif() diff --git a/README.md b/README.md index 6387f568..1a8f27a0 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ OpenRW has been ported to Linux, macOS, Windows, and several variants of BSD. A legitimate copy of the original PC game is required to run OpenRW. Without this it will not be possible to play. -Windows | Linux | macOS ----| --- | --- -[![Build status](https://ci.appveyor.com/api/projects/status/k33qf9ssrja6ckx8/branch/master?svg=true)](https://ci.appveyor.com/project/rwengine/openrw/branch/master) | [![Build Status](https://travis-ci.org/rwengine/openrw.svg?branch=master)](https://travis-ci.org/rwengine/openrw) | [![Build Status](https://travis-ci.org/rwengine/openrw.svg?branch=master)](https://travis-ci.org/rwengine/openrw) +Windows | Linux | macOS | coverage +---| --- | --- | --- +[![Build status](https://ci.appveyor.com/api/projects/status/k33qf9ssrja6ckx8/branch/master?svg=true)](https://ci.appveyor.com/project/rwengine/openrw/branch/master) | [![Build Status](https://travis-ci.org/rwengine/openrw.svg?branch=master)](https://travis-ci.org/rwengine/openrw) | [![Build Status](https://travis-ci.org/rwengine/openrw.svg?branch=master)](https://travis-ci.org/rwengine/openrw) | [![codecov](https://codecov.io/gh/rwengine/openrw/branch/master/graph/badge.svg)](https://codecov.io/gh/rwengine/openrw) ## Links diff --git a/cmake/ctest/build.ctest b/cmake/ctest/build.ctest index f8c162a5..79b634d7 100644 --- a/cmake/ctest/build.ctest +++ b/cmake/ctest/build.ctest @@ -1,7 +1,8 @@ # This file does: # - check whether all arguments are defined, # - configure, build and test, -# - coverage and memcheck, +# - coverage, +# - memcheck (NOT!!), # - submit set(_ARGS_BOOL @@ -20,7 +21,7 @@ set(_ARGS_BOOL ENABLE_SANITIZERS APPEND_RESULTS - RUN_COVERAGE + TEST_COVERAGE SUBMIT ) @@ -34,7 +35,8 @@ set(_ARGS_ONEVAL CONAN_ARCH CMAKE_GENERATOR - COVERAGE_COMMAND + + CODECOV_FLAGS ) set(_ARGS_MULVAL @@ -44,15 +46,14 @@ set(_ARGS_MULVAL foreach(_ARG ${_ARGS_BOOL} ${_ARGS_ONEVAL} ${_ARGS_MULVAL}) set(_VAL "${${_ARG}}") - message(STATUS "build parameter: ${_ARG}='${_VAL}'") + message(STATUS "build parameter: ${_ARG}=${_VAL}") if(NOT DEFINED _VAL) message(FATAL_ERROR "Build parameter '${_ARG}' not defined") endif() endforeach() -# CTEST_CMAKE_GENERATOR and CTEST_COVERAGE_COMMAND needed by CTest +# CTEST_CMAKE_GENERATOR needed by CTest set(CTEST_CMAKE_GENERATOR "${CMAKE_GENERATOR}") -set(CTEST_COVERAGE_COMMAND "${COVERAGE_COMMAND}") set(CTEST_SITE "${BUILDER_NAME}") set(CTEST_BUILD_NAME "${BUILD_NAME}") @@ -164,25 +165,34 @@ set(_CONFIGURE_OPTIONS "-DBUILD_VIEWER=${BUILD_VIEWER}" "-DBUILD_TESTS=TRUE" "-DTESTS_NODATA=${TESTS_NODATA}" - "-DTEST_COVERAGE=${RUN_COVERAGE}" + "-DTEST_COVERAGE=${TEST_COVERAGE}" "-DSEPARATE_TEST_SUITES=${SEPARATE_TEST_SUITES}" "-DCHECK_IWYU=${CHECK_IWYU}" "-DCMAKE_BUILD_TYPE=${_CMAKE_BUILD_TYPE}" "-DENABLE_SANITIZERS=${ENABLE_SANITIZERS}" "-DUSE_CONAN=${USE_CONAN}" "-DENABLE_PROFILING=TRUE" + "-L" ) +if(TEST_CONFIGURE) + list(APPEND _CONFIGURE_OPTIONS + "-DCODECOV_FLAGS=${CODECOV_FLAGS}" + ) +endif() + message(STATUS "Configuring...") message(STATUS "options='${_CONFIGURE_OPTIONS}'") message(STATUS "extra options='${CONFIGURE_EXTRA_OPTIONS}'") ctest_configure( OPTIONS "${_CONFIGURE_OPTIONS};${CONFIGURE_EXTRA_OPTIONS}" - RETURN_VALUE - _CONFIGURE_RESULT + RETURN_VALUE _CONFIGURE_RESULT ${_CTEST_CONFIGURE_EXTRA_ARGS} ) +if(_CONFIGURE_RESULT) + emit_error("Configure error detected!") +endif() message(STATUS "Building...") ctest_build( @@ -190,23 +200,84 @@ ctest_build( FLAGS ${BUILD_EXTRA_FLAGS} NUMBER_ERRORS _NB_BUILD_ERRORS ) +if(_NB_BUILD_ERRORS) + emit_error("Build failure detected!") +endif() if(RUN_TESTS) message(STATUS "Running tests...") ctest_test( RETURN_VALUE _TEST_RESULT ) + if(_TEST_RESULT) + emit_error("Test failure detected!") + endif() else() message(STATUS "Skipping tests...") endif() - -if(RUN_COVERAGE) - message(STATUS "Collecting coverage...") - ctest_coverage( - RETURN_VALUE _COVERAGE_RESULT +if(SUBMIT) + message(STATUS "Submitting to CDash...") + ctest_submit( + RETRY_COUNT 5 + RETRY_DELAY 120 + RETURN_VALUE _SUBMIT_RESULT ) + if(_SUBMIT_RESULT) + emit_warning("Test submission failure detected!") + endif() else() - message(STATUS "Coverage skipped.") + message(STATUS "Submit skipped.") +endif() + +if(TEST_COVERAGE) + message(STATUS "Collecting coverage and submitting to codecov.io...") + ctest_build(APPEND + CONFIGURATION "${_CTEST_BUILD_CONFIGURATION}" + FLAGS "-j1" + TARGET "coverage_upload" + RETURN_VALUE _COVERAGE_COLLECT_RV + ) + if(_COVERAGE_COLLECT_RV) + emit_error("Collecting and uploading coverage failed!") + endif() + if(SUBMIT) + message(STATUS "Submitting to CDash...") + ctest_submit( + RETRY_COUNT 5 + RETRY_DELAY 120 + RETURN_VALUE _SUBMIT_RESULT + ) + if(_SUBMIT_RESULT) + emit_warning("Test submission failure detected!") + endif() + else() + message(STATUS "Submit skipped.") + endif() + + message(STATUS "Cleaning collected coverage data...") + ctest_build(APPEND + CONFIGURATION "${_CTEST_BUILD_CONFIGURATION}" + TARGET "lcov-geninfo-clean" + RETURN_VALUE _COVERAGE_CLEAN_RV + ) + if(_COVERAGE_CLEAN_RV) + emit_error("Cleaning collected coverage data failed!") + endif() + if(SUBMIT) + message(STATUS "Submitting to CDash...") + ctest_submit( + RETRY_COUNT 5 + RETRY_DELAY 120 + RETURN_VALUE _SUBMIT_RESULT + ) + if(_SUBMIT_RESULT) + emit_warning("Test submission failure detected!") + endif() + else() + message(STATUS "Submit skipped.") + endif() +else() + message(STATUS "Collecting and uploading coverage data skipped.") endif() if(RUN_MEMCHECK) @@ -216,29 +287,3 @@ else() message(STATUS "Memcheck skipped.") endif() -if(SUBMIT) - message(STATUS "Submitting...") - ctest_submit( - RETRY_COUNT 5 - RETRY_DELAY 120 - RETURN_VALUE _SUBMIT_RESULT - ) -else() - message(STATUS "Submit skipped.") -endif() - -if(_CONFIGURE_RESULT) - list(APPEND ERROR_MESSAGES "Configure error detected!") -endif() - -if(_NB_BUILD_ERRORS) - list(APPEND ERROR_MESSAGES "Build failure detected!") -endif() - -if(_TEST_RESULT) - list(APPEND ERROR_MESSAGES "Test failure detected!") -endif() - -if(_SUBMIT_RESULT) - list(APPEND WARNING_MESSAGES "Test submission failure detected!") -endif() diff --git a/cmake/ctest/configure_darwin.ctest b/cmake/ctest/configure_darwin.ctest index bb16d966..39b2bb5e 100644 --- a/cmake/ctest/configure_darwin.ctest +++ b/cmake/ctest/configure_darwin.ctest @@ -8,7 +8,6 @@ set(CONFIGURE_EXTRA_OPTIONS ";") set(BUILD_EXTRA_FLAGS "") set(BUILD_TOOLS TRUE) set(BUILD_VIEWER TRUE) -set(COVERAGE_COMMAND gcov) set(CHECK_IWYU FALSE) set(ENABLE_SANITIZERS "") diff --git a/cmake/ctest/configure_linux.ctest b/cmake/ctest/configure_linux.ctest index 960d427a..c02ee81f 100644 --- a/cmake/ctest/configure_linux.ctest +++ b/cmake/ctest/configure_linux.ctest @@ -9,7 +9,6 @@ set(BUILD_EXTRA_FLAGS "") set(BUILD_TOOLS TRUE) set(BUILD_VIEWER TRUE) -set(COVERAGE_COMMAND gcov) set(CHECK_IWYU FALSE) set(ENABLE_SANITIZERS "address") diff --git a/cmake/ctest/configure_windows.ctest b/cmake/ctest/configure_windows.ctest index a36cd8fe..a89d56b9 100644 --- a/cmake/ctest/configure_windows.ctest +++ b/cmake/ctest/configure_windows.ctest @@ -31,6 +31,5 @@ set(CONAN_ARCH "x86_64") set(BUILD_TOOLS TRUE) set(BUILD_VIEWER TRUE) -set(COVERAGE_COMMAND "echo") #FIXME: ENABLE set(CHECK_IWYU FALSE) #FIXME: ENABLE set(ENABLE_SANITIZERS "") diff --git a/cmake/ctest/script_ci.ctest b/cmake/ctest/script_ci.ctest index 053a938b..82c23fbf 100644 --- a/cmake/ctest/script_ci.ctest +++ b/cmake/ctest/script_ci.ctest @@ -41,9 +41,6 @@ else() message(FATAL_ERROR "Unknown CMAKE_SYSTEM_NAME detected '${CMAKE_SYSTEM_NAME}'") endif() -set(WARNING_MESSAGES) -set(ERROR_MESSAGES) - if($ENV{USE_CONAN}) set(USE_CONAN TRUE) else() @@ -51,7 +48,6 @@ else() endif() set(SEPARATE_TEST_SUITES FALSE) -set(RUN_COVERAGE FALSE) set(RUN_MEMCHECK FALSE) openrw_should_submit_ci(SUBMIT) @@ -60,6 +56,13 @@ set(BUILDER_NAME "${BUILDER_NAME_BASE}-nodata") set(APPEND_RESULTS FALSE) set(TESTS_NODATA TRUE) set(RUN_TESTS TRUE) +if($ENV{TEST_COVERAGE}) + set(TEST_COVERAGE TRUE) +else() + set(TEST_COVERAGE FALSE) +endif() + +set(CODECOV_FLAGS "nodata") include("${CTEST_SCRIPT_DIRECTORY}/build.ctest") @@ -69,18 +72,8 @@ set(APPEND_RESULTS FALSE) set(TESTS_NODATA FALSE) set(RUN_TESTS FALSE) +set(CODECOV_FLAGS "data") + include("${CTEST_SCRIPT_DIRECTORY}/build.ctest") -if(WARNING_MESSAGES) - foreach(WARNING_MESSAGE ${WARNING_MESSAGES}) - message(WARNING "${WARNING_MESSAGE}") - endforeach() - message(WARNING "Warning(s) detected") -endif() - -if(ERROR_MESSAGES) - foreach(ERROR_MESSAGE ${ERROR_MESSAGES}) - message(SEND_ERROR "${ERROR_MESSAGE}") - endforeach() - message(FATAL_ERROR "Error(s) detected") -endif() +handle_warnings_errors() diff --git a/cmake/ctest/script_experimental.ctest b/cmake/ctest/script_experimental.ctest index 0f3266e3..79319c93 100644 --- a/cmake/ctest/script_experimental.ctest +++ b/cmake/ctest/script_experimental.ctest @@ -40,9 +40,6 @@ else() message(FATAL_ERROR "Unknown CMAKE_SYSTEM_NAME detected '${CMAKE_SYSTEM_NAME}'") endif() -set(WARNING_MESSAGES) -set(ERROR_MESSAGES) - if($ENV{USE_CONAN}) set(USE_CONAN TRUE) else() @@ -51,10 +48,10 @@ endif() set(SEPARATE_TEST_SUITES TRUE) -if($ENV{RUN_COVERAGE}) - set(RUN_COVERAGE TRUE) +if($ENV{TEST_COVERAGE}) + set(TEST_COVERAGE TRUE) else() - set(RUN_COVERAGE FALSE) + set(TEST_COVERAGE FALSE) endif() set(RUN_MEMCHECK FALSE) #TODO @@ -68,18 +65,10 @@ endif() set(TESTS_NODATA FALSE) set(RUN_TESTS TRUE) +set(SUBMIT $ENV{SUBMIT}) + +set(CODECOV_FLAGS "data") + include("${CTEST_SCRIPT_DIRECTORY}/build.ctest") -if(WARNING_MESSAGES) - foreach(WARNING_MESSAGE ${WARNING_MESSAGES}) - message(WARNING "${WARNING_MESSAGE}") - endforeach() - message(WARNING "Warning(s) detected") -endif() - -if(ERROR_MESSAGES) - foreach(ERROR_MESSAGE ${ERROR_MESSAGES}) - message(SEND_ERROR "${ERROR_MESSAGE}") - endforeach() - message(FATAL_ERROR "Error(s) detected") -endif() +handle_warnings_errors() diff --git a/cmake/ctest/utils.ctest b/cmake/ctest/utils.ctest index f2a38c96..814007a8 100644 --- a/cmake/ctest/utils.ctest +++ b/cmake/ctest/utils.ctest @@ -1,3 +1,34 @@ +set(WARNING_MESSAGES) +set(ERROR_MESSAGES) + +function(emit_warning) + message("WARNING: ${ARGV}") + list(APPEND WARNING_MESSAGES "${ARGV}") + set(WARNING_MESSAGES "${WARNING_MESSAGES}" PARENT_SCOPE) +endfunction() + +function(emit_error) + message("ERROR: ${ARGV}") + list(APPEND ERROR_MESSAGES "${ARGV}") + set(ERROR_MESSAGES "${ERROR_MESSAGES}" PARENT_SCOPE) +endfunction() + +function(handle_warnings_errors) + if(WARNING_MESSAGES) + foreach(WARNING_MESSAGE ${WARNING_MESSAGES}) + message(WARNING "${WARNING_MESSAGE}") + endforeach() + message(WARNING "Warning(s) detected") + endif() + + if(ERROR_MESSAGES) + foreach(ERROR_MESSAGE ${ERROR_MESSAGES}) + message(SEND_ERROR "${ERROR_MESSAGE}") + endforeach() + message(FATAL_ERROR "Error(s) detected") + endif() +endfunction() + function(openrw_src_dir RESULT) # Returns the OpenRW source directory get_filename_component(SRC "${CTEST_SCRIPT_DIRECTORY}/../.." ABSOLUTE) diff --git a/cmake/modules/CodeCoverage.cmake b/cmake/modules/CodeCoverage.cmake new file mode 100644 index 00000000..efe2f378 --- /dev/null +++ b/cmake/modules/CodeCoverage.cmake @@ -0,0 +1,461 @@ +# DOES NOT SUPPORT RUNNING IN PARALLEL: https://github.com/linux-test-project/lcov/issues/37 + +# TODO: macos xcode coverage: works? What dependencies? + +get_filename_component(_CODECOVERAGE_MODDIR ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(codecoverage_enable _DIR _GLOBALREPORT) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + find_program(GCOV_BIN gcov) + if(NOT GCOV_BIN) + message(FATAL_ERROR "gcov not found") + endif() + set(COV_BIN "${GCOV_BIN}") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + find_program(LLVM_COV_BIN llvm-cov) + if(NOT LLVM_COV_BIN) + message(FATAL_ERROR "llvm-cov not found") + endif() + configure_file("${_CODECOVERAGE_MODDIR}/llvm-cov-wrapper.in" "${CMAKE_BINARY_DIR}/llvm-cov-wrapper") + set(COV_BIN "${CMAKE_BINARY_DIR}/llvm-cov-wrapper") + else() + message(FATAL_ERROR "Code coverage unsupported for this compiler.") + endif() + set(COV_BIN "${COV_BIN}" CACHE INTERNAL "Coverage tool") + + find_program(LCOV_BIN lcov) + if(NOT LCOV_BIN) + message(FATAL_ERROR "lcov not found") + endif() + + find_program(GENINFO_BIN geninfo) + if(NOT GENINFO_BIN) + message(FATAL_ERROR "geninfo not found") + endif() + + find_program(GENHTML_BIN genhtml) + if(NOT GENHTML_BIN) + message(FATAL_ERROR "genhtml not found") + endif() + + find_program(CPPFILT_BIN c++filt) + if(NOT CPPFILT_BIN) + message(FATAL_ERROR "c++filt not found") + endif() + + message(STATUS "TEST_COVERAGE enabled. Optimizations are disabled, debug data will be added to targets.") + + # Remove global optimization flags + foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES} "") + foreach(LANGUAGE C CXX) + set(FLAGVARNAME "CMAKE_${LANGUAGE}_FLAGS") + if(CONFIG_TYPE) + string(TOUPPER "${CONFIG_TYPE}" CONFIG_TYPE) + set(FLAGVARNAME "${FLAGVARNAME}_${CONFIG_TYPE}") + endif() + string(REGEX REPLACE "-O[s0-3]" "" _OUT "${${FLAGVARNAME}}") + set("${FLAGVARNAME}" "${_OUT}" PARENT_SCOPE) + endforeach() + endforeach() + + set(COVERAGE_COMPILE_FLAGS "-O0 -fprofile-arcs -ftest-coverage -g" CACHE STRING "Compile flags for compiling with coverage support") + set(COVERAGE_LINK_FLAGS "-O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Link flags for linking with coverage support") + + set(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data") + set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init" CACHE PATH "Where to put initial coverage") + set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture" CACHE PATH "Where to put final coverage") + set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html" CACHE PATH "Where to put html coverage reports") + + file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT}) + file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE}) + + add_custom_target(gcov) + add_custom_target(lcov-capture-init) + add_custom_target(lcov-capture) + + define_property(GLOBAL + PROPERTY COVERAGE_TARGETS + BRIEF_DOCS "List of all coverage targets" + FULL_DOCS "All targets that is collected coverage over" + ) + define_property(GLOBAL + PROPERTY LCOV_CAPTURE_FILES + BRIEF_DOCS "List of all capture files" + FULL_DOCS "All capture files which have coverage data included" + ) + define_property(GLOBAL + PROPERTY LCOV_CAPTURE_INIT_FILES + BRIEF_DOCS "List of all init capture files" + FULL_DOCS "Empty capture files for the baseline coverage" + ) +endfunction() + +function(_coverage_path_dest _RETURNVAR PATH) + string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" PATH "${PATH}") + if(IS_ABSOLUTE "${PATH}") + file(RELATIVE_PATH PATH "${CMAKE_CURRENT_SOURCE_DIR}" ${PATH}) + endif() + string(REPLACE ".." "__" PATH "${PATH}") + set("${_RETURNVAR}" "${PATH}" PARENT_SCOPE) +endfunction() + +function(_coverage_filter_languages _RETURNVAR) + get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + + set(FILTERED_FILES) + foreach(FILE ${ARGN}) + get_filename_component(FILE_EXT "${FILE}" EXT) + string(TOLOWER "${FILE_EXT}" FILE_EXT) + string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT) + foreach(LANG ${ENABLED_LANGUAGES}) + if(FILE_EXT IN_LIST CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS) + list(APPEND FILTERED_FILES "${FILE}") + endif() + endforeach() + endforeach() + set("${_RETURNVAR}" "${FILTERED_FILES}" PARENT_SCOPE) +endfunction() + +function(coverage_add_target _TARGET) + cmake_parse_arguments(CAT "" "" "EXCEPT" ${ARGN}) + + get_property(COMPILE_FLAGS TARGET "${_TARGET}" PROPERTY COMPILE_FLAGS) + + set_property(TARGET "${_TARGET}" + APPEND_STRING + PROPERTY COMPILE_FLAGS " ${COVERAGE_COMPILE_FLAGS}" + ) + set_property(TARGET "${_TARGET}" + APPEND_STRING + PROPERTY LINK_FLAGS " ${COVERAGE_LINK_FLAGS}" + ) + + get_target_property(SOURCES "${_TARGET}" SOURCES) + set(COVERAGE_FILES) + foreach(SOURCE ${SOURCES}) + if("${SOURCE}" IN_LIST CAT_EXCEPT) + continue() + endif() + _coverage_path_dest(RELSOURCE "${SOURCE}") + list(APPEND COVERAGE_FILES + "CMakeFiles/${_TARGET}.dir/${RELSOURCE}.gcno" + "CMakeFiles/${_TARGET}.dir/${RELSOURCE}.gcda" + ) + endforeach() + + set_property(GLOBAL + APPEND PROPERTY COVERAGE_TARGETS + "${_TARGET}" + ) + set_property(DIRECTORY + APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + ${COVERAGE_FILES} + ) + coverage_gcov_target(${_TARGET} EXCEPT "${CAT_EXCEPT}") + coverage_lcov_target(${_TARGET} EXCEPT "${CAT_EXCEPT}") +endfunction() + +function(coverage_collect) + codecoverage_lcov_capture_initial() + codecoverage_lcov_capture() +endfunction() + +function(coverage_gcov_target _TARGET) + cmake_parse_arguments(CGT "" "" "EXCEPT" ${ARGN}) + + set(GCOV_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_TARGET}.dir") + get_target_property(SOURCES "${_TARGET}" SOURCES) + _coverage_filter_languages(SOURCES ${SOURCES}) + foreach(SOURCE ${SOURCES}) + _coverage_path_dest(RELSOURCE "${SOURCE}") + if("${SOURCE}" IN_LIST CGT_EXCEPT) + continue() + endif() + get_filename_component(RELSOURCE_PATH "${RELSOURCE}" PATH) + + add_custom_command(OUTPUT "${GCOV_DIR}/${RELSOURCE}.gcov" + COMMAND test -s "${GCOV_DIR}/${RELSOURCE}.gcda" + && "${COV_BIN}" "${GCOV_DIR}/${RELSOURCE}.gcno" > /dev/null + || true + DEPENDS "${_TARGET}" "${GCOV_DIR}/${RELSOURCE}.gcno" "${GCOV_DIR}/${RELSOURCE}.gcda" + WORKING_DIRECTORY "${GCOV_DIR}/${RELSOURCE_PATH}" + COMMENT "Capturing gcov data for source ${SOURCE} of target ${_TARGET}" + ) + + list(APPEND GCOV_FILES "${GCOV_DIR}/${RELSOURCE}.gcov") + endforeach() + add_custom_target("${_TARGET}-gcov" + DEPENDS ${GCOV_FILES} + COMMENT "Capturing gcov data of target ${_TARGET}" + ) + add_dependencies(gcov "${_TARGET}-gcov") +endfunction() + +function(coverage_lcov_target _TARGET) + coverage_lcov_target_initial("${_TARGET}" ${ARGN}) + coverage_lcov_capture_target("${_TARGET}" ${ARGN}) +endfunction() + +function(coverage_lcov_target_initial _TARGET) + cmake_parse_arguments(CLTI "" "" "EXCEPT" ${ARGN}) + + set(LCOV_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_TARGET}.dir") + set(INIT_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_TARGET}-capture-init.dir") + get_target_property(SOURCES "${_TARGET}" SOURCES) + _coverage_filter_languages(SOURCES ${SOURCES}) + + set(GENINFO_FILES) + foreach(SOURCE ${SOURCES}) + if("${SOURCE}" IN_LIST CLTI_EXCEPT) + continue() + endif() + + # generate empty coverage files + _coverage_path_dest(RELSOURCE "${SOURCE}") + get_filename_component(RELSOURCE_DIR "${RELSOURCE}" DIRECTORY) + file(MAKE_DIRECTORY "${INIT_DIR}/${RELSOURCE_DIR}") + set(GENINFO_FILE "${INIT_DIR}/${RELSOURCE}.info.init") + list(APPEND GENINFO_FILES "${GENINFO_FILE}") + + add_custom_command(OUTPUT "${GENINFO_FILE}" + COMMAND "${GENINFO_BIN}" + --quiet --base-directory "${PROJECT_SOURCE_DIR}" --initial + --gcov-tool "${COV_BIN}" --output-filename "${GENINFO_FILE}" + --no-external "${LCOV_DIR}/${RELSOURCE}.gcno" + DEPENDS "${_TARGET}" + COMMENT "Capturing initial coverage data for ${SOURCE}" + ) + endforeach() + + set(OUTFILE "${LCOV_DATA_PATH_INIT}/${_TARGET}.info") + coverage_lcov_merge_files( + OUTFILE "${OUTFILE}" + FILES ${GENINFO_FILES} + FLAGS "--initial" + REMOVE_PATTERNS + ) + add_custom_target("${_TARGET}-capture-init" + DEPENDS "${OUTFILE}" + COMMENT "Capturing initial coverage data for target ${_TARGET}" + ) + + add_dependencies(lcov-capture-init "${_TARGET}-capture-init") + set_property(GLOBAL APPEND PROPERTY LCOV_CAPTURE_INIT_FILES "${OUTFILE}") +endfunction() + +function(coverage_lcov_capture_target _TARGET) + cmake_parse_arguments(CLC "" "" "EXCEPT" ${ARGN}) + + set(LCOV_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_TARGET}.dir") + set(CAP_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_TARGET}-geninfo.dir") + set(INIT_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_TARGET}-capture-init.dir") + get_target_property(SOURCES "${_TARGET}" SOURCES) + _coverage_filter_languages(SOURCES ${SOURCES}) + + set(GCDA_FILES) + set(GENINFO_FILES) + foreach(SOURCE ${SOURCES}) + if("${SOURCE}" IN_LIST CLC_EXCEPT) + continue() + endif() + + _coverage_path_dest(RELSOURCE "${SOURCE}") + get_filename_component(RELSOURCE_DIR "${RELSOURCE}" DIRECTORY) + file(MAKE_DIRECTORY "${CAP_DIR}/${RELSOURCE_DIR}") + set(OUTFILE "${CAP_DIR}/${RELSOURCE}.info") + + list(APPEND GENINFO_FILES "${OUTFILE}") + list(APPEND GCDA_FILES "${LCOV_DIR}/${RELSOURCE}.gcda") + + add_custom_command(OUTPUT "${LCOV_DIR}/${RELSOURCE}.gcda" + COMMAND "${CMAKE_COMMAND}" -E touch "${LCOV_DIR}/${RELSOURCE}.gcda" + DEPENDS "${_TARGET}" + COMMENT "Touching ${LCOV_DIR}/${RELSOURCE}.gcda" + ) + + add_custom_command(OUTPUT "${OUTFILE}" + COMMAND test -s "${LCOV_DIR}/${RELSOURCE}.gcda" + && "${GENINFO_BIN}" --quiet --base-directory + "${PROJECT_SOURCE_DIR}" --gcov-tool "${COV_BIN}" + --output-filename "${OUTFILE}" --no-external + "${LCOV_DIR}/${RELSOURCE}.gcda" + || cp "${INIT_DIR}/${RELSOURCE}.info.init" "${OUTFILE}" + DEPENDS "${_TARGET}" "${_TARGET}-capture-init" "${LCOV_DIR}/${RELSOURCE}.gcda" + COMMENT "Capturing coverage data for ${SOURCE}" + ) + endforeach() + + # Concatenate all files generated by geninfo to a single file per target. + set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${_TARGET}.info") + coverage_lcov_merge_files(OUTFILE "${OUTFILE}" + FILES ${GENINFO_FILES} + ) + add_custom_target("${_TARGET}-geninfo" + DEPENDS "${OUTFILE}" + COMMENT "Capturing coverage data for target ${_TARGET}" + ) + + add_custom_target("${_TARGET}-geninfo-clean" + COMMAND "${CMAKE_COMMAND}" -E remove "${OUTFILE}" ${GCDA_FILES} + COMMENT "Cleaning coverage data of target ${_TARGET}" + ) + + add_dependencies(lcov-capture "${_TARGET}-geninfo") + set_property(GLOBAL APPEND PROPERTY LCOV_CAPTURE_FILES "${OUTFILE}") + + # Add target for generating html output for this target only. + file(MAKE_DIRECTORY "${LCOV_HTML_PATH}/${_TARGET}") + add_custom_target("${_TARGET}-lcov" + COMMAND "${GENHTML_BIN}" --quiet --sort --prefix "${PROJECT_SOURCE_DIR}" + --baseline-file "${LCOV_DATA_PATH_INIT}/${_TARGET}.info" + --output-directory "${LCOV_HTML_PATH}/${_TARGET}" + --title "${CMAKE_PROJECT_NAME} - target ${_TARGET}" + --demangle-cpp "${OUTFILE}" + DEPENDS "${_TARGET}-geninfo" "${_TARGET}-capture-init" + COMMENT "Generating coverage report for target ${_TARGET}" + ) +endfunction() + +function(codecoverage_lcov_capture_initial) + set(INITCAPTURE_FILE "${LCOV_DATA_PATH_INIT}/all_targets.info") + set(INITCAPTURE_FILE_UPLOAD "${INITCAPTURE_FILE}.upload") + get_property(LCOV_CAPTURE_INIT_FILES GLOBAL PROPERTY LCOV_CAPTURE_INIT_FILES) + coverage_lcov_merge_files(OUTFILE "${INITCAPTURE_FILE}" FILES ${LCOV_CAPTURE_INIT_FILES}) + add_custom_target(lcov-geninfo-init + DEPENDS ${INITCAPTURE_FILE} lcov-capture-init + COMMENT "Capturing global initial coverage data" + ) + + string(REPLACE "/" "\\/" PROJBINDIR_ESCAPED "${PROJECT_BINARY_DIR}/") + string(REPLACE "/" "\\/" PROJSRCDIR_ESCAPED "${PROJECT_SOURCE_DIR}/") + add_custom_command(OUTPUT "${INITCAPTURE_FILE_UPLOAD}" + COMMAND sed -e 's/${PROJBINDIR_ESCAPED}//g' -e 's/${PROJSRCDIR_ESCAPED}//g' "${INITCAPTURE_FILE}" > "${INITCAPTURE_FILE_UPLOAD}" + DEPENDS lcov-geninfo-init "${INITCAPTURE_FILE}" + COMMENT "Creating ${INITCAPTURE_FILE_UPLOAD}" + ) + add_custom_target(lcov-geninfo-init-upload + DEPENDS "${INITCAPTURE_FILE_UPLOAD}" + COMMENT "Preparing ${INITCAPTURE_FILE_UPLOAD} for upload" + ) +endfunction() + +function(codecoverage_lcov_capture) + set(TOTALCAPTURE_FILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info") + set(TOTALCAPTURE_FILE_UPLOAD "${TOTALCAPTURE_FILE}.upload") + get_property(COVERAGE_TARGETS GLOBAL PROPERTY COVERAGE_TARGETS) + get_property(LCOV_CAPTURE_FILES GLOBAL PROPERTY LCOV_CAPTURE_FILES) + set(GENINFO_CLEAN_TARGETS) + set(GENINFO_TARGETS) + foreach(COVERAGE_TARGET ${COVERAGE_TARGETS}) + list(APPEND GENINFO_TARGETS "${COVERAGE_TARGET}-geninfo") + list(APPEND GENINFO_CLEAN_TARGETS "${COVERAGE_TARGET}-geninfo-clean") + endforeach() + + coverage_lcov_merge_files(OUTFILE "${TOTALCAPTURE_FILE}" FILES ${LCOV_CAPTURE_FILES}) + add_custom_target(lcov-geninfo + DEPENDS ${GENINFO_TARGETS} "${TOTALCAPTURE_FILE}" + COMMENT "Capturing global coverage data" + ) + + string(REPLACE "/" "\\/" PROJBINDIR_ESCAPED "${PROJECT_BINARY_DIR}/") + string(REPLACE "/" "\\/" PROJSRCDIR_ESCAPED "${PROJECT_SOURCE_DIR}/") + add_custom_command(OUTPUT "${TOTALCAPTURE_FILE_UPLOAD}" + COMMAND sed -e 's/${PROJBINDIR_ESCAPED}//g' -e 's/${PROJSRCDIR_ESCAPED}//g' "${TOTALCAPTURE_FILE}" > "${TOTALCAPTURE_FILE_UPLOAD}" + DEPENDS lcov-geninfo "${TOTALCAPTURE_FILE}" + COMMENT "Creating ${TOTALCAPTURE_FILE_UPLOAD}" + ) + add_custom_target(lcov-geninfo-upload + DEPENDS "${TOTALCAPTURE_FILE_UPLOAD}" + COMMENT "Preparing ${TOTALCAPTURE_FILE_UPLOAD} for upload" + ) + + add_custom_target(lcov-geninfo-clean + COMMAND "${CMAKE_COMMAND}" -E remove "${TOTALCAPTURE_FILE}" "${TOTALCAPTURE_FILE_UPLOAD}" + COMMENT "Cleaning global coverage data" + DEPENDS ${GENINFO_CLEAN_TARGETS} + ) + + 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}" + --demangle-cpp "${TOTALCAPTURE_FILE}" + DEPENDS lcov-geninfo-init lcov-geninfo + COMMENT "Generating global coverage report" + ) +endfunction() + +function(coverage_lcov_merge_files) + cmake_parse_arguments(CLMF "" "OUTFILE" "FILES;FLAGS;REMOVE_PATTERNS" ${ARGN}) + set(OUTFILE "${CLMF_OUTFILE}") + + # Generate merged file. + string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}") + add_custom_command(OUTPUT "${OUTFILE}.raw" + COMMAND cat ${CLMF_FILES} > ${OUTFILE}.raw + DEPENDS ${CLMF_FILES} + COMMENT "Generating ${FILE_REL}" + ) + + add_custom_command(OUTPUT "${OUTFILE}" + COMMAND "${LCOV_BIN}" --quiet -a "${OUTFILE}.raw" --output-file "${OUTFILE}" + --base-directory "${PROJECT_SOURCE_DIR}" ${CLMF_FLAGS} + COMMAND "${LCOV_BIN}" --quiet -r "${OUTFILE}" ${CLMF_REMOVE_PATTERNS} + --output-file "${OUTFILE}" ${CLMF_FLAGS} + DEPENDS "${OUTFILE}.raw" + COMMENT "Post-processing ${FILE_REL}" + ) +endfunction() + +function(add_coverage_upload_target_codecov_io) + cmake_parse_arguments(CU "" "GITSHA1;GITBRANCH;NAME" "" ${ARGN}) + set(CAPTURE_FILES "${LCOV_DATA_PATH_INIT}/all_targets.info.upload" "${LCOV_DATA_PATH_CAPTURE}/all_targets.info.upload") + + find_program(CURL_BIN curl) + if(NOT CURL_BIN) + message(FATAL_ERROR "curl not found") + endif() + + find_program(BASH_BIN bash) + if(NOT BASH_BIN) + message(FATAL_ERROR "bash not found") + endif() + + set(CODECOV_PATH "${PROJECT_BINARY_DIR}/codecov.sh") + + set(CODECOV_SCRIPT_URL "https://codecov.io/bash" CACHE STRING "codecov.io bash script url") + set(CODECOV_FLAGS "" CACHE STRING "codecov.io flags") + string(REPLACE ";" "," CODECOV_FLAGS_ARG "${CODECOV_FLAGS}") + add_custom_command(OUTPUT "${CODECOV_PATH}" + COMMAND "${CURL_BIN}" "${CODECOV_SCRIPT_URL}" --insecure --output "${CODECOV_PATH}" + COMMENT "Fetching codecov.io bash script" + ) + + set(EXTRA_ARGS) + if(CU_GITSHA1) + list(APPEND EXTRA_ARGS -C "${CU_GITSHA1}") + endif() + if(CU_GITBRANCH) + list(APPEND EXTRA_ARGS -B "${CU_GITBRANCH}") + endif() + if(CU_NAME) + list(APPEND EXTRA_ARGS -n "${CU_NAME}") + endif() + foreach(CAPTURE_FILE ${CAPTURE_FILES}) + list(APPEND EXTRA_ARGS -f "${CAPTURE_FILE}") + endforeach() + if(CODECOV_FLAG) + list(APPEND EXTRA_ARGS -F "${CODECOV_FLAGS_ARG}") + endif() + + add_custom_target(coverage_upload + COMMAND "${BASH_BIN}" "${CODECOV_PATH}" ${EXTRA_ARGS} + -Z -A "--insecure" -U "--insecure" + -X gcov -X coveragepy -X search -X fix + DEPENDS "${CODECOV_PATH}" lcov-geninfo-upload lcov-geninfo-init-upload + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Uploading coverage to codecov.io" + ) +endfunction() diff --git a/cmake/modules/llvm-cov-wrapper.in b/cmake/modules/llvm-cov-wrapper.in new file mode 100755 index 00000000..d255b77b --- /dev/null +++ b/cmake/modules/llvm-cov-wrapper.in @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import re +import subprocess +import sys + +llvm_cov_bin = "@LLVM_COV_BIN@" + +# The wrapper must return the version for the "-v" and "--version" flags. +# llvm-cov only accepts --version +if any(h in sys.argv for h in ("-v", "--version",)): + p = subprocess.Popen([llvm_cov_bin, "--version"], stdout=subprocess.PIPE) + output = p.stdout.read().decode("utf8") + p.wait() + assert p.returncode == 0 + versionmatch = re.search("([0-9]+\\.[0-9]+(?:\\.[0-9]+))", output) + if not versionmatch: + raise RuntimeError("Cannot detect version") + print(versionmatch) + print("{} version {}".format(sys.argv[0], versionmatch.group(1))) + sys.exit(0) + +p = subprocess.Popen([llvm_cov_bin, "gcov"] + sys.argv[1:]) +p.wait() +assert p.returncode == 0 diff --git a/cmake_configure.cmake b/cmake_configure.cmake index 1f873c94..ea2cad9f 100644 --- a/cmake_configure.cmake +++ b/cmake_configure.cmake @@ -144,23 +144,23 @@ else() endif() if(TEST_COVERAGE) - if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - message("TEST_COVERAGE enabled. Setting CMAKE_BUILD_TYPE to Debug.") - set(CMAKE_BUILD_TYPE "Debug") + include(CodeCoverage) + codecoverage_enable("${PROJECT_BINARY_DIR}" "${PROJECT_BINARY_DIR}/codecoverage") + + string(REGEX MATCH "[^/]*/[^/]*/([^/]*)" _RE_REFSPEC "${GIT_REFSPEC}") + if(_RE_REFSPEC) + set(GIT_BRANCH "${CMAKE_MATCH_1}") + message(STATUS "Git branch detected from .git directory: ${GIT_BRANCH}") + elseif(DEFINED ENV{TRAVIS_BRANCH}) + set(GIT_BRANCH "$ENV{TRAVIS_BRANCH}") + message(STATUS "Git branch detected from TRAVIS_BRANCH environment variable: ${GIT_BRANCH}") + else() + message("Git branch unknown: uploading coverage might nog work") endif() - if(NOT BUILD_TESTS) - message("TEST_COVERAGE enabled. Enabling BUILD_TESTS.") - set(BUILD_TESTS "ON") - endif() - target_compile_options(rw_checks - INTERFACE - "-O0" - "-fprofile-arcs" - "-ftest-coverage" - ) - target_link_libraries(rw_checks - INTERFACE - gcov + add_coverage_upload_target_codecov_io( + GITSHA1 "${GIT_SHA1}" + GITBRANCH "${GIT_BRANCH}" + NAME "${CODECOV_NAME}" ) endif() @@ -188,7 +188,7 @@ endforeach() function(openrw_target_apply_options) set(IWYU_MAPPING "${PROJECT_SOURCE_DIR}/openrw_iwyu.imp") - cmake_parse_arguments("ORW" "INSTALL;INSTALL_PDB" "TARGET" "" ${ARGN}) + cmake_parse_arguments("ORW" "INSTALL;INSTALL_PDB;COVERAGE" "TARGET" "COVERAGE_EXCEPT" ${ARGN}) if(CHECK_IWYU) iwyu_check(TARGET "${ORW_TARGET}" EXTRA_OPTS @@ -196,6 +196,10 @@ function(openrw_target_apply_options) ) endif() + if(TEST_COVERAGE AND ORW_COVERAGE) + coverage_add_target("${ORW_TARGET}" EXCEPT ${ORW_COVERAGE_EXCEPT}) + endif() + if(CHECK_CLANGTIDY) clang_tidy_check_target( TARGET "${ORW_TARGET}" diff --git a/cmake_options.cmake b/cmake_options.cmake index 2243b549..08cc26df 100644 --- a/cmake_options.cmake +++ b/cmake_options.cmake @@ -15,8 +15,9 @@ set_property(CACHE FAILED_CHECK_ACTION PROPERTY STRINGS "IGNORE" "ABORT" "BREAKP set(FILESYSTEM_LIBRARY "BOOST" CACHE STRING "Which filesystem library to use") set_property(CACHE FILESYSTEM_LIBRARY PROPERTY STRINGS "CXX17" "CXXTS" "BOOST") +set(CMAKE_CONFIGURATION_TYPES "Release;Debug;RelWithDebInfo;MinSizeRel" CACHE INTERNAL "Build types supported by this project.") if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel") + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}") endif() option(CHECK_IWYU "Enable IncludeWhatYouUse (Analyze #includes in C and C++ source files)") @@ -25,6 +26,7 @@ option(CHECK_CLANGTIDY_FIX "Apply fixes from clang-tidy (!!!RUN ON CLEAN GIT TRE set(ENABLE_SANITIZERS "" CACHE STRING "Enable selected sanitizer.") +set(CODECOV_NAME "" CACHE STRING "Name of report in codecov.io ui.") option(TEST_COVERAGE "Enable coverage analysis (implies CMAKE_BUILD_TYPE=Debug)") option(SEPARATE_TEST_SUITES "Add each test suite as separate test to CTest") diff --git a/external/microprofile/CMakeLists.txt b/external/microprofile/CMakeLists.txt index ab138f65..0a6dd2e5 100644 --- a/external/microprofile/CMakeLists.txt +++ b/external/microprofile/CMakeLists.txt @@ -21,4 +21,8 @@ target_link_libraries(microprofile openrw::checks ) +openrw_target_apply_options( + TARGET microprofile +) + add_library(microprofile::microprofile ALIAS microprofile) diff --git a/rwcore/CMakeLists.txt b/rwcore/CMakeLists.txt index 95a2c35e..5ee71152 100644 --- a/rwcore/CMakeLists.txt +++ b/rwcore/CMakeLists.txt @@ -66,7 +66,10 @@ target_link_libraries(rwcore OpenGL::GL ) -openrw_target_apply_options(TARGET rwcore) +openrw_target_apply_options(TARGET rwcore + COVERAGE + COVERAGE_EXCEPT gl/gl_core_3_3.c gl/gl_core_3_3.h + ) if(BUILD_SHARED_LIBS) install(TARGETS rwcore diff --git a/rwengine/CMakeLists.txt b/rwengine/CMakeLists.txt index 24d0620a..80be4543 100644 --- a/rwengine/CMakeLists.txt +++ b/rwengine/CMakeLists.txt @@ -167,7 +167,9 @@ target_include_directories(rwengine "${CMAKE_CURRENT_SOURCE_DIR}/src" ) -openrw_target_apply_options(TARGET rwengine) +openrw_target_apply_options(TARGET rwengine + COVERAGE + ) if(BUILD_SHARED_LIBS) install(TARGETS rwengine diff --git a/rwgame/CMakeLists.txt b/rwgame/CMakeLists.txt index f9b9afdc..438772e0 100644 --- a/rwgame/CMakeLists.txt +++ b/rwgame/CMakeLists.txt @@ -63,5 +63,6 @@ target_link_libraries(rwgame openrw_target_apply_options( TARGET rwgame + COVERAGE INSTALL INSTALL_PDB ) diff --git a/rwtools/rwfont/CMakeLists.txt b/rwtools/rwfont/CMakeLists.txt index 7494258b..4526dcc3 100644 --- a/rwtools/rwfont/CMakeLists.txt +++ b/rwtools/rwfont/CMakeLists.txt @@ -13,5 +13,6 @@ target_link_libraries(rwfontmap openrw_target_apply_options( TARGET rwfontmap + COVERAGE INSTALL INSTALL_PDB ) diff --git a/rwviewer/CMakeLists.txt b/rwviewer/CMakeLists.txt index 0e4490b1..0ab0127f 100644 --- a/rwviewer/CMakeLists.txt +++ b/rwviewer/CMakeLists.txt @@ -56,6 +56,7 @@ target_link_libraries(rwviewer openrw_target_apply_options( TARGET rwviewer + COVERAGE INSTALL INSTALL_PDB ) diff --git a/scripts/docker/arch_latest.docker b/scripts/docker/arch_latest.docker index 8640a96a..2145c3d6 100644 --- a/scripts/docker/arch_latest.docker +++ b/scripts/docker/arch_latest.docker @@ -2,9 +2,11 @@ FROM base/archlinux RUN pacman -Syy --noconfirm \ core/gcc \ + extra/llvm \ extra/clang \ make \ ninja \ + curl \ extra/boost \ extra/cmake \ extra/ffmpeg \ @@ -15,4 +17,6 @@ RUN pacman -Syy --noconfirm \ extra/qt5-base \ extra/freetype2 +# FIXME: lcov + CMD ["/bin/bash"] diff --git a/scripts/docker/conan_base.docker b/scripts/docker/conan_base.docker index 88910470..f1c4cad9 100644 --- a/scripts/docker/conan_base.docker +++ b/scripts/docker/conan_base.docker @@ -4,10 +4,13 @@ RUN apt-get update \ && apt-get install --no-install-recommends --no-upgrade -y \ build-essential \ cmake \ - gcc-8 \ - g++-8 \ - clang-6.0 \ ninja-build \ + gcc-7 \ + g++-7 \ + clang-6.0 \ + llvm \ + lcov \ + curl \ # scripts to install conan \ python3-pip \ python3-distutils \ @@ -62,7 +65,10 @@ RUN apt-get update \ # conan-sdl2 dependencies https://github.com/bincrafters/conan-sdl2/blob/stable/2.0.8/conanfile.py\ libxinerama-dev \ libxkbcommon-dev \ - && apt-get clean + && apt-get clean \ + && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 60 \ + && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 \ + && update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-7 60 # RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 50 --slave /usr/bin/g++ g++ /usr/bin/g++-8 diff --git a/scripts/docker/docker_build.sh b/scripts/docker/docker_build.sh index 2834dd14..9d2885bc 100755 --- a/scripts/docker/docker_build.sh +++ b/scripts/docker/docker_build.sh @@ -8,7 +8,9 @@ docker=$1 "$curdir/docker_tool.py" build -d "$docker" -t openrw_build_image # Start docker container + add travis user -"$curdir/docker_tool.py" create -t openrw_build_image -n openrw_builder -U travis +"$curdir/docker_tool.py" create -t openrw_build_image -n openrw_builder -U travis \ + -e \ + ALSOFT_DRIVERS=null # Build only "$curdir/docker_tool.py" exec -n openrw_builder -U travis -- /bin/bash -c "cd /build && cmake -VV /src && make" diff --git a/scripts/docker/docker_tool.py b/scripts/docker/docker_tool.py index e7567820..27f174f2 100755 --- a/scripts/docker/docker_tool.py +++ b/scripts/docker/docker_tool.py @@ -32,7 +32,7 @@ def create(ns: argparse.Namespace): env_args = [a for e in ns.env for a in ('-e', e)] env_args += ['-e', 'DOCKER=TRUE', ] run_args = ['docker', 'run', - '-v', '{}:/src:ro,z'.format(str(openrw_dir)), + '-v', '{}:/src:rw,z'.format(str(openrw_dir)), '-v', '{}:/build:rw,z'.format(str(build_dir)) ] + \ env_args + ['--name', ns.name, '-d', ns.tag, 'sleep', 'infinity'] sub_run(run_args) diff --git a/scripts/docker/docker_travis.sh b/scripts/docker/docker_travis.sh index f572362f..229b51b5 100755 --- a/scripts/docker/docker_travis.sh +++ b/scripts/docker/docker_travis.sh @@ -11,12 +11,24 @@ docker=$1 "$curdir/docker_tool.py" create -t openrw_build_image -n openrw_builder -U travis \ -e \ NAME_SUFFIX=$NAME_SUFFIX \ + CI=$CI \ TRAVIS=$TRAVIS \ - TRAVIS_COMMIT=$TRAVIS_COMMIT \ - TRAVIS_EVENT_TYPE=$TRAVIS_EVENT_TYPE \ + SHIPPABLE=$SHIPPABLE \ + CODECOV_ENV=$CODECOV_ENV \ + CODECOV_TOKEN=$CODECOV_TOKEN \ + CODECOV_URL=$CODECOV_URL \ + CODECOV_SLUG=$CODECOV_SLUG \ TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG \ TRAVIS_BRANCH=$TRAVIS_BRANCH \ + TRAVIS_COMMIT=$TRAVIS_COMMIT \ + TRAVIS_JOB_NUMBER=$TRAVIS_JOB_NUMBER \ + TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST \ + TRAVIS_JOB_ID=$TRAVIS_JOB_ID \ + TRAVIS_TAG=$TRAVIS_TAG \ + TRAVIS_OS_NAME=$TRAVIS_OS_NAME \ + TRAVIS_EVENT_TYPE=$TRAVIS_EVENT_TYPE \ USE_CONAN=$USE_CONAN \ + TEST_COVERAGE=$TEST_COVERAGE \ ALSOFT_DRIVERS=null \ CC=$CC \ CXX=$CXX \ @@ -25,4 +37,4 @@ docker=$1 # execute test "$curdir/docker_tool.py" exec -n openrw_builder -U travis -- /bin/bash -c \ - "ctest -VV -S /src/cmake/ctest/script_ci.ctest -VV" + "ctest -VV -S /src/cmake/ctest/script_ci.ctest" diff --git a/scripts/docker/fedora_latest.docker b/scripts/docker/fedora_latest.docker index 167ff3df..912b61f0 100644 --- a/scripts/docker/fedora_latest.docker +++ b/scripts/docker/fedora_latest.docker @@ -10,6 +10,9 @@ RUN dnf update -y \ gcc \ gcc-c++ \ clang \ + llvm \ + lcov \ + curl \ boost-devel \ cmake \ make \ @@ -21,6 +24,7 @@ RUN dnf update -y \ SDL2-devel \ qt5-devel \ freetype-devel \ - libasan + libasan \ + && ln -s /usr/bin/python3 /usr/bin/python CMD ["/bin/bash"] diff --git a/scripts/docker/ubuntu_latest.docker b/scripts/docker/ubuntu_latest.docker index 33342224..1cfb0d9a 100644 --- a/scripts/docker/ubuntu_latest.docker +++ b/scripts/docker/ubuntu_latest.docker @@ -4,9 +4,13 @@ RUN apt-get update \ && apt-get install --no-install-recommends --no-upgrade -y \ build-essential \ cmake \ + ninja-build \ gcc-7 \ g++-7 \ clang-6.0 \ + llvm \ + lcov \ + curl \ libavcodec-dev \ libavformat-dev \ libboost-filesystem-dev \ @@ -19,7 +23,10 @@ RUN apt-get update \ libqt5opengl5-dev \ libfreetype6-dev \ iwyu \ - ninja-build \ - qt5-default + qt5-default \ + && apt-get clean \ + && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 60 \ + && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 \ + && update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-7 60 CMD ["/bin/bash"] diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b91bdaf1..24207aaf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -78,6 +78,7 @@ target_link_libraries(rwtests openrw_target_apply_options( TARGET rwtests + COVERAGE INSTALL INSTALL_PDB )