From 8459ff022bc24af2fb24ca7936f26d31a9c01cba Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Sep 2025 14:43:14 -0400 Subject: [PATCH 1/5] ci: factor out memcheck "prep" logic This is to support running memcheck as part of the "standalone" workflow. --- .gitlab/ci/ctest_memcheck.cmake | 8 +------- .gitlab/ci/ctest_memcheck_prep.cmake | 7 +++++++ 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 .gitlab/ci/ctest_memcheck_prep.cmake diff --git a/.gitlab/ci/ctest_memcheck.cmake b/.gitlab/ci/ctest_memcheck.cmake index 3e3a411cdf..ee5296d57a 100644 --- a/.gitlab/ci/ctest_memcheck.cmake +++ b/.gitlab/ci/ctest_memcheck.cmake @@ -20,13 +20,7 @@ if (NOT "$ENV{CMAKE_CI_TEST_TIMEOUT}" STREQUAL "") set(CTEST_TEST_TIMEOUT "$ENV{CMAKE_CI_TEST_TIMEOUT}") endif () -set(CTEST_MEMORYCHECK_TYPE "$ENV{CTEST_MEMORYCHECK_TYPE}") -set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "$ENV{CTEST_MEMORYCHECK_SANITIZER_OPTIONS}") - -set(lsan_suppressions "${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_$ENV{CMAKE_CONFIGURATION}.lsan.supp") -if (EXISTS "${lsan_suppressions}") - set(ENV{LSAN_OPTIONS} "suppressions='${lsan_suppressions}'") -endif () +include("${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_prep.cmake") include("${CMAKE_CURRENT_LIST_DIR}/ctest_exclusions.cmake") ctest_memcheck( diff --git a/.gitlab/ci/ctest_memcheck_prep.cmake b/.gitlab/ci/ctest_memcheck_prep.cmake new file mode 100644 index 0000000000..e537d51840 --- /dev/null +++ b/.gitlab/ci/ctest_memcheck_prep.cmake @@ -0,0 +1,7 @@ +set(CTEST_MEMORYCHECK_TYPE "$ENV{CTEST_MEMORYCHECK_TYPE}") +set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "$ENV{CTEST_MEMORYCHECK_SANITIZER_OPTIONS}") + +set(lsan_suppressions "${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_$ENV{CMAKE_CONFIGURATION}.lsan.supp") +if (EXISTS "${lsan_suppressions}") + set(ENV{LSAN_OPTIONS} "suppressions='${lsan_suppressions}'") +endif () From 35337bcc0687b2d589c3ae3028125b5c45217894 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Sep 2025 14:43:44 -0400 Subject: [PATCH 2/5] gitlab-ci: report JUnit results for memcheck runs --- .gitlab-ci.yml | 1 + .gitlab/ci/ctest_memcheck.cmake | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f0c72afbe..c2d6c13ab2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1023,6 +1023,7 @@ t:fedora42-asan: - .fedora42_asan - .cmake_memcheck_linux - .linux_x86_64_tags + - .cmake_junit_artifacts - .run_dependent needs: - b:fedora42-asan diff --git a/.gitlab/ci/ctest_memcheck.cmake b/.gitlab/ci/ctest_memcheck.cmake index ee5296d57a..7121015640 100644 --- a/.gitlab/ci/ctest_memcheck.cmake +++ b/.gitlab/ci/ctest_memcheck.cmake @@ -26,6 +26,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/ctest_exclusions.cmake") ctest_memcheck( PARALLEL_LEVEL "${nproc}" TEST_LOAD "${nproc}" + OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml" RETURN_VALUE test_result EXCLUDE "${test_exclusions}" DEFECT_COUNT defects) From f22d8a3f36d57a5caed4b5ed3b7bb7d7b04a14fc Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Sep 2025 14:45:07 -0400 Subject: [PATCH 3/5] ci: support memcheck-testing external test processes --- .gitlab/ci/ctest_standalone.cmake | 39 ++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/.gitlab/ci/ctest_standalone.cmake b/.gitlab/ci/ctest_standalone.cmake index bfee8484ef..298126403d 100644 --- a/.gitlab/ci/ctest_standalone.cmake +++ b/.gitlab/ci/ctest_standalone.cmake @@ -33,6 +33,10 @@ elseif("$ENV{CMAKE_CONFIGURATION}" MATCHES "extdeps") set(CTEST_CONFIGURE_COMMAND "/opt/extdeps/bin/cmake -C \"${initial_cache}\" -G \"${CTEST_CMAKE_GENERATOR}\" \"${CTEST_SOURCE_DIRECTORY}\"") endif() +if ("$ENV{CMAKE_CI_RUN_MEMCHECK}" STREQUAL "true") + include("${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_prep.cmake") +endif () + # Configure the project. ctest_configure( OPTIONS "${cmake_args}" @@ -93,20 +97,37 @@ if (NOT "$ENV{CTEST_LABELS}" STREQUAL "") endif () include("${CMAKE_CURRENT_LIST_DIR}/ctest_exclusions.cmake") -ctest_test( - PARALLEL_LEVEL "${nproc}" - TEST_LOAD "${nproc}" - OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml" - RETURN_VALUE test_result - ${ctest_label_args} - EXCLUDE "${test_exclusions}") -ctest_submit(PARTS Test) +set(extra_annotations) +if ("$ENV{CMAKE_CI_RUN_MEMCHECK}" STREQUAL "true") + ctest_memcheck( + PARALLEL_LEVEL "${nproc}" + TEST_LOAD "${nproc}" + OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml" + RETURN_VALUE test_result + ${ctest_label_args} + EXCLUDE "${test_exclusions}") + ctest_submit(PARTS Test) + ctest_submit(PARTS Memcheck) + list(APPEND extra_annotations + "Dynamic Analysis" "https://open.cdash.org/viewDynamicAnalysis.php?buildid=${build_id}" + ) +else () + ctest_test( + PARALLEL_LEVEL "${nproc}" + TEST_LOAD "${nproc}" + OUTPUT_JUNIT "${CTEST_BINARY_DIRECTORY}/junit.xml" + RETURN_VALUE test_result + ${ctest_label_args} + EXCLUDE "${test_exclusions}") + ctest_submit(PARTS Test) +endif () ctest_annotation_report("${CTEST_BINARY_DIRECTORY}/annotations.json" "All Tests" "https://open.cdash.org/viewTest.php?buildid=${build_id}" "Test Failures" "https://open.cdash.org/viewTest.php?onlyfailed&buildid=${build_id}" "Tests Not Run" "https://open.cdash.org/viewTest.php?onlynotrun&buildid=${build_id}" - "Test Passes" "https://open.cdash.org/viewTest.php?onlypassed&buildid=${build_id}") + "Test Passes" "https://open.cdash.org/viewTest.php?onlypassed&buildid=${build_id}" + ${extra_annotations}) if (test_result) ctest_submit(PARTS Done) From f1e8762a8ba592fb6b7f816f047b7c60019e5c8c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 29 Sep 2025 10:13:33 -0400 Subject: [PATCH 4/5] ci: support valgrind memcheck runs --- .gitlab/artifacts.yml | 13 +++++++++ .gitlab/ci/ctest_memcheck_prep.cmake | 43 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/.gitlab/artifacts.yml b/.gitlab/artifacts.yml index 2d28d8bc11..e33cdc8a05 100644 --- a/.gitlab/artifacts.yml +++ b/.gitlab/artifacts.yml @@ -146,6 +146,19 @@ junit: - ${CMAKE_CI_BUILD_DIR}/junit.xml +.cmake_valgrind_artifacts: + artifacts: + expire_in: 1d + when: always + reports: + annotations: + - ${CMAKE_CI_BUILD_DIR}/annotations.json + junit: + - ${CMAKE_CI_BUILD_DIR}/junit.xml + paths: + # Valgrind logs. + - ${CMAKE_CI_BUILD_DIR}/Testing/Temporary/MemoryChecker.*.log + .cmake_sphinx_artifacts: artifacts: expire_in: 1d diff --git a/.gitlab/ci/ctest_memcheck_prep.cmake b/.gitlab/ci/ctest_memcheck_prep.cmake index e537d51840..1d9d12cc18 100644 --- a/.gitlab/ci/ctest_memcheck_prep.cmake +++ b/.gitlab/ci/ctest_memcheck_prep.cmake @@ -5,3 +5,46 @@ set(lsan_suppressions "${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_$ENV{CMAKE_CONFI if (EXISTS "${lsan_suppressions}") set(ENV{LSAN_OPTIONS} "suppressions='${lsan_suppressions}'") endif () + +if (CTEST_MEMORYCHECK_TYPE STREQUAL "Valgrind") + find_program(valgrind_exe NAMES valgrind) + set(CTEST_MEMORYCHECK_COMMAND "${valgrind_exe}") + + set(valgrind_suppressions "${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_$ENV{CMAKE_CONFIGURATION}.valgrind.supp") + set(common_valgrind_suppressions "${CMAKE_CURRENT_LIST_DIR}/ctest_memcheck_$ENV{CMAKE_VALGRIND_CONFIGURATION}.valgrind.supp") + if (EXISTS "${valgrind_suppressions}") + set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${valgrind_suppressions}") + elseif (EXISTS "${common_valgrind_suppressions}") + set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${common_valgrind_suppressions}") + endif () + + set(valgrind_skip + /bin/* + /sbin/* + /usr/bin/* + /usr/lib64/qt5/bin/* + /usr/lib64/qt6/bin/* + /usr/lib64/qt6/libexec/* + bootstrap + sample_script + */Tests/CTestTest2/kwsysBin/* + */Tests/CTestTestCrash/Crash + *QtAutogen + # Ignore ISPC files which may contain unimplemented instructions. + */build/Tests/ISPC/TryCompile/ISPCTryCompile + # Ignore anything CI downloads. + */.gitlab/*) + list(JOIN valgrind_skip "," valgrind_skip) + string(CONCAT valgrind_options + "--gen-suppressions=all " + "--child-silent-after-fork=yes " + "--trace-children=yes " + "--trace-children-skip=${valgrind_skip} " + "--track-origins=yes " + "-q " + "--leak-check=yes " + "--show-reachable=yes " + "--num-callers=50 " + "-v ") + set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "${valgrind_options}") +endif () From e981fc4f4d1579435d71588e169b3e498c83089e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Sep 2025 14:47:58 -0400 Subject: [PATCH 5/5] gitlab-ci: add a job to test with Valgrind on Linux with Ninja --- .gitlab-ci.yml | 13 +++ .gitlab/ci/.gitattributes | 2 + .../configure_fedora42_ninja_valgrind.cmake | 6 ++ .gitlab/ci/configure_fedora42_valgrind.cmake | 2 + .gitlab/ci/ctest_exclusions.cmake | 14 +++ .../ci/ctest_memcheck_fedora42.valgrind.supp | 91 +++++++++++++++++++ .gitlab/ci/env_fedora42_ninja_valgrind.sh | 1 + .gitlab/os-linux.yml | 25 +++++ 8 files changed, 154 insertions(+) create mode 100644 .gitlab/ci/.gitattributes create mode 100644 .gitlab/ci/configure_fedora42_ninja_valgrind.cmake create mode 100644 .gitlab/ci/configure_fedora42_valgrind.cmake create mode 100644 .gitlab/ci/ctest_memcheck_fedora42.valgrind.supp create mode 100644 .gitlab/ci/env_fedora42_ninja_valgrind.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c2d6c13ab2..df4423b5fe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1030,6 +1030,19 @@ t:fedora42-asan: variables: CMAKE_CI_JOB_NIGHTLY: "true" +t:fedora42-ninja-valgrind: + extends: + - .fedora42_ninja_valgrind + - .cmake_test_linux_release + # Use a fast CPU so that timeouts are less of a concern. + - .linux_x86_64_tags_fast_x11 + - .cmake_valgrind_artifacts + - .run_dependent + - .needs_centos7_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + timeout: 2 hours + # macOS builds b:macos-x86_64-ninja: diff --git a/.gitlab/ci/.gitattributes b/.gitlab/ci/.gitattributes new file mode 100644 index 0000000000..b4f5f9da67 --- /dev/null +++ b/.gitlab/ci/.gitattributes @@ -0,0 +1,2 @@ +# Do not apply a size limit to suppression files. +*.valgrind.supp -hooks-max-size diff --git a/.gitlab/ci/configure_fedora42_ninja_valgrind.cmake b/.gitlab/ci/configure_fedora42_ninja_valgrind.cmake new file mode 100644 index 0000000000..c50e5df4cd --- /dev/null +++ b/.gitlab/ci/configure_fedora42_ninja_valgrind.cmake @@ -0,0 +1,6 @@ +set(CMake_TEST_Qt5 ON CACHE BOOL "") +set(CMake_TEST_Qt6 ON CACHE BOOL "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora42_valgrind.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora42_ninja.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/configure_fedora42_valgrind.cmake b/.gitlab/ci/configure_fedora42_valgrind.cmake new file mode 100644 index 0000000000..01753950bd --- /dev/null +++ b/.gitlab/ci/configure_fedora42_valgrind.cmake @@ -0,0 +1,2 @@ +# Disable bootstrap testing for Valgrind testing. +set(CMAKE_SKIP_BOOTSTRAP_TEST OFF CACHE BOOL "") diff --git a/.gitlab/ci/ctest_exclusions.cmake b/.gitlab/ci/ctest_exclusions.cmake index 89a5ace956..30f796b3e9 100644 --- a/.gitlab/ci/ctest_exclusions.cmake +++ b/.gitlab/ci/ctest_exclusions.cmake @@ -27,6 +27,20 @@ if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "_jom") ) endif() +if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "_valgrind") + list(APPEND test_exclusions + # Tests that timeout under valgrind. + "^RunCMake.NinjaMultiConfig$" + "^RunCMake.Autogen_Qt6_1$" + "^RunCMake.GoogleTest$" + "^RunCMake.CXXModules$" + "^RunCMake.CommandLine$" + + # Too spurious under Valgrind. + "^RunCMake.testUVProcessChain$" + ) +endif() + string(REPLACE ";" "|" test_exclusions "${test_exclusions}") if (test_exclusions) set(test_exclusions "(${test_exclusions})") diff --git a/.gitlab/ci/ctest_memcheck_fedora42.valgrind.supp b/.gitlab/ci/ctest_memcheck_fedora42.valgrind.supp new file mode 100644 index 0000000000..acc1d2ceae --- /dev/null +++ b/.gitlab/ci/ctest_memcheck_fedora42.valgrind.supp @@ -0,0 +1,91 @@ +# Add Valgrind suppressions here. +{ + libc_start_main-malloc + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:__libc_start_main@@GLIBC_2.34 + ... +} +{ + dl_init-malloc + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:_dl_init + ... +} +{ + dl_init-calloc + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + ... + fun:_dl_init + ... +} +{ + dl_init-realloc + Memcheck:Leak + match-leak-kinds: reachable + fun:realloc + ... + fun:_dl_init + ... +} +{ + dl_open-malloc + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:_dl_open + ... +} +{ + dl_open-calloc + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + ... + fun:_dl_open + ... +} +{ + qt5-object-new + Memcheck:Leak + match-leak-kinds: reachable + fun:_Znwm + ... + fun:_ZN7QObjectC1ER14QObjectPrivatePS_ + ... +} +{ + qt5-logger-malloc + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + ... + fun:_ZNK14QMessageLogger5debugEv + ... +} +{ + strerror_l-malloc + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + fun:__vasprintf_internal + fun:__asprintf_chk + fun:strerror_l + ... +} +{ + bash + Memcheck:Leak + match-leak-kinds: reachable + ... + obj:/usr/bin/bash + ... +} diff --git a/.gitlab/ci/env_fedora42_ninja_valgrind.sh b/.gitlab/ci/env_fedora42_ninja_valgrind.sh new file mode 100644 index 0000000000..7ddc9e8ecc --- /dev/null +++ b/.gitlab/ci/env_fedora42_ninja_valgrind.sh @@ -0,0 +1 @@ +source .gitlab/ci/env_fedora42_ninja.sh diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 42daea4ec1..e552ea4c6b 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -337,6 +337,15 @@ CTEST_MEMORYCHECK_TYPE: AddressSanitizer CTEST_MEMORYCHECK_SANITIZER_OPTIONS: "" +.fedora_valgrind_addon: + extends: .fedora_memcheck + + variables: + CTEST_MEMORYCHECK_TYPE: Valgrind + CMAKE_CI_RUN_MEMCHECK: "true" + CMAKE_CI_TEST_TIMEOUT: "1500" + CMAKE_VALGRIND_CONFIGURATION: fedora42 + .fedora42_asan: extends: - .fedora42 @@ -345,6 +354,15 @@ variables: CMAKE_CONFIGURATION: fedora42_asan + +.fedora42_ninja_valgrind: + extends: + - .fedora42 + - .fedora_valgrind_addon + + variables: + CMAKE_CONFIGURATION: fedora42_ninja_valgrind + ### Intel Compiler .intelcompiler: @@ -616,6 +634,13 @@ - linux-x86_64 - x11 +.linux_x86_64_tags_fast_x11: + tags: + - cmake + - docker + - linux-x86_64-v4 + - x11 + .linux_x86_64_tags_cuda_arch_30: tags: - cmake