Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 22 additions & 33 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.26)
cmake_minimum_required(VERSION 3.28)

# NOTE: update executable name in .github/workflows/cmake.yml:25 when changing executable name in this file
# NOTE: update executable name in .github/workflows/cmake.yml when changing executable name in this file
# for now, the project name is used as the executable name
set(MAIN_PROJECT_NAME "oop")
set(MAIN_EXECUTABLE_NAME "${MAIN_PROJECT_NAME}")
set(MAIN_PROJECT_LIB_NAME "${MAIN_PROJECT_NAME}_lib")
set(MAIN_PROJECT_NO_SAN_LIB_NAME "${MAIN_PROJECT_NAME}_nslib")
set(MAIN_LIBRARY_NAME "${MAIN_PROJECT_NAME}_lib")
set(MAIN_LIBRARY_NO_SAN_NAME "${MAIN_PROJECT_NAME}_nslib")
set(TESTS_PROJECT_NAME "${MAIN_PROJECT_NAME}_test")
set(TESTS_EXECUTABLE_NAME "${TESTS_PROJECT_NAME}")

Expand All @@ -22,9 +22,10 @@ set(CMAKE_CXX_EXTENSIONS OFF)
include(cmake/Options.cmake)
include(cmake/CompilerFlags.cmake)
include(cmake/CopyHelper.cmake)
include(cmake/RegisterTests.cmake)

# include(CTest) declares BUILD_TESTING (default ON)
include(CTest)
enable_testing()
###############################################################################

# external dependencies with FetchContent
Expand Down Expand Up @@ -55,15 +56,15 @@ enable_testing()

###############################################################################

# NOTE: update executable name in .github/workflows/cmake.yml:25 when changing name here
add_library(${MAIN_PROJECT_LIB_NAME})
target_sources(${MAIN_PROJECT_LIB_NAME}
# NOTE: update executable name in .github/workflows/cmake.yml when changing name here
add_library(${MAIN_LIBRARY_NAME} STATIC)
target_sources(${MAIN_LIBRARY_NAME}
PRIVATE
src/exemplu_test_oop/BankAccount.cpp
)

add_library(${MAIN_PROJECT_NO_SAN_LIB_NAME})
target_sources(${MAIN_PROJECT_NO_SAN_LIB_NAME}
add_library(${MAIN_LIBRARY_NO_SAN_NAME} STATIC)
target_sources(${MAIN_LIBRARY_NO_SAN_NAME}
PRIVATE
src/exemplu_test_oop/BankAccount.cpp
)
Expand All @@ -80,34 +81,34 @@ target_sources(${MAIN_EXECUTABLE_NAME}

# NOTE: Add all defined targets (e.g. executables, libraries, etc. )
# NOTE: RUN_SANITIZERS is optional, if it's not present it will default to true
set_compiler_flags(RUN_SANITIZERS ${USE_ASAN} TARGET_NAMES ${MAIN_EXECUTABLE_NAME} ${MAIN_PROJECT_LIB_NAME})
set_compiler_flags(RUN_SANITIZERS FALSE TARGET_NAMES ${MAIN_PROJECT_NO_SAN_LIB_NAME})
set_compiler_flags(RUN_SANITIZERS ${USE_ASAN} TARGET_NAMES ${MAIN_EXECUTABLE_NAME} ${MAIN_LIBRARY_NAME})
set_compiler_flags(RUN_SANITIZERS FALSE TARGET_NAMES ${MAIN_LIBRARY_NO_SAN_NAME})
# set_compiler_flags(TARGET_NAMES ${MAIN_EXECUTABLE_NAME} ${FOO} ${BAR})
# where ${FOO} and ${BAR} represent additional executables or libraries
# you want to compile with the set compiler flags

###############################################################################

target_include_directories(${MAIN_PROJECT_LIB_NAME} PUBLIC
target_include_directories(${MAIN_LIBRARY_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
)
target_include_directories(${MAIN_PROJECT_NO_SAN_LIB_NAME} PUBLIC
target_include_directories(${MAIN_LIBRARY_NO_SAN_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
)
target_include_directories(${MAIN_EXECUTABLE_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
)
target_include_directories(${MAIN_PROJECT_LIB_NAME} SYSTEM PRIVATE
target_include_directories(${MAIN_LIBRARY_NAME} SYSTEM PRIVATE
${CMAKE_SOURCE_DIR}/ext
)
target_include_directories(${MAIN_PROJECT_NO_SAN_LIB_NAME} SYSTEM PRIVATE
target_include_directories(${MAIN_LIBRARY_NO_SAN_NAME} SYSTEM PRIVATE
${CMAKE_SOURCE_DIR}/ext
)
target_include_directories(${MAIN_EXECUTABLE_NAME} SYSTEM PRIVATE
${CMAKE_SOURCE_DIR}/ext
)

target_link_libraries(${MAIN_EXECUTABLE_NAME} PRIVATE ${MAIN_PROJECT_LIB_NAME})
target_link_libraries(${MAIN_EXECUTABLE_NAME} PRIVATE ${MAIN_LIBRARY_NAME})

###############################################################################

Expand All @@ -119,26 +120,14 @@ target_link_libraries(${MAIN_EXECUTABLE_NAME} PRIVATE ${MAIN_PROJECT_LIB_NAME})

###############################################################################

set(TEST_SOURCES_DIR ${CMAKE_SOURCE_DIR}/tests)
set(BOOST_UT_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/ext/include/boost")

add_executable(${TESTS_EXECUTABLE_NAME}
${TEST_SOURCES_DIR}/main.cpp
${TEST_SOURCES_DIR}/test_oop.cpp
${TEST_SOURCES_DIR}/test_simplu.cpp
)

target_link_libraries(${TESTS_EXECUTABLE_NAME} PRIVATE ${MAIN_PROJECT_NO_SAN_LIB_NAME})
target_include_directories(${TESTS_EXECUTABLE_NAME} SYSTEM PRIVATE ${BOOST_UT_INCLUDE_DIR})

set_compiler_flags(RUN_SANITIZERS FALSE TARGET_NAMES ${TESTS_EXECUTABLE_NAME})

add_test(NAME ${TESTS_EXECUTABLE_NAME} COMMAND ${TESTS_PROJECT_NAME})
if(BUILD_TESTING)
add_subdirectory(tests)
endif ()

###############################################################################

# copy binaries to "bin" folder; these are uploaded as artifacts on each release
# DESTINATION_DIR is set as "bin" in cmake/Options.cmake:6
# DESTINATION_DIR is set as "bin" in cmake/Options.cmake
install(TARGETS ${MAIN_EXECUTABLE_NAME} DESTINATION ${DESTINATION_DIR})
if(APPLE)
install(FILES launcher.command DESTINATION ${DESTINATION_DIR})
Expand Down
122 changes: 122 additions & 0 deletions cmake/RegisterTests.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
###############################################################################
# Framework agnostic registration of test executables with CTest.
# No test framework code here, keep identical on every branch.
#
# register_tests(<target>) one CTest test for the executable
# register_tests(<target> LIST_ARGS <arg> ...) one CTest test per test case
#
# Options (all optional):
# LIST_ARGS <arg> argument that prints the test cases, one per line
# LIST_NOISE <regex> removed from every line of the listing, a line left
# empty is not a test case
# SELECT_ARG <template>... argument that runs one case, <name> is the
# placeholder, several arguments stay separate
# NAME_ESCAPE <characters> characters replaced by "?" in a selection argument,
# for frameworks selecting by pattern instead of name
# TIMEOUT <seconds> per test timeout, default 60
# LIST_TIMEOUT <seconds> timeout for the listing run, default 60
# WORKING_DIRECTORY <dir> default CMAKE_SOURCE_DIR
# TEST_LIST <variable> set in the calling scope to the list of test names
# PROPERTIES <name value> extra CTest test properties
###############################################################################

# CMAKE_CURRENT_LIST_DIR inside a function body is the file of the caller
set(REGISTER_TESTS_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}")

function(register_tests TARGET)
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "LIST_ARGS;LIST_NOISE;NAME_ESCAPE;TIMEOUT;LIST_TIMEOUT;WORKING_DIRECTORY;TEST_LIST" "SELECT_ARG;PROPERTIES")

if(NOT TARGET ${TARGET})
message(FATAL_ERROR "register_tests: ${TARGET} is not a target")
endif()

if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "register_tests: unknown arguments: ${ARG_UNPARSED_ARGUMENTS}")
endif()

if(NOT DEFINED ARG_WORKING_DIRECTORY)
set(ARG_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif()

if(NOT DEFINED ARG_TIMEOUT)
set(ARG_TIMEOUT 60)
endif()

if(NOT DEFINED ARG_LIST_TIMEOUT)
set(ARG_LIST_TIMEOUT 60)
endif()

if(NOT ARG_LIST_ARGS)
# plain assert() tests: nothing to enumerate
add_test(NAME ${TARGET} COMMAND ${TARGET})

set_tests_properties(${TARGET} PROPERTIES
WORKING_DIRECTORY "${ARG_WORKING_DIRECTORY}"
TIMEOUT "${ARG_TIMEOUT}"
${ARG_PROPERTIES}
)

if(DEFINED ARG_TEST_LIST)
set(${ARG_TEST_LIST} ${TARGET} PARENT_SCOPE)
endif()

return()
endif()

# the cases are only known by running the executable, so discovery runs inside
# ctest, never during the build; same TEST_INCLUDE_FILES mechanism as
# gtest_discover_tests(DISCOVERY_MODE PRE_TEST)
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)

set(file_base "${CMAKE_CURRENT_BINARY_DIR}/ctest_${TARGET}")
set(include_file "${file_base}_include.cmake")

if(GENERATOR_IS_MULTI_CONFIG)
set(tests_file "${file_base}_tests-$<CONFIG>.cmake")
else()
set(tests_file "${file_base}_tests.cmake")
endif()

# regenerated by cmake, it only includes the file written at test time
string(CONCAT include_content
"if(EXISTS \"$<TARGET_FILE:${TARGET}>\")" "\n"
" if(NOT EXISTS \"${tests_file}\" OR" "\n"
" NOT \"${tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\" OR\n"
" NOT \"${tests_file}\" IS_NEWER_THAN \"\${CMAKE_CURRENT_LIST_FILE}\")\n"
" include(\"${REGISTER_TESTS_MODULE_DIR}/RegisterTestsAddTests.cmake\")\n"
" register_tests_discover(" "\n"
" TEST_EXECUTABLE" " [==[" "$<TARGET_FILE:${TARGET}>" "]==]" "\n"
" TEST_WORKING_DIR" " [==[" "${ARG_WORKING_DIRECTORY}" "]==]" "\n"
" LIST_ARGS" " [==[" "${ARG_LIST_ARGS}" "]==]" "\n"
" LIST_NOISE" " [==[" "${ARG_LIST_NOISE}" "]==]" "\n"
" SELECT_ARG" " [==[" "${ARG_SELECT_ARG}" "]==]" "\n"
" NAME_ESCAPE" " [==[" "${ARG_NAME_ESCAPE}" "]==]" "\n"
" LIST_TIMEOUT" " [==[" "${ARG_LIST_TIMEOUT}" "]==]" "\n"
" TIMEOUT" " [==[" "${ARG_TIMEOUT}" "]==]" "\n"
" TEST_LIST" " [==[" "${ARG_TEST_LIST}" "]==]" "\n"
" TEST_PROPERTIES" " [==[" "${ARG_PROPERTIES}" "]==]" "\n"
" CTEST_FILE" " [==[" "${tests_file}" "]==]" "\n"
" )" "\n"
" endif()" "\n"
" include(\"${tests_file}\")" "\n"
"else()" "\n"
" add_test(${TARGET}_NOT_BUILT ${TARGET}_NOT_BUILT)" "\n"
"endif()" "\n"
)

if(GENERATOR_IS_MULTI_CONFIG)
foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
file(GENERATE OUTPUT "${file_base}_include-${config}.cmake" CONTENT "${include_content}" CONDITION $<CONFIG:${config}>)
endforeach()
file(WRITE "${include_file}" "include(\"${file_base}_include-\${CTEST_CONFIGURATION_TYPE}.cmake\")")
else()
file(GENERATE OUTPUT "${file_base}_include.cmake" CONTENT "${include_content}")
file(WRITE "${include_file}" "include(\"${file_base}_include.cmake\")")
endif()

set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES "${include_file}")

if(DEFINED ARG_TEST_LIST)
message(WARNING "register_tests: TEST_LIST is only set by ctest, after the cases were discovered")
endif()
endfunction()
Loading
Loading