diff --git a/CMakeLists.txt b/CMakeLists.txt index 1103053c1..0e1dbac7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ include(cmake/OptionVariables.cmake) # target that we can modify (can't modify ALIAS targets) # target name should not be the same as ${PROJECT_NAME}, causes add_subdirectory issues -set(target_name "patomic_patomic") +set(target_name "patomic-patomic") add_library(${target_name} ${build_type}) # alias to cause error at configuration time instead of link time if target is missing diff --git a/test/bt/CMakeLists.txt b/test/bt/CMakeLists.txt index 7469ab097..66794e7e0 100644 --- a/test/bt/CMakeLists.txt +++ b/test/bt/CMakeLists.txt @@ -1,12 +1,11 @@ -# create_test requires windows_deps_path include(../cmake/CreateTest.cmake) include(../cmake/WindowsDependenciesPath.cmake) # ---- Setup Tests ---- -add_custom_target(patomic_bt) -add_dependencies(patomic_test patomic_bt) +add_custom_target(patomic-test-bt) +add_dependencies(patomic-test patomic-test-bt) create_test(BT example_add SOURCE example_add.cpp) create_test(BT example_sub SOURCE example_sub.cpp) @@ -14,4 +13,4 @@ create_test(BT example_sub SOURCE example_sub.cpp) # ---- Windows Path Issues ---- -create_test_win_deps_path_file(BT) +create_test_win_deps_paths_file(BT) diff --git a/test/cmake/CreateTest.cmake b/test/cmake/CreateTest.cmake index 97110406b..71af34c5a 100644 --- a/test/cmake/CreateTest.cmake +++ b/test/cmake/CreateTest.cmake @@ -1,11 +1,21 @@ +include(WindowsDependenciesPath.cmake) + + # ---- Create Test ---- # Creates a target to build a test executable and registers it with CTest. -# Expects a target named patomic_${kind} to exist. -# E.g. if you call it as create_test(BT ...) then patomic_bt must exist. -# The target is named patomic_${kind}_${name} but the name of the executable -# produced is just ${name}. -# When the executable is installed, it's installed as patomic/${kind}/${name}. +# Expects a target named patomic-test-${kind} to exist. +# E.g. if you call it as create_test(BT ...) then patomic-test-bt must exist. +# +# Naming: +# - created target -> patomic-test-${kind}-${name} (e.g. patomic-test-bt-SomeExample) +# - executable name -> ${name} (e.g. SomeExample on Unix or SomeExample.exe on Windows) +# - install directory -> ${CMAKE_INSTALL_TESTDIR}/${kind} (e.g. share/test/bt) +# +# Hierarchy: +# - patomic-test -> base custom target & component (build/install) for all tests +# - patomic-test-${kind} -> custom target & component (build install) for all tests of a specific kind +# - patomic-test-${kind}-${name} -> executable target for a single test # # create_test( # BT|UT @@ -17,8 +27,8 @@ function(create_test) # setup what arguments we expect - set(all_kinds "BT;UT") # list we can iterate over - set(all_kinds_option "BT|UT") # string to use in debug message + set(all_kinds "BT;UT") # list of all kinds we can iterate over + set(all_kinds_opt_msg "BT|UT") # string to use in debug message cmake_parse_arguments( "ARG" @@ -32,10 +42,10 @@ function(create_test) # check what test kinds are passed set(kind "") # -> "bt" - set(name "") # -> "${ARG_BT}" - # we turn kind into a list so that we can check its length (should be 1) - # and name is just the last name we process - foreach(ak IN LISTS all_kinds) + set(name "") # -> value of "${ARG_BT}" + # we turn 'kind' into a list so that we can check its length (which should be 1) + # 'name' is just the last name we process (there should only be 1 name) + foreach(ak in LISTS all_kinds) # if(ARG_BT) if (ARG_${ak}) string(TOLOWER ${ak} ak_lower) @@ -49,63 +59,91 @@ function(create_test) # validate arguments + # setup set(args_valid TRUE) - set(func_name "create_test") - set(LENGTH kind kinds_count) + set(func_name "create_test") # CMAKE_CURRENT_FUNCTION is CMake 3.17+ + set(LENGTH kind kinds_count) # expected value is 1 + # go through all possible issues with arguments if(kinds_count EQUAL 0) - message(WARNING "${all_kinds_option} option needs to be specified when invoking '${func_name}'") + message(WARNING "'${all_kinds_opt_msg}' option must be specified invoking '${func_name}'") set(args_valid FALSE) elseif(kinds_count GREATER 1) - message(WARNING "Only a single ${all_kinds_option} option may be specified when invoking '${func_name}'") + message(WARNING "Only a single '${all_kinds_opt_msg}' option may be specified when invoking '${func_name}'") set(args_valid FALSE) elseif(TARGET ${name}) - message(WARNING "Test name must not be an existing target when invoking '${func_name}', was passed: ${name}") + message(WARNING "Test name must not be an existing target when invoking '${func_name}', was passed: '${name}'") set(args_valid FALSE) elseif("${name}" STREQUAL "") message(WARNING "Test name must not be empty when invoking '${func_name}'") + set(args_valid FALSE) endif() + # check there are no leftover arguments if(DEFINED ARG_UNPARSED_ARGUMENTS) message(WARNING "The following arguments were not recognised when invoking '${func_name}': ${ARG_UNPARSED_ARGUMENTS}") set(args_valid FALSE) endif() - if (NOT args_valid) + # abort if validation failed + if(NOT args_valid) message(FATAL_ERROR "Aborting '${func_name}' due to invalid arguments") endif() - # setup target + # create test target - set(parent_target patomic_${kind}) - set(target ${parent_target}_${name}) - set(target_deps patomic::patomic GTest::gtest_main ${ARG_LINK}) - set(output_name ${name}) + # setup + set(base_target patomic-test) # patomic-test + set(parent_target ${base_target}-${kind}) # patomic-test-bt + set(target ${parent_target}-${name}) # patomic-test-bt-SomeExample - if (NOT "${target}" MATCHES ${PATOMIC_CREATE_TEST_TARGETS_MATCHING}) - message(DEBUG "Skipping creation of test target ${target} (matches ${PATOMIC_CREATE_TEST_TARGETS_MATCHING})") - return() + # check target name matches pattern + if(NOT "${target}" MATCHES "${PATOMIC_CREATE_TEST_TARGETS_MATCHING}") + message(VERBOSE "Skipping creation of test target '${target}' (does not match ${PATOMIC_CREATE_TEST_TARGETS_MATCHING})") endif() + # create target with sources add_executable( ${target} - ${ARG_INCLUDE} ${ARG_SOURCE} ) + # add include directories + target_include_directories( + ${target} PRIVATE + ${ARG_INCLUDE} + ) + + # link dependencies (all tests use GTest framework) + # save list for Windows PATH issues later + set(target_deps patomic::patomic GTest::gtest GTest::gmock ${ARG_LINK}) target_link_libraries( - ${target} - PRIVATE + ${target} PRIVATE ${target_deps} ) - target_compile_features(${target} PRIVATE cxx_std_14) + # require C++14 as minimum + target_compile_features( + ${target} PRIVATE + cxx_std_14 + ) + + # set macro to know which test kind code is part of + string(TOUPPER "${kind}" kind_upper) + target_compile_definitions( + ${target} PRIVATE + "PATOMIC_${kind_upper}" + ) - set_target_properties(${target} PROPERTIES OUTPUT_NAME ${output_name}) + # set binary name instead of using default + set_target_properties( + ${target} PROPERTIES + OUTPUT_NAME "${name}" + ) - # register tests with CTest + # register test with GTest/CTest and parent target # must be run in same directory scope as target gtest_add_tests( @@ -113,84 +151,88 @@ function(create_test) TEST_LIST added_tests ) + add_dependencies(${parent_target} ${target}) + - # deal with Windows runtime linker issues for tests (with and without CTest) + # deal with Windows runtime linker issues - if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") # check we actually care about Windows PATH stuff - if (NOT PATOMIC_WINDOWS_SET_CTEST_PATH_ENV AND NOT PATOMIC_WINDOWS_CREATE_PATH_ENV_FILE) + if(NOT PATOMIC_WINDOWS_SET_CTEST_PATH_ENV AND + NOT PATOMIC_WINDOWS_CREATE_PATH_ENV_FILE) return() endif() # get paths to all shared library dependencies (DLLs) - windows_deps_path( - deps_path + windows_deps_paths( + deps_paths ${target_deps} ) - # set environment variable for the each test so that CTest works automatically - if (deps_path AND PATOMIC_WINDOWS_SET_CTEST_PATH_ENV) + # set environment variable for each test so that CTest works + if(deps_paths AND PATOMIC_WINDOWS_SET_CTEST_PATH_ENV) foreach(test IN LISTS added_tests) set_property( TEST "${test}" - PROPERTY ENVIRONMENT "PATH=${deps_path}" + PROPERTY ENVIRONMENT "PATH=${deps_paths}" ) endforeach() endif() # make dependencies accessible from parent target - if (PATOMIC_WINDOWS_CREATE_PATH_ENV_FILE) + # so that we can create single file for all tests in kind + if(PATOMIC_WINDOWS_CREATE_PATH_ENV_FILE) set_property( TARGET ${parent_target} - APPEND PROPERTY WIN_DEP_TARGETS ${target_deps} + APPEND PROPERTY WIN_DEPS_TARGETS "${target_deps}" ) endif() + endif() # setup install of target if(NOT CMAKE_SKIP_INSTALL_RULES) - # install as part of patomic_${kind} component + + # install as part of patomic-test-${kind} component install( TARGETS ${target} RUNTIME # - COMPONENT "${parent_target}" - DESTINATION "${CMAKE_INSTALL_TESTDIR}/patomic/${kind}" + COMPONENT ${parent_target} + DESTINATION "${CMAKE_INSTALL_TESTDIR}/patomic/${kind}/" EXCLUDE_FROM_ALL ) - # install as part of patomic_test component + # install as part of patomic-test component install( TARGETS ${target} RUNTIME # - COMPONENT patomic_test - DESTINATION "${CMAKE_INSTALL_TESTDIR}/patomic/${kind}" + COMPONENT ${base_target} + DESTINATION "${CMAKE_INSTALL_TESTDIR}/patomic/${kind}/" EXCLUDE_FROM_ALL ) - endif() - - # attach to parent target - - add_dependencies(${parent_target} ${target}) + endif() endfunction() # ---- Create Test Dependency File ---- -# Creates a file containing the output of windows_deps_path for all tests of +# Creates a file containing the output of windows_deps_paths for all tests of # the given kind registered so far. -# Expects a target named patomic_${kind} to exist -# E.g. if you call it as create_test_win_deps_path_file(BT) then patomic_bt must +# The file path will be "${CMAKE_CURRENT_BINARY_DIR}/windows_dependencies_path.txt". +# Expects a target named patomic-test-${kind} to exist +# E.g. if you call it as create_test_win_deps_paths_file(BT) then patomic-bt must # exist. +# This function has no effect when not running on Windows. # -# create_test_win_deps_path_file( +# create_test_win_deps_paths_file( # BT|UT # ) -function(create_test_win_deps_path_file ARG_KIND) +function(create_test_win_deps_paths_file ARG_KIND) # check we actually want to generate file @@ -201,10 +243,10 @@ function(create_test_win_deps_path_file ARG_KIND) # check KIND is valid - set(all_kinds_option "BT|UT") - set(func_name "create_test_win_deps_path_file") + set(all_kinds_opt_msg "BT|UT") + set(func_name "create_test_win_deps_paths_file") - if (NOT ARG_KIND MATCHES "^(${all_kinds_option})$") + if(NOT ARG_KIND MATCHES "^(${all_kinds_option})$") message(WARNING "${all_kinds_option} option needs to be specified when invoking '${func_name}'") message(FATAL_ERROR "Aborting '${func_name}' due to invalid arguments") endif() @@ -214,19 +256,19 @@ function(create_test_win_deps_path_file ARG_KIND) # create and install file with dependencies path - if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") # get dependencies set by create_test from target - get_target_property(dep_targets patomic_${kind} WIN_DEP_TARGETS) + get_target_property(dep_targets patomic-test-${kind} WIN_DEP_TARGETS) if("${dep_targets}" STREQUAL "dep_targets-NOTFOUND") - message(DEBUG "Skipping creation of Windows dependencies PATH file for ${ARG_KIND}; no relevant test targets created") + message(VERBOSE "Skipping creation of Windows dependencies PATH file for ${ARG_KIND}; no relevant test targets created") return() endif() list(REMOVE_DUPLICATES dep_targets) # get paths to all shared library dependencies (DLLs) - windows_deps_path( - deps_path + windows_deps_paths( + deps_paths ${dep_targets} ) @@ -234,27 +276,30 @@ function(create_test_win_deps_path_file ARG_KIND) set(file_path "${CMAKE_CURRENT_BINARY_DIR}/windows_dependencies_path.txt") file(GENERATE OUTPUT ${file_path} - CONTENT "${deps_path}" + CONTENT "${deps_paths}" ) # copy file to install location if(NOT CMAKE_SKIP_INSTALL_RULES) - # install as part of patomic_${kind} component + + # install as part of patomic-test-${kind} component install( FILES ${file_path} - COMPONENT patomic_${kind} + COMPONENT patomic-test-${kind} DESTINATION "${CMAKE_INSTALL_TESTDIR}/patomic/${kind}" EXCLUDE_FROM_ALL ) - # install as part of patomic_test component + # install as part of patomic-test component install( FILES ${file_path} - COMPONENT patomic_test + COMPONENT patomic-test DESTINATION "${CMAKE_INSTALL_TESTDIR}/patomic/${kind}" EXCLUDE_FROM_ALL ) + endif() + endif() endfunction() diff --git a/test/ut/CMakeLists.txt b/test/ut/CMakeLists.txt index 20b7cd490..b72c0b29b 100644 --- a/test/ut/CMakeLists.txt +++ b/test/ut/CMakeLists.txt @@ -1,12 +1,11 @@ -# create_test requires windows_deps_path include(../cmake/CreateTest.cmake) include(../cmake/WindowsDependenciesPath.cmake) # ---- Setup Tests ---- -add_custom_target(patomic_ut) -add_dependencies(patomic_test patomic_ut) +add_custom_target(patomic-test-ut) +add_dependencies(patomic-test patomic-test-ut) create_test(UT example_add SOURCE example_add.cpp) create_test(UT example_sub SOURCE example_sub.cpp) @@ -14,4 +13,4 @@ create_test(UT example_sub SOURCE example_sub.cpp) # ---- Windows Path Issues ---- -create_test_win_deps_path_file(UT) +create_test_win_deps_paths_file(UT)