Hi everyone,
I currently explore the possibilities of cmake scripting to run sanitizers and tests. But it seems to be not working.
# This file is supposed to run in ctest script mode:
# ctest -S <path-to-this-file>/CTestScript.cmake
#
# You can set some command line variables to change the behaviour of this script:
#
# -DCTEST_CONFIGURATION_TYPE:STRING=DEBUG|RELEASE|MSAN|ASAN|LSAN|TSAN|UBSAN|COVERAGE
# -DCTEST_MODEL:STRING=Experimental|Nightly|Continuous
# -DCTEST_CMAKE_GENERATOR:STRING=Ninja|Unix Makefiles|...)
# Memory checker (MemoryCheckCommand) not set, or cannot find the specified program. -> Doesn't stop the CI
include(${CTEST_SCRIPT_DIRECTORY}/CTestConfig.cmake)
site_name(CTEST_SITE)
set(CTEST_BUILD_NAME ${CMAKE_HOST_SYSTEM_NAME})
set(CTEST_SOURCE_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}")
set(CTEST_BINARY_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}/build")
if(NOT DEFINED CTEST_CMAKE_GENERATOR)
set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
endif()
if(NOT DEFINED CTEST_CONFIGURATION_TYPE)
set(CTEST_CONFIGURATION_TYPE "DEBUG")
endif()
if(CTEST_CONFIGURATION_TYPE STREQUAL "ASAN")
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
set(configureOpts
"-DCMAKE_CXX_FLAGS_INIT=-fsanitize=address -fno-omit-frame-pointer"
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fsanitize=address -fno-omit-frame-pointer"
)
# set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "verbosity=1:exitcode=-1:check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:detect_invalid_pointer_pairs=10:strict_string_checks=true")
elseif(CTEST_CONFIGURATION_TYPE STREQUAL "MSAN")
set(CTEST_MEMORYCHECK_TYPE "MemorySanitizer")
set(configureOpts
"-DCMAKE_CXX_FLAGS_INIT=-fsanitize=memory -fno-omit-frame-pointer"
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fsanitize=memory -fno-omit-frame-pointer"
)
# set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "verbosity=1:exitcode=-1")
elseif(CTEST_CONFIGURATION_TYPE STREQUAL "LSAN")
set(CTEST_MEMORYCHECK_TYPE "LeakSanitizer")
set(configureOpts
"-DCMAKE_CXX_FLAGS_INIT=-fsanitize=leak -fno-omit-frame-pointer"
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fsanitize=leak -fno-omit-frame-pointer"
)
# set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "verbosity=1:exitcode=-1")
elseif(CTEST_CONFIGURATION_TYPE STREQUAL "TSAN")
set(CTEST_MEMORYCHECK_TYPE "ThreadSanitizer")
set(configureOpts
"-DCMAKE_CXX_FLAGS_INIT=-fsanitize=thread -fno-omit-frame-pointer"
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fsanitize=thread -fno-omit-frame-pointer"
)
# set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "verbosity=1:exitcode=-1")
elseif(CTEST_CONFIGURATION_TYPE STREQUAL "UBSAN")
set(CTEST_MEMORYCHECK_TYPE "UndefinedBehaviorSanitizer")
set(configureOpts
"-DCMAKE_CXX_FLAGS_INIT=-fsanitize=undefined -fno-omit-frame-pointer"
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fsanitize=undefined -fno-omit-frame-pointer"
)
# set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS "verbosity=1:exitcode=-1:print_stacktrace=1")
# elseif(CTEST_CONFIGURATION_TYPE STREQUAL "Valgrind")
# find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind)
# set(CTEST_MEMORYCHECK_TYPE Valgrind)
# set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "--errors-for-leak-kinds=all --show-leak-kinds=all --leak-check=full --error-exitcode=1")
# set(CTEST_CONFIGURATION_TYPE "Debug")
#set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CTEST_SOURCE_DIRECTORY}/tests/valgrind.supp)
endif()
if(NOT DEFINED CTEST_MODEL)
set(CTEST_MODEL "Continuous")
endif()
# Dashboard actions to execute, always clearing the build directory first
ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY})
ctest_start(${CTEST_MODEL})
ctest_configure(OPTIONS "${configureOpts}")
ctest_build()
ctest_memcheck()
ctest_test()
ctest_submit()
And I then run the script with:
ctest -S CTestScript.cmake -DCTEST_CONFIGURATION_TYPE=LSAN
and again with the other sanitizers.
It also uploads to the CDash, but it says everything is alright and I built this in the main.cpp:
// test memory leak
double* my_array = new double[1000];
std::cout << my_array;
When I run manually with LSAN it actually shows the memory leak.
I do get the following error:
Cannot find memory tester output file: /home/leon/Dokumente/Projects/beans/build/Testing /Temporary/MemoryChecker.1.log.*
So what am I missing? What sources / targets are actually checked? And why do I have to specify the flags if I already set set(CTEST_MEMORYCHECK_TYPE “LeakSanitizer”).
I would also be greatfull for helpful resources. I found a few words and example in “Professional cmake” and other sources, but it wasn’t so detailed.
In the end, I want to actually not use CDash at all, but rather use it with gitlab pipeline. But I figured, starting with CDash might be easier.