From 6dd489eed93bd802aa156f60115c6983927273a9 Mon Sep 17 00:00:00 2001 From: light7734 Date: Sun, 20 Jul 2025 14:53:34 +0330 Subject: [PATCH 01/12] ci: add lcov dockerfile --- tools/ci/amd64/clang/coverage.dockerfile | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tools/ci/amd64/clang/coverage.dockerfile diff --git a/tools/ci/amd64/clang/coverage.dockerfile b/tools/ci/amd64/clang/coverage.dockerfile new file mode 100644 index 0000000..bf54cdf --- /dev/null +++ b/tools/ci/amd64/clang/coverage.dockerfile @@ -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/ -- 2.45.3 From 9d31a5eb1a56293eb3ce46f5908fd20efaa6a812 Mon Sep 17 00:00:00 2001 From: light7734 Date: Sun, 20 Jul 2025 14:53:58 +0330 Subject: [PATCH 02/12] build: add enable_lcov compiler option --- CMakeLists.txt | 12 +++++++++++- conanfile.py | 5 ++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a88bf5..0c1508b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.14) project(Light) set(CMAKE_CXX_STANDARD 23) +add_option(ENABLE_TESTS "Enables the building of the test modules") 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) @@ -11,6 +12,15 @@ 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_LCOV "Enables the code coverage instrumentation for clang") +if(ENABLE_LCOV) + if (CMAKE_CXX_COMPILER_ID NOT STREQUAL "Clang") + message(FATAL_ERROR "ENABLE_LCOV option is only supported when compiling with clang") + 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) diff --git a/conanfile.py b/conanfile.py index 47348bc..b9e6f07 100644 --- a/conanfile.py +++ b/conanfile.py @@ -12,6 +12,7 @@ class LightRecipe(ConanFile): options = { "enable_tests": [True, False], + "enable_lcov": [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_lcov": 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_LCOV"] = self.options.enable_lcov + 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 -- 2.45.3 From d6ff7cdc8baf9cef1edc8537f7c733144fe7ae4b Mon Sep 17 00:00:00 2001 From: light7734 Date: Sun, 20 Jul 2025 14:54:12 +0330 Subject: [PATCH 03/12] ci: add lcov ci script --- tools/ci/amd64/clang/coverage.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/ci/amd64/clang/coverage.sh b/tools/ci/amd64/clang/coverage.sh index 6a03ffe..51b813b 100755 --- a/tools/ci/amd64/clang/coverage.sh +++ b/tools/ci/amd64/clang/coverage.sh @@ -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_lcov=True \ --build=missing for test in $(find ./build -type f -name '*_tests' -executable); do -- 2.45.3 From 87619a9ce340fba1d33e3bb4ca80fc83745cd618 Mon Sep 17 00:00:00 2001 From: light7734 Date: Sun, 20 Jul 2025 14:56:40 +0330 Subject: [PATCH 04/12] ci: add clang coverage to build_ci_images script --- tools/scripts/build_ci_images.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/scripts/build_ci_images.sh b/tools/scripts/build_ci_images.sh index adb718e..8ba6376 100755 --- a/tools/scripts/build_ci_images.sh +++ b/tools/scripts/build_ci_images.sh @@ -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_msan" +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 . -- 2.45.3 From f67a4b0392ab0bfcdf7d38e30ebfb1fded8ee48e Mon Sep 17 00:00:00 2001 From: light7734 Date: Sun, 20 Jul 2025 14:56:52 +0330 Subject: [PATCH 05/12] ci: add clang code coverage step & fix image names --- .drone.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index 283384d..af1a0fd 100644 --- a/.drone.yml +++ b/.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,20 @@ trigger: - main steps: +- name: code coverage + image: amd64_clang_coverage:latest + pull: if-not-exists + 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 -- 2.45.3 From 3eb98c1e8125287ec6e4ab33ab75981bf16a2511 Mon Sep 17 00:00:00 2001 From: light7734 Date: Sun, 20 Jul 2025 14:59:33 +0330 Subject: [PATCH 06/12] ci: fix build_ci_images typo --- tools/scripts/build_ci_images.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/build_ci_images.sh b/tools/scripts/build_ci_images.sh index 8ba6376..4919748 100755 --- a/tools/scripts/build_ci_images.sh +++ b/tools/scripts/build_ci_images.sh @@ -15,7 +15,7 @@ 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_msan" +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" -- 2.45.3 From 6d41482576e614fbb8c821ba4a729534df8713c0 Mon Sep 17 00:00:00 2001 From: light7734 Date: Mon, 21 Jul 2025 12:29:29 +0330 Subject: [PATCH 07/12] build: minor refactors --- CMakeLists.txt | 29 ++++++++++++++++++++++------- conanfile.py | 6 +++--- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c1508b..19da931 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,23 +1,38 @@ cmake_minimum_required(VERSION 3.14) project(Light) set(CMAKE_CXX_STANDARD 23) +set(CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake) + +include(${CMAKE_DIR}/functions.cmake) +include(${CMAKE_DIR}/definitions.cmake) +include(${CMAKE_DIR}/dependencies.cmake) add_option(ENABLE_TESTS "Enables the building of the test modules") -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) -add_option(ENABLE_STATIC_ANALYSIS "Performs static analysis via clang-tidy and fails build on failing checks") +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_LCOV "Enables the code coverage instrumentation for clang") -if(ENABLE_LCOV) +add_option(ENABLE_LLVM_COVERAGE "Enables the code coverage instrumentation for clang") +if(ENABLE_LLVM_COVERAGE) if (CMAKE_CXX_COMPILER_ID NOT STREQUAL "Clang") - message(FATAL_ERROR "ENABLE_LCOV option is only supported when compiling with clang") + message(FATAL_ERROR "ENABLE_LLVM_COVERAGE only supports the clang compiler") endif () + # Check for libc++ + check_cxx_source_compiles(" + #include + #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 () diff --git a/conanfile.py b/conanfile.py index b9e6f07..18e21bc 100644 --- a/conanfile.py +++ b/conanfile.py @@ -12,7 +12,7 @@ class LightRecipe(ConanFile): options = { "enable_tests": [True, False], - "enable_lcov": [True, False], + "enable_llvm_coverage": [True, False], "enable_static_analysis": [True, False], "use_mold": [True, False], "export_compile_commands": [True, False], @@ -20,7 +20,7 @@ class LightRecipe(ConanFile): default_options = { "enable_tests": True, - "enable_lcov": False, + "enable_llvm_coverage": False, "enable_static_analysis": False, "use_mold": False, "export_compile_commands": True, @@ -47,7 +47,7 @@ class LightRecipe(ConanFile): tc.cache_variables["CMAKE_EXPORT_COMPILE_COMMANDS"] = self.options.export_compile_commands tc.cache_variables["ENABLE_TESTS"] = self.options.enable_tests - tc.cache_variables["ENABLE_LCOV"] = self.options.enable_lcov + 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) -- 2.45.3 From aa6967fa40fbd1afbd25c28e65b81f862ccb209b Mon Sep 17 00:00:00 2001 From: light7734 Date: Mon, 21 Jul 2025 12:37:46 +0330 Subject: [PATCH 08/12] build: fix cmakelists if statement --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19da931..20829ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ endif () add_option(ENABLE_LLVM_COVERAGE "Enables the code coverage instrumentation for clang") if(ENABLE_LLVM_COVERAGE) - if (CMAKE_CXX_COMPILER_ID NOT STREQUAL "Clang") + if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") message(FATAL_ERROR "ENABLE_LLVM_COVERAGE only supports the clang compiler") endif () -- 2.45.3 From 50dbb1fddfd75bcdbbda380e48ef6f78ae934e21 Mon Sep 17 00:00:00 2001 From: light7734 Date: Mon, 21 Jul 2025 12:40:23 +0330 Subject: [PATCH 09/12] build: add include(CheckCXXSourceCompiles) to root cmake lists --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20829ea..7cc9934 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(Light) set(CMAKE_CXX_STANDARD 23) set(CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake) +include(CheckCXXSourceCompiles) include(${CMAKE_DIR}/functions.cmake) include(${CMAKE_DIR}/definitions.cmake) include(${CMAKE_DIR}/dependencies.cmake) -- 2.45.3 From c064a7017af21074f04a836c75cab21f04bec241 Mon Sep 17 00:00:00 2001 From: light7734 Date: Mon, 21 Jul 2025 12:55:57 +0330 Subject: [PATCH 10/12] ci: add clang code coverage check --- .drone.yml | 3 +++ tools/ci/amd64/clang/coverage.sh | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index af1a0fd..159dc65 100644 --- a/.drone.yml +++ b/.drone.yml @@ -48,6 +48,9 @@ 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 diff --git a/tools/ci/amd64/clang/coverage.sh b/tools/ci/amd64/clang/coverage.sh index 51b813b..5141e92 100755 --- a/tools/ci/amd64/clang/coverage.sh +++ b/tools/ci/amd64/clang/coverage.sh @@ -13,7 +13,7 @@ conan build . \ -s compiler.version=20 \ -s compiler.libcxx=libc++ \ -o use_mold=True \ - -o enable_lcov=True \ + -o enable_llvm_coverage=True \ --build=missing for test in $(find ./build -type f -name '*_tests' -executable); do @@ -21,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 -- 2.45.3 From 3b63449bdc9675da449a44d7b1d75870dfdd304d Mon Sep 17 00:00:00 2001 From: light7734 Date: Mon, 21 Jul 2025 12:59:50 +0330 Subject: [PATCH 11/12] ci: fix amd64/clang/coverage.sh --- tools/ci/amd64/clang/coverage.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci/amd64/clang/coverage.sh b/tools/ci/amd64/clang/coverage.sh index 5141e92..60f409f 100755 --- a/tools/ci/amd64/clang/coverage.sh +++ b/tools/ci/amd64/clang/coverage.sh @@ -24,12 +24,12 @@ 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; + 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" +echo "${LLVM_COV_SHOW}" > "./build/coverage/coverage.txt" wget -qO- "https://codecov.io/bash" | bash -- 2.45.3 From a1e94e9814ed264d205cc52b82b64d2c05f6f4c1 Mon Sep 17 00:00:00 2001 From: light7734 Date: Mon, 21 Jul 2025 13:04:36 +0330 Subject: [PATCH 12/12] ci: fix amd64/clang/coverage.sh --- tools/ci/amd64/clang/coverage.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ci/amd64/clang/coverage.sh b/tools/ci/amd64/clang/coverage.sh index 60f409f..4935ad3 100755 --- a/tools/ci/amd64/clang/coverage.sh +++ b/tools/ci/amd64/clang/coverage.sh @@ -30,6 +30,6 @@ 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" +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 -- 2.45.3