From e5b83bd995b711f80485b28b6202c0722fdda0c5 Mon Sep 17 00:00:00 2001 From: S David <2100425+s-daveb@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:53:57 -0400 Subject: [PATCH] Switch to the CPM package manager and add some macros for readability --- CMakeLists.txt | 118 +++++++++++++++++------------------- cmake/BuildProperties.cmake | 31 ++++++++++ cmake/CPM.cmake | 24 ++++++++ tests/CMakeLists.txt | 2 +- 4 files changed, 112 insertions(+), 63 deletions(-) create mode 100644 cmake/BuildProperties.cmake create mode 100644 cmake/CPM.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c7ea882..9273ac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,27 +1,18 @@ cmake_minimum_required(VERSION 3.26) -# Prevent in-source builds -if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR) - message(FATAL_ERROR "Source and build directories cannot be the same.") -endif() +# Additional paths to search for custom and third-party CMake modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") - cmake_policy(SET CMP0135 NEW) -endif() +include(BuildProperties) + +prevent_in_source_build() +disable_deprecated_features() # When this package is included as a subproject, there's no need to -# build and run the unit-tests. Setting -DENABLE_TESTS to false could -# speed up build time for pacakge maintainers -if (NOT DEFINED PROJECT_NAME) - option(ENABLE_TESTS "Build and run unit tests" ON) -else() - option(ENABLE_TESTS "Build and run unit tests" OFF) -endif() - -option(USE_SYSTEM_CATCH2 - "Do not download & compile catch2 library for unit tests" - ON -) +# build and run the unit-tests. +# Sets -DENABLE_TESTS to false by default if this is a third-party lib build +# This check must appear before project() +disable_tests_if_subproject() project( VERSION 0.1 @@ -29,6 +20,17 @@ project( # HOMEPAGE_URL DESCRIPTION "Description" ) +include(CPM) + +option(USE_SYSTEM_CATCH2 + "Do not download & compile catch2 library for unit tests" + ON +) +option(USE_CCACHE + [=[Use ccache compiler cache to speed up builds. +Enabled by default if ccache is found]=] +ON +) IF( NOT CMAKE_BUILD_TYPE ) SET( CMAKE_BUILD_TYPE Debug ) @@ -43,23 +45,20 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Search for the code caching compiler wrapper, ccache and enable it # if found. This will speed up repeated builds. -find_program(CCACHE_PATH ccache) -if(CCACHE_PATH) - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH}) - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH}) -endif(CCACHE_PATH) +if (USE_CCACHE) + message(CHECK_START "Detecting cacche") -if (USE_SYSTEM_CATCH2) - message(CHECK_START "Detecting System Catch2 ") - find_package(Catch2 3 QUIET) - - if(TARGET Catch2::Catch2) - message(CHECK_PASS "found target Catch2::Catch2") - else() - message(CHECK_FAIL "not found") - set(USE_SYSTEM_CATCH2 OFF) - message(STATUS "USE_SYSTEM_CATCH2=OFF") + find_program(CCACHE_PATH ccache) + if(DEFINED CCACHE_PATH) + message(CHECK_PASS("found")) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH}) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH}) endif() + + list(APPEND CMAKE_MESSAGE_INDENT " ") + message(STATUS "(set -DUSE_CCACHE=Off to disable)") + list(POP_BACK CMAKE_MESSAGE_INDENT) + endif() # enable compile_commands.json generation for clangd @@ -88,43 +87,39 @@ include(FetchContent) #) if (ENABLE_TESTS) - if (NOT USE_SYSTEM_CATCH2) - FetchContent_Declare( - Catch2 - URL https://github.com/catchorg/Catch2/archive/refs/tags/v3.4.0.zip - URL_HASH MD5=c426e77d4ee0055410bc930182959ae5 - ) - FetchContent_MakeAvailable(Catch2) - else() - include_directories(${CATCH2_INCLUDE_DIRS}) - link_directories(${CATCH2_LIBRARY_DIRS}) - endif() - FetchContent_Declare( - FakeIt - URL https://github.com/eranpeer/FakeIt/archive/refs/tags/2.4.0.zip - URL_HASH MD5=72e4ce7f1c0de97074d2d5b517753286 - FIND_PACKAGE_ARGS + CPMFindPackage(NAME Catch2 + GITHUB_REPOSITORY catchorg/Catch2 + VERSION 3.4.0 + OPTIONS + "CATCH_DEVELOPMENT_BUILD OFF" + "CATCH_BUILD_TESTING OFF" + ) + CPMFindPackage(NAME FakeIt + GITHUB_REPOSITORY eranpeer/FakeIt + GIT_TAG 2.4.0 + OPTIONS + "ENABLE_TESTING OFF" ) - FetchContent_MakeAvailable(FakeIt) if (TARGET Catch2) set_target_properties(Catch2 PROPERTIES CXX_STANDARD 20 ) - endif() - - if (TARGET Catch2WithMain) + elseif (TARGET Catch2WithMain) set_target_properties(Catch2WithMain PROPERTIES - CXX_STANDARD 20 + CXX_STANDARD 20 ) endif() - list(APPEND cmake_module_path ${Catch2_source_dir}/extras) + if (Catch2_ADDED STREQUAL "YES") + list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras) + endif() endif() # Set output directories for build targets -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/bin) +set(ARTIFACT_DIR "${CMAKE_BINARY_DIR}/out") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ARTIFACT_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ARTIFACT_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ARTIFACT_DIR}/bin) # Include directories include_directories(${CMAKE_SOURCE_DIR}/src) @@ -134,7 +129,7 @@ include_directories(${CMAKE_SOURCE_DIR}/include) #add_custom_target(copy_assets #COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/data ${CMAKE_BINARY_DIR}/artifacts/share/data # COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/data ${CMAKE_BINARY_DIR}/tests/data - #) +#) # Add subdirectories add_subdirectory(src) @@ -144,5 +139,4 @@ if(ENABLE_TESTS) add_subdirectory(tests) endif() - -# vim: ts=2 sw=2 noet foldmethod=indent : +# vim: ts=4 sw=4 noet foldmethod=indent : diff --git a/cmake/BuildProperties.cmake b/cmake/BuildProperties.cmake new file mode 100644 index 0000000..46b67ad --- /dev/null +++ b/cmake/BuildProperties.cmake @@ -0,0 +1,31 @@ +# BuildProperties.cmake +# Copyright (c) 2024 Saul D Beniquez +# License: MIT +# +# This module defines a function prevent_in_source_build() that prevents in-source builds +# and sets a policy for CMake version 3.24.0 and above. + +function(prevent_in_source_build) + # Prevent in-source builds + if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR) + message(FATAL_ERROR "Source and build directories cannot be the same.") + endif() +endfunction() + +function(disable_deprecated_features) + # Use new timestamp behavior when extracting files archives + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") + cmake_policy(SET CMP0135 NEW) + endif() +endfunction() + +function(disable_tests_if_subproject) +if (NOT DEFINED PROJECT_NAME) + option(ENABLE_TESTS "Build and run unit tests" ON) +else() + option(ENABLE_TESTS "Build and run unit tests" OFF) +endif() +endfunction() + + +# vim: ts=4 sts=4 sw=4 noet : diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 0000000..cc25ec2 --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.38.7) +set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7d5db25..dd0766a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,7 +19,7 @@ set_target_properties(test-runner PROPERTIES # add catch2's ctest cmake module and register the tests defined by mdml-tests # using catch_discover_tests include(ctest) -include(catch) +include(Catch) catch_discover_tests(test-runner) # bonus: add a custom ctest target to the build system, to run tests in the