diff --git a/CMakeLists.txt b/CMakeLists.txt index b325771..60c2031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,7 @@ set(CMAKE_MODULE_FILES cmake/modules/BasicConfig.cmake cmake/modules/ConfigHeader.cmake cmake/modules/LibraryTarget.cmake + cmake/modules/TestUtilities.cmake cmake/modules/TestTarget.cmake cmake/modules/AppTarget.cmake cmake/modules/WindowsResources.cmake diff --git a/cmake/modules/TestTarget.cmake b/cmake/modules/TestTarget.cmake index cebaa6b..8cced2c 100644 --- a/cmake/modules/TestTarget.cmake +++ b/cmake/modules/TestTarget.cmake @@ -7,7 +7,7 @@ if (TEST_CONFIG_DONE) message(FATAL_ERROR "Can not include TestTarget module when tests are already configured.") endif () -option(EXCLUDE_TESTS_FROM_ALL "specifies whether to exclude tests from the \"all\" target (enabled by default)" ON) +include(TestUtilities) # find and link against cppunit if required (used by all my projects, so it is required by default) if (NOT META_NO_CPP_UNIT) @@ -82,21 +82,6 @@ endif () # always link test applications against c++utilities list(APPEND TEST_LIBRARIES ${CPP_UTILITIES_LIB}) -# add target for test executable, but exclude it from the "all" target when EXCLUDE_TESTS_FROM_ALL is set -if (EXCLUDE_TESTS_FROM_ALL) - set(TESTS_EXCLUSION EXCLUDE_FROM_ALL) -else () - unset(TESTS_EXCLUSION) -endif () -add_executable(${META_TARGET_NAME}_tests ${TESTS_EXCLUSION} ${TEST_HEADER_FILES} ${TEST_SRC_FILES}) - -# add top-level target to build all test targets conveniently, also when excluded from "all" target -if (NOT TARGET tests) - add_custom_target(tests DEPENDS ${META_TARGET_NAME}_tests) -else () - add_dependencies(tests ${META_TARGET_NAME}_tests) -endif () - # handle testing a library (which is default project type) if (META_PROJECT_IS_LIBRARY) # when testing a library, the test application always needs to link against it @@ -145,38 +130,30 @@ if (META_PROJECT_IS_APPLICATION AND LINK_TESTS_AGAINST_APP_TARGET) endif () # configure test target -target_link_libraries( - ${META_TARGET_NAME}_tests - PUBLIC ${META_ADDITIONAL_LINK_FLAGS} ${META_ADDITIONAL_LINK_FLAGS_TEST_TARGET} "${PUBLIC_LIBRARIES}" - PRIVATE "${TEST_LIBRARIES}" "${PRIVATE_LIBRARIES}") -target_include_directories( - ${META_TARGET_NAME}_tests - PUBLIC $ $ - ${PUBLIC_INCLUDE_DIRS} - PRIVATE ${TEST_INCLUDE_DIRS} "${PRIVATE_INCLUDE_DIRS}") -target_compile_definitions( - ${META_TARGET_NAME}_tests - PUBLIC "${META_PUBLIC_COMPILE_DEFINITIONS}" - PRIVATE "${META_PRIVATE_COMPILE_DEFINITIONS}") -target_compile_options( - ${META_TARGET_NAME}_tests - PUBLIC "${META_PUBLIC_COMPILE_OPTIONS}" - PRIVATE "${META_PRIVATE_COMPILE_OPTIONS}") -set_target_properties( - ${META_TARGET_NAME}_tests - PROPERTIES CXX_STANDARD "${META_CXX_STANDARD}" C_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden - LINK_SEARCH_START_STATIC ${STATIC_LINKAGE} LINK_SEARCH_END_STATIC ${STATIC_LINKAGE}) - -# make the test recognized by ctest -unset(RUN_TESTS_APPLICATION_ARG) +unset(TEST_TARGET_OPTIONS) +unset(RUN_TESTS_APPLICATION_ARGS) if (META_PROJECT_TYPE STREQUAL "application") - set(RUN_TESTS_APPLICATION_ARGS -a "$") + set(RUN_TESTS_APPLICATION_ARGS -a "$") endif () -if (NOT META_TEST_TARGET_IS_MANUAL) - add_test(NAME ${META_PROJECT_NAME}_run_tests - COMMAND ${META_TARGET_NAME}_tests -p "${CMAKE_CURRENT_SOURCE_DIR}/testfiles" -w - "${CMAKE_CURRENT_BINARY_DIR}/testworkingdir" ${RUN_TESTS_APPLICATION_ARGS}) +set(RUN_TESTS_ARGS -p "${CMAKE_CURRENT_SOURCE_DIR}/testfiles" -w "${CMAKE_CURRENT_BINARY_DIR}/testworkingdir" + ${RUN_TESTS_APPLICATION_ARGS}) +if (META_TEST_TARGET_IS_MANUAL) + list(APPEND TEST_TARGET_OPTIONS MANUAL) endif () +configure_test_target( + TARGET_NAME + "${META_TARGET_NAME}" + TEST_NAME + "tests" + HEADER_FILES + "${TEST_HEADER_FILES}" + SRC_FILES + "${TEST_SRC_FILES}" + LIBRARIES + "${TEST_LIBRARIES}" + RUN_ARGS + "${RUN_TESTS_ARGS}" + ${TEST_TARGET_OPTIONS}) # enable source code based coverage analysis using clang if (CLANG_SOURCE_BASED_COVERAGE_AVAILABLE) diff --git a/cmake/modules/TestUtilities.cmake b/cmake/modules/TestUtilities.cmake new file mode 100644 index 0000000..1862a77 --- /dev/null +++ b/cmake/modules/TestUtilities.cmake @@ -0,0 +1,67 @@ +cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR) + +# prevent multiple inclusion +if (DEFINED TESTING_UTILITIES_LOADED) + return() +endif () +set(TESTING_UTILITIES_LOADED YES) + +option(EXCLUDE_TESTS_FROM_ALL "specifies whether to exclude tests from the \"all\" target (enabled by default)" ON) + +function (configure_test_target) + # parse arguments + set(OPTIONAL_ARGS MANUAL) + set(ONE_VALUE_ARGS TARGET_NAME TEST_NAME) + set(MULTI_VALUE_ARGS HEADER_FILES SRC_FILES LIBRARIES RUN_ARGS) + cmake_parse_arguments(ARGS "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" "${MULTI_VALUE_ARGS}" ${ARGN}) + if (NOT ARGS_TARGET_NAME) + set(ARGS_TARGET_NAME "${META_TARGET_NAME}") + endif () + if (NOT ARGS_TEST_NAME) + message(FATAL_ERROR "No test name specified.") + endif () + set(TEST_TARGET_NAME "${ARGS_TARGET_NAME}_${ARGS_TEST_NAME}") + + # add target for test executable, but exclude it from the "all" target when EXCLUDE_TESTS_FROM_ALL is set + if (EXCLUDE_TESTS_FROM_ALL) + set(TESTS_EXCLUSION EXCLUDE_FROM_ALL) + else () + unset(TESTS_EXCLUSION) + endif () + add_executable("${TEST_TARGET_NAME}" ${TESTS_EXCLUSION} ${ARGS_HEADER_FILES} ${ARGS_SRC_FILES}) + + # add top-level target to build all test targets conveniently, also when excluded from "all" target + if (NOT TARGET tests) + add_custom_target(tests DEPENDS "${TEST_TARGET_NAME}") + else () + add_dependencies(tests "${TEST_TARGET_NAME}") + endif () + + # configure test target + target_link_libraries( + "${TEST_TARGET_NAME}" + PUBLIC ${META_ADDITIONAL_LINK_FLAGS} ${META_ADDITIONAL_LINK_FLAGS_TEST_TARGET} "${PUBLIC_LIBRARIES}" + PRIVATE "${ARGS_LIBRARIES}" "${PRIVATE_LIBRARIES}") + target_include_directories( + "${TEST_TARGET_NAME}" + PUBLIC $ $ + ${PUBLIC_INCLUDE_DIRS} + PRIVATE ${TEST_INCLUDE_DIRS} "${PRIVATE_INCLUDE_DIRS}") + target_compile_definitions( + "${TEST_TARGET_NAME}" + PUBLIC "${META_PUBLIC_COMPILE_DEFINITIONS}" + PRIVATE "${META_PRIVATE_COMPILE_DEFINITIONS}") + target_compile_options( + "${TEST_TARGET_NAME}" + PUBLIC "${META_PUBLIC_COMPILE_OPTIONS}" + PRIVATE "${META_PRIVATE_COMPILE_OPTIONS}") + set_target_properties( + "${TEST_TARGET_NAME}" + PROPERTIES CXX_STANDARD "${META_CXX_STANDARD}" C_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden + LINK_SEARCH_START_STATIC ${STATIC_LINKAGE} LINK_SEARCH_END_STATIC ${STATIC_LINKAGE}) + + # make the test recognized by ctest + if (NOT ARGS_MANUAL) + add_test(NAME "${ARGS_TARGET_NAME}_run_${ARGS_TEST_NAME}" COMMAND "${TEST_TARGET_NAME}" ${RUN_ARGS}) + endif () +endfunction ()