diff --git a/cmake/functions/cpp_modules.cmake b/cmake/functions/cpp_modules.cmake deleted file mode 100644 index d348100..0000000 --- a/cmake/functions/cpp_modules.cmake +++ /dev/null @@ -1,155 +0,0 @@ -# Setting hint paths and configuration hints is a delicate process -# if we want to ensure transitive dependencies work. Many hints -# are stored in environment variables so that child processes -# can find or build transitive dependencies with the proper -# configuration values we want. - -# We need some functions to process semver version requirements, as -# CMake does not natively support semver requirements and they are -# important to ensure the correct dependency versions are found. -# To make sure this is not computationally expensive, these functions -# avoid relying on regex and do attempt to validate the input. -# The calling functions are also designed to avoid checking the most -# expensive requirements unless it really has to. -include(cmake/functions/semver.cmake) - -####################################################### -### Configuration descriptor ### -####################################################### -# Create a configuration descriptor with the core config options for this library. -# This is the default core configuration, unless these options are overridden. -# It ensures all dependencies were compiled with compatible with the current toolchain. -function(generate_config_descriptor) - # Build type - string(TOLOWER ${CMAKE_BUILD_TYPE} LC_CMAKE_BUILD_TYPE) - if (NOT BUILD_SHARED_LIBS) - set(LC_BUILD_SHARED_LIBS static) - else () - set(LC_BUILD_SHARED_LIBS dynamic) - endif () - # Compiler and compiler version - string(TOLOWER ${CMAKE_CXX_COMPILER_ID} LC_CMAKE_CXX_COMPILER_ID) - string(TOLOWER ${CMAKE_CXX_COMPILER_VERSION} LC_CMAKE_CXX_COMPILER_VERSION) - # Processor - string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} LC_CMAKE_SYSTEM_PROCESSOR) - # OS and OS version - string(TOLOWER ${CMAKE_SYSTEM_NAME} LC_CMAKE_SYSTEM_NAME) - string(TOLOWER ${CMAKE_SYSTEM_VERSION} LC_CMAKE_SYSTEM_VERSION) - # Concatenate strings - set(CONFIG_CORE - "${LC_CMAKE_BUILD_TYPE}-${LC_BUILD_SHARED_LIBS}-${LC_CMAKE_CXX_COMPILER_ID}-${LC_CMAKE_CXX_COMPILER_VERSION}-${LC_CMAKE_SYSTEM_PROCESSOR}-${LC_CMAKE_SYSTEM_NAME}-${LC_CMAKE_SYSTEM_VERSION}" - PARENT_SCOPE) -endfunction() -generate_config_descriptor() -message("- Find packages for ${CONFIG_CORE}") - -# This function sets a path hint for the package in case it already exists locally in a cpp_modules -# directory. If no such directory exists, the process continues as usual with find_package so the -# process still is non-intrusive apart from this convenience system inspection. -# This logic is somewhat redundant with the "paths" toolchain, but it solves two problems: -# - The "paths" toolchain is somewhat intrusive because the user will ultimately need cppm -# to generate this toolchain correctly. -# - This is very little intrusive as all of this will be ignored if the cpp_modules path does not exist. -# - This is also very little intrusive as it ensures package consumers don't need cppm to find dependencies. -# - Using a toolchain to set hints is optional and might be considered is bad workaround by some: -# - Setting hint paths does not really constitute a new *toolchain* (compiler+link+...) at all. -# - The "paths" toolchain creates difficulties for the user when a real toolchain is required for cross-compiling. -# - This difficulty can be solved with "second-order" toolchains on a mock toolchain, which is quite a workaround. -# All the logic in these functions avoid compiling any semver string we don't really need. Whenever possible -# we check for an existing directory with the lock version. We need compare the parse and semver strings only if: -# - (i) no hint has been set by the user -# - (ii) the original lock directory does not exist -# - (iii) a number of other reasonable candidates exist for some rare reason -# Although option (iii) includes the cost of splitting semver strings, this is much cheaper than -# redundantly downloading the library again or throwing an error for a false positive. -function(set_local_module_hints PACKAGE_NAME LOCK_VERSION REQUIREMENTS) - # Check if user's hasn't already set his own hint - if (NOT ENV{${PACKAGE_NAME}_ROOT} AND NOT ${PACKAGE_NAME}_ROOT) - # Look for local cpp_modules path with this package - string(TOLOWER ${PACKAGE_NAME} LC_PACKAGE_NAME) - set(${PACKAGE_NAME}_DIR_HINT ${CMAKE_SOURCE_DIR}/cpp_modules/${LC_PACKAGE_NAME}) - if (EXISTS ${${PACKAGE_NAME}_DIR_HINT} AND IS_DIRECTORY ${${PACKAGE_NAME}_DIR_HINT}) - # Base directory with package exists. Look for a compatible version now. - # Try a directory with the lock version first, in order to avoid inspecting the system - set(${PACKAGE_NAME}_PREFIX_HINT ${${PACKAGE_NAME}_DIR_HINT}/${LOCK_VERSION}) - # If the locked version is not available in cpp_modules - if (NOT (EXISTS ${${PACKAGE_NAME}_PREFIX_HINT} AND IS_DIRECTORY ${${PACKAGE_NAME}_PREFIX_HINT})) - # Go through other subdirectories looking for some compatible version - file(GLOB VERSION_SUBDIRS ${${PACKAGE_NAME}_DIR_HINT}/*) - foreach (VERSION_SUBDIR ${VERSION_SUBDIRS}) - # Get semver version this directory represents - get_filename_component(VERSION_SUBDIR_VERSION ${VERSION_SUBDIR} NAME) - if (VERSION_SUBDIR_VERSION VERSION_GREATER_EQUAL LOCK_VERSION) - # Check if version is compatible with requirements - semver_requirements_compatible(${VERSION_SUBDIR_VERSION} ${REQUIREMENTS} match_requirements) - if (match_requirements) - # Store this compatible version and the prefix hint - if (NOT MOST_COMPATIBLE_VERSION) - set(MOST_COMPATIBLE_VERSION ${VERSION_SUBDIR_VERSION}) - set(${PACKAGE_NAME}_PREFIX_HINT ${VERSION_SUBDIR}) - else () - # If this is not the first compatible version we find - # Check if this is a more recent candidate than what we had before - semver_greater(${VERSION_SUBDIR_VERSION} ${MOST_COMPATIBLE_VERSION} gt) - if (gt) - set(MOST_COMPATIBLE_VERSION ${VERSION_SUBDIR_VERSION}) - set(${PACKAGE_NAME}_PREFIX_HINT ${VERSION_SUBDIR}) - else () - # If this is not greater than the previous version we found, - # it might still be the edge-case where the previous version we found - # didn't match the requirements and we just had it here because - # it was compatible with the lock version. In that case, we still favour - # this version - semver_requirements_compatible(${MOST_COMPATIBLE_VERSION} ${REQUIREMENTS} match_requirements) - if (NOT match_requirements) - set(MOST_COMPATIBLE_VERSION ${VERSION_SUBDIR_VERSION}) - set(${PACKAGE_NAME}_PREFIX_HINT ${VERSION_SUBDIR}) - endif () - endif () - endif () - else () - # We still store the hint if this does not match the requirements but - # it's semver compatible with the lock version - semver_compatible(${VERSION_SUBDIR_VERSION} ${LOCK_VERSION} compatible_with_lock) - if (compatible_with_lock) - set(MOST_COMPATIBLE_VERSION ${VERSION_SUBDIR_VERSION}) - set(${PACKAGE_NAME}_PREFIX_HINT ${VERSION_SUBDIR}) - endif () - endif () - endif () - endforeach () - endif () - endif () - - # If we found no prefix with a reasonable hint - if (NOT ${PACKAGE_NAME}_PREFIX_HINT) - # Reset this to the lock version so that FetchContents puts the contents here - # if we really need to use it. However, the user might have the package installed - # globally before that. - set(${PACKAGE_NAME}_PREFIX_HINT ${${PACKAGE_NAME}_DIR_HINT}/${LOCK_VERSION}) - endif () - - # Return expected hint paths - set(${PACKAGE_NAME}_PREFIX_HINT ${${PACKAGE_NAME}_PREFIX_HINT} PARENT_SCOPE) - set(${PACKAGE_NAME}_SOURCE_HINT ${${PACKAGE_NAME}_PREFIX_HINT}/source PARENT_SCOPE) - set(${PACKAGE_NAME}_BINARY_HINT ${${PACKAGE_NAME}_PREFIX_HINT}/build/${CONFIG_CORE} PARENT_SCOPE) - set(${PACKAGE_NAME}_INSTALL_HINT ${${PACKAGE_NAME}_PREFIX_HINT}/install/${CONFIG_CORE} PARENT_SCOPE) - - # Set the root directory, where CMake might also look for the package - set(${PACKAGE_NAME}_ROOT ${${PACKAGE_NAME}_PREFIX_HINT}/install/${CONFIG_CORE} PARENT_SCOPE) - # Also set this as an ENV variable for the build script of transitive dependencies - set(ENV{${PACKAGE_NAME}_ROOT} ${${PACKAGE_NAME}_PREFIX_HINT}/install/${CONFIG_CORE}) - - # Do the same, with capitalized package name - string(SUBSTRING ${PACKAGE_NAME} 0 1 PACKAGE_NAME_FRONT) - string(TOUPPER ${PACKAGE_NAME_FRONT} PACKAGE_NAME_FRONT) - string(SUBSTRING ${PACKAGE_NAME} 1 -1 PACKAGE_NAME_TAIL) - set(CAPITALIZED_PACKAGE_NAME "${PACKAGE_NAME_FRONT}${PACKAGE_NAME_TAIL}") - set(${CAPITALIZED_PACKAGE_NAME}_PREFIX_HINT ${${PACKAGE_NAME}_PREFIX_HINT} PARENT_SCOPE) - set(${CAPITALIZED_PACKAGE_NAME}_SOURCE_HINT ${${PACKAGE_NAME}_PREFIX_HINT}/source PARENT_SCOPE) - set(${CAPITALIZED_PACKAGE_NAME}_BINARY_HINT ${${PACKAGE_NAME}_PREFIX_HINT}/build/${CONFIG_CORE} PARENT_SCOPE) - set(${CAPITALIZED_PACKAGE_NAME}_INSTALL_HINT ${${PACKAGE_NAME}_PREFIX_HINT}/install/${CONFIG_CORE} PARENT_SCOPE) - set(${CAPITALIZED_PACKAGE_NAME}_ROOT ${${PACKAGE_NAME}_PREFIX_HINT}/install/${CONFIG_CORE} PARENT_SCOPE) - set(ENV{${CAPITALIZED_PACKAGE_NAME}_ROOT} ${${PACKAGE_NAME}_PREFIX_HINT}/install/${CONFIG_CORE}) - endif () -endfunction() \ No newline at end of file diff --git a/cmake/small/dependencies.cmake b/cmake/small/dependencies.cmake deleted file mode 100644 index e3b93ef..0000000 --- a/cmake/small/dependencies.cmake +++ /dev/null @@ -1,97 +0,0 @@ -####################################################### -### cpp_modules hints ### -####################################################### -# If user has a cpp_modules directory in their project but the user didn't -# set the hint paths properly (i.e.: no toolchain / no manager / no env variables), -# we need some helper functions to identify the default configuration and -# identify these extra hint paths. -include(cmake/functions/cpp_modules.cmake) - -####################################################### -### Catch2 ### -####################################################### -set(catch2_VERSION_LOCK 2.13.6) -set(catch2_VERSION_REQUIREMENT ^2.0.0) -set_local_module_hints(catch2 ${catch2_VERSION_LOCK} ${catch2_VERSION_REQUIREMENT}) - -# Look for lock version -if (NOT Catch2_FOUND) - semver_split(${catch2_VERSION_LOCK} catch2_VERSION_LOCK) - find_package(Catch2 ${catch2_VERSION_LOCK_CORE} QUIET CONFIG) -endif () - -# Look for any version that matches our requirements -if (NOT Catch2_FOUND) - find_package(Catch2 QUIET CONFIG) - if (Catch2_FOUND AND catch2_VERSION AND NOT DEFINED ENV{catch2_ROOT}) - semver_requirements_compatible(${catch2_VERSION} ${catch2_VERSION_REQUIREMENT} ok) - if (NOT ok) - set(Catch2_FOUND FALSE) - endif () - endif () -endif () - -# Fetch catch2 if we couldn't find a valid version -if (NOT Catch2_FOUND) - # Fallback to FetchContent and then find_package again - message("Downloading catch2...") - FetchContent_Declare(catch2 - URL https://github.com/catchorg/Catch2/archive/refs/tags/v2.13.6.zip - SOURCE_DIR ${catch2_SOURCE_HINT} - BINARY_DIR ${catch2_BINARY_HINT} - ) - - # Check if already populated - FetchContent_GetProperties(catch2) - - if (NOT catch2_POPULATED) - # Download files - FetchContent_Populate(catch2) - - # Run configure step - execute_process(COMMAND "${CMAKE_COMMAND}" - # CMake options - -G "${CMAKE_GENERATOR}" - -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} - # CMake install prefix - -DCMAKE_INSTALL_PREFIX=${catch2_INSTALL_HINT} - # Allow looking for _ROOT - -DCMAKE_POLICY_DEFAULT_CMP0074=NEW - # Package options - -DCATCH_USE_VALGRIND=OFF # "Perform SelfTests with Valgrind" - -DCATCH_BUILD_TESTING=OFF # "Build SelfTest project" - -DCATCH_BUILD_EXAMPLES=OFF # "Build documentation examples" - -DCATCH_BUILD_EXTRA_TESTS=OFF # "Build extra tests" - -DCATCH_BUILD_STATIC_LIBRARY=OFF # "Builds static library from the main implementation. EXPERIMENTAL" - -DCATCH_ENABLE_COVERAGE=OFF # "Generate coverage for codecov.io" - -DCATCH_ENABLE_WERROR=OFF # "Enable all warnings as errors" - -DCATCH_INSTALL_DOCS=OFF # "Install documentation alongside library" - -DCATCH_INSTALL_HELPERS=ON # "Install contrib alongside library" - # Source dir - ${catch2_SOURCE_DIR} - # Build dir - WORKING_DIRECTORY "${catch2_BINARY_DIR}" - ) - - # Run build step - execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${catch2_BINARY_DIR}" - ) - - # Run install step - execute_process(COMMAND "${CMAKE_COMMAND}" --install . - WORKING_DIRECTORY "${catch2_BINARY_DIR}" - ) - # Find package again - set(ENV{catch2_ROOT} ${catch2_INSTALL_HINT}) - find_package(Catch2 CONFIG REQUIRED) - endif () -endif () -version_requirement_message(catch2 - VERSION_FOUND ${catch2_VERSION} - VERSION_LOCK ${catch2_VERSION_LOCK} - VERSION_REQUIREMENTS ${catch2_VERSION_REQUIREMENT} - PREFIX_HINT ${catch2_PREFIX_HINT}) - diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index de7f30a..2f91b64 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -6,16 +6,38 @@ # ####################################################### -### Unit Tests ### +### Dependencies ### ####################################################### -# Include catch helper CMake scripts -include(${Catch2_DIR}/Catch.cmake) +find_package(Catch2 2.13.8 CONFIG) +if (Catch2_FOUND) + include(${Catch2_DIR}/Catch.cmake) +else () + FetchContent_Declare(Catch2 URL https://github.com/catchorg/Catch2/archive/refs/tags/v2.13.8.zip) + FetchContent_GetProperties(Catch2) + if (NOT Catch2_POPULATED) + FetchContent_Populate(Catch2) + set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + set(CATCH_USE_VALGRIND OFF) # "Perform SelfTests with Valgrind" + set(CATCH_BUILD_EXAMPLES OFF) # "Build documentation examples" + set(CATCH_BUILD_EXTRA_TESTS OFF) # "Build extra tests" + set(CATCH_BUILD_STATIC_LIBRARY OFF) # "Builds static library from the main implementation. EXPERIMENTAL" + set(CATCH_ENABLE_COVERAGE OFF) # "Generate coverage for codecov.io" + set(CATCH_ENABLE_WERROR OFF) # "Enable all warnings as errors" + set(CATCH_INSTALL_DOCS OFF) # "Install documentation alongside library" + set(CATCH_INSTALL_HELPERS ON) # "Install contrib alongside library" + add_subdirectory(${catch2_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/catch2) + include(${catch2_SOURCE_DIR}/contrib/Catch.cmake) + endif () +endif () # Create a common catch main for all tests add_library(catch_main catch_main.cpp) target_link_libraries(catch_main PUBLIC Catch2::Catch2) target_compile_features(catch_main PUBLIC cxx_std_17) +####################################################### +### Unit Tests ### +####################################################### # Macro to create test targets and register with ctest # First parameter: filename without extension # Other parameters: libraries to link in this test (if empty, it links libcppm)