ci: add clang code coverage check #10
					 6 changed files with 112 additions and 14 deletions
				
			
		
							
								
								
									
										17
									
								
								.drone.yml
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								.drone.yml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -25,13 +25,13 @@ trigger:
 | 
			
		|||
 | 
			
		||||
steps:
 | 
			
		||||
- name: unit tests
 | 
			
		||||
  image: unit_tests:latest
 | 
			
		||||
  image: amd64_gcc_unit_tests:latest
 | 
			
		||||
  pull: if-not-exists
 | 
			
		||||
  commands:
 | 
			
		||||
    - ./tools/ci/amd64/gcc/unit_tests.sh
 | 
			
		||||
 | 
			
		||||
- name: valgrind
 | 
			
		||||
  image: valgrind:latest
 | 
			
		||||
  image: amd64_gcc_valgrind:latest
 | 
			
		||||
  pull: if-not-exists
 | 
			
		||||
  commands:
 | 
			
		||||
    - ./tools/ci/amd64/gcc/valgrind.sh
 | 
			
		||||
| 
						 | 
				
			
			@ -45,14 +45,23 @@ trigger:
 | 
			
		|||
  - main
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
- name: code coverage
 | 
			
		||||
  image: amd64_clang_coverage:latest
 | 
			
		||||
  pull: if-not-exists
 | 
			
		||||
  environment:
 | 
			
		||||
    CODECOV_TOKEN:
 | 
			
		||||
      from_secret: CODECOV_TOKEN 
 | 
			
		||||
  commands:
 | 
			
		||||
    - ./tools/ci/amd64/clang/coverage.sh
 | 
			
		||||
 | 
			
		||||
- name: leak sanitizer
 | 
			
		||||
  image: leak_sanitizer:latest
 | 
			
		||||
  image: amd64_clang_lsan:latest
 | 
			
		||||
  pull: if-not-exists
 | 
			
		||||
  commands:
 | 
			
		||||
    - ./tools/ci/amd64/clang/lsan.sh
 | 
			
		||||
 | 
			
		||||
- name: memory sanitizer
 | 
			
		||||
  image: memory_sanitizer:latest
 | 
			
		||||
  image: amd64_clang_msan:latest
 | 
			
		||||
  pull: if-not-exists
 | 
			
		||||
  commands:
 | 
			
		||||
    - ./tools/ci/amd64/clang/msan.sh
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,42 @@
 | 
			
		|||
cmake_minimum_required(VERSION 3.14)
 | 
			
		||||
project(Light)
 | 
			
		||||
set(CMAKE_CXX_STANDARD 23)
 | 
			
		||||
set(CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake)
 | 
			
		||||
 | 
			
		||||
include(${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake/functions.cmake)
 | 
			
		||||
include(${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake/definitions.cmake)
 | 
			
		||||
include(${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake/dependencies.cmake)
 | 
			
		||||
include(CheckCXXSourceCompiles)
 | 
			
		||||
include(${CMAKE_DIR}/functions.cmake)
 | 
			
		||||
include(${CMAKE_DIR}/definitions.cmake)
 | 
			
		||||
include(${CMAKE_DIR}/dependencies.cmake)
 | 
			
		||||
 | 
			
		||||
add_option(ENABLE_STATIC_ANALYSIS "Performs static analysis via clang-tidy and fails build on failing checks")
 | 
			
		||||
add_option(ENABLE_TESTS "Enables the building of the test modules")
 | 
			
		||||
 | 
			
		||||
add_option(ENABLE_STATIC_ANALYSIS "Makes clang-tidy checks mandatory for compilation")
 | 
			
		||||
if (ENABLE_STATIC_ANALYSIS)
 | 
			
		||||
    set(CMAKE_CXX_CLANG_TIDY "clang-tidy;--warnings-as-errors=*;--allow-no-checks")
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
add_option(ENABLE_TESTS "Enables the building of the test modules")
 | 
			
		||||
add_option(ENABLE_LLVM_COVERAGE "Enables the code coverage instrumentation for clang")
 | 
			
		||||
if(ENABLE_LLVM_COVERAGE)
 | 
			
		||||
    if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
 | 
			
		||||
        message(FATAL_ERROR "ENABLE_LLVM_COVERAGE only supports the clang compiler")
 | 
			
		||||
    endif ()
 | 
			
		||||
 | 
			
		||||
    # Check for libc++
 | 
			
		||||
    check_cxx_source_compiles("
 | 
			
		||||
        #include <string>
 | 
			
		||||
        #ifdef _LIBCPP_VERSION
 | 
			
		||||
        int main() { return 0; }
 | 
			
		||||
        #else
 | 
			
		||||
        #error Not using libc++
 | 
			
		||||
        #endif
 | 
			
		||||
    " USING_LIBCXX)
 | 
			
		||||
    if(NOT USING_LIBCXX)
 | 
			
		||||
        message(FATAL_ERROR "ENABLE_LLVM_COVERAGE requires libc++, please compile with -stdlib=libc++")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    add_compile_options(-fprofile-instr-generate -fcoverage-mapping)
 | 
			
		||||
    add_link_options(-fprofile-instr-generate -fcoverage-mapping)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/modules)
 | 
			
		||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/glad)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ class LightRecipe(ConanFile):
 | 
			
		|||
 | 
			
		||||
    options = {
 | 
			
		||||
        "enable_tests": [True, False],
 | 
			
		||||
        "enable_llvm_coverage": [True, False],
 | 
			
		||||
        "enable_static_analysis": [True, False],
 | 
			
		||||
        "use_mold": [True, False],
 | 
			
		||||
        "export_compile_commands": [True, False],
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +20,7 @@ class LightRecipe(ConanFile):
 | 
			
		|||
 | 
			
		||||
    default_options = {
 | 
			
		||||
        "enable_tests": True,
 | 
			
		||||
        "enable_llvm_coverage": False,
 | 
			
		||||
        "enable_static_analysis": False,
 | 
			
		||||
        "use_mold": False,
 | 
			
		||||
        "export_compile_commands": True,
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +46,9 @@ class LightRecipe(ConanFile):
 | 
			
		|||
            tc.cache_variables["CMAKE_LINKER_TYPE"] = "MOLD"
 | 
			
		||||
 | 
			
		||||
        tc.cache_variables["CMAKE_EXPORT_COMPILE_COMMANDS"] = self.options.export_compile_commands
 | 
			
		||||
        tc.cache_variables["ENABLE_STATIC_ANALYSIS"] = self.options.enable_static_analysis
 | 
			
		||||
        tc.cache_variables["ENABLE_TESTS"] = self.options.enable_tests
 | 
			
		||||
        tc.cache_variables["ENABLE_LLVM_COVERAGE"] = self.options.enable_llvm_coverage
 | 
			
		||||
        tc.cache_variables["ENABLE_STATIC_ANALYSIS"] = self.options.enable_static_analysis
 | 
			
		||||
 | 
			
		||||
        repo = git.Repo(search_parent_directories=True)
 | 
			
		||||
        tc.cache_variables["GIT_HASH"] = repo.head.object.hexsha
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										48
									
								
								tools/ci/amd64/clang/coverage.dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tools/ci/amd64/clang/coverage.dockerfile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
FROM archlinux:latest
 | 
			
		||||
 | 
			
		||||
RUN pacman -Syu --noconfirm && \
 | 
			
		||||
    pacman -S --noconfirm \
 | 
			
		||||
    bash \
 | 
			
		||||
    base-devel \
 | 
			
		||||
    git \
 | 
			
		||||
    cmake \
 | 
			
		||||
    ninja \
 | 
			
		||||
    python \
 | 
			
		||||
    python-pip \
 | 
			
		||||
    clang \
 | 
			
		||||
    llvm \
 | 
			
		||||
    mesa \
 | 
			
		||||
    mold \
 | 
			
		||||
    ninja \
 | 
			
		||||
    curl \
 | 
			
		||||
    wget \
 | 
			
		||||
    zlib
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir --break-system-packages conan gitpython \
 | 
			
		||||
    && conan profile detect
 | 
			
		||||
 | 
			
		||||
RUN clang --version  \
 | 
			
		||||
    && pip --version \
 | 
			
		||||
    && conan --version \
 | 
			
		||||
    && cmake --version \
 | 
			
		||||
    && g++ --version \
 | 
			
		||||
    && clang --version \
 | 
			
		||||
    && ninja --version \
 | 
			
		||||
    && mold --version \
 | 
			
		||||
    && llvm-profdata --version \
 | 
			
		||||
    && llvm-cov --version
 | 
			
		||||
 | 
			
		||||
RUN git clone 'https://git.light7734.com/light7734/light.git' \
 | 
			
		||||
    && cd light; git checkout 'ci/code_cov' \
 | 
			
		||||
    && conan build . \
 | 
			
		||||
        -c tools.system.package_manager:mode=install \
 | 
			
		||||
        -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
        -c tools.build:compiler_executables='{"c": "clang", "cpp": "clang++"}' \
 | 
			
		||||
        -s build_type=Release \
 | 
			
		||||
        -s compiler=clang \
 | 
			
		||||
        -s compiler.version=20 \
 | 
			
		||||
        -s compiler.libcxx=libc++ \
 | 
			
		||||
        -o use_mold=True \
 | 
			
		||||
        -o enable_lcov=True \
 | 
			
		||||
        --build=missing \
 | 
			
		||||
    && rm -r ../light/
 | 
			
		||||
| 
						 | 
				
			
			@ -7,16 +7,13 @@ rm -rf ./build
 | 
			
		|||
conan build . \
 | 
			
		||||
    -c tools.system.package_manager:mode=install \
 | 
			
		||||
    -c tools.cmake.cmaketoolchain:generator=Ninja \
 | 
			
		||||
    -c tools.build:cxxflags='["-fprofile-instr-generate", "-fcoverage-mapping"]' \
 | 
			
		||||
    -c tools.build:sharedlinkflags='["-fprofile-instr-generate", "-fcoverage-mapping"]' \
 | 
			
		||||
    -c tools.build:exelinkflags='["-fprofile-instr-generate", "-fcoverage-mapping"]' \
 | 
			
		||||
    -c tools.info.package_id:confs='["tools.build:cxxflags","tools.build:sharedlinkflags","tools.build:exelinkflags"]' \
 | 
			
		||||
    -c tools.build:compiler_executables='{"c": "clang", "cpp": "clang++"}' \
 | 
			
		||||
    -s build_type=Release \
 | 
			
		||||
    -s compiler=clang \
 | 
			
		||||
    -s compiler.version=20 \
 | 
			
		||||
    -s compiler.libcxx=libc++ \
 | 
			
		||||
    -o use_mold=True \
 | 
			
		||||
    -o enable_llvm_coverage=True \
 | 
			
		||||
    --build=missing
 | 
			
		||||
 | 
			
		||||
for test in $(find ./build -type f -name '*_tests' -executable); do
 | 
			
		||||
| 
						 | 
				
			
			@ -24,3 +21,15 @@ for test in $(find ./build -type f -name '*_tests' -executable); do
 | 
			
		|||
  "$test"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
mkdir -p ./build/coverage/ 
 | 
			
		||||
for test in $(find ./build -type f -name '*_tests' -executable); do
 | 
			
		||||
    export LLVM_PROFILE_FILE="./build/coverage/$(basename "$(dirname "{}")").profraw";
 | 
			
		||||
    echo ${LLVM_PROFILE_FILE} >> ./build/coverage/list;
 | 
			
		||||
    "$test"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
llvm-profdata merge --input-files './build/coverage/list' -o "./build/coverage/merged.profdata" 
 | 
			
		||||
find ./modules -type f -name "*.profraw" -exec rm -fv {} +
 | 
			
		||||
LLVM_COV_SHOW=$(llvm-cov show -instr-profile='./build/coverage/merged.profdata' $(find ./build -type f -name '*_tests' -executable -exec printf -- '-object %s ' {} \;) -ignore-filename-regex='./modules/[^/]+/*_tests')
 | 
			
		||||
echo "${LLVM_COV_SHOW}" > './build/coverage/coverage.txt'
 | 
			
		||||
wget -qO- "https://codecov.io/bash" | bash
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,9 @@ docker build -t amd64_gcc_unit_tests -f $CI_DIR/amd64/gcc/unit_tests.dockerfile
 | 
			
		|||
echo "==> Building image: amd64_gcc_valgrind"
 | 
			
		||||
docker build -t amd64_gcc_valgrind -f $CI_DIR/amd64/gcc/valgrind.dockerfile .
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_clang_coverage"
 | 
			
		||||
docker build -t amd64_clang_coverage -f $CI_DIR/amd64/clang/coverage.dockerfile .
 | 
			
		||||
 | 
			
		||||
echo "==> Building image: amd64_clang_lsan"
 | 
			
		||||
docker build -t amd64_clang_lsan -f $CI_DIR/amd64/clang/lsan.dockerfile .
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue