From 7cf69779b338ae870283d750aec0e3b32f5a152a Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Fri, 19 May 2023 12:33:51 -0500 Subject: [PATCH] Add support for adding cmake extras to packages (#345) Signed-off-by: Michael Carroll --- cmake/GzConfigureProject.cmake | 48 +++++++++++++++++++++++++++++- cmake/GzUtils.cmake | 54 ++++++++++++++++++++++++++++++++++ cmake/gz-config.cmake.in | 6 ++++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/cmake/GzConfigureProject.cmake b/cmake/GzConfigureProject.cmake index ec0c69f6..ad9ee32c 100644 --- a/cmake/GzConfigureProject.cmake +++ b/cmake/GzConfigureProject.cmake @@ -49,7 +49,7 @@ macro(gz_configure_project) # Define the expected arguments set(options NO_PROJECT_PREFIX NO_IGNITION_PREFIX) # TODO(CH3): NO_IGNITION_PREFIX IS DEPRECATED. set(oneValueArgs REPLACE_INCLUDE_PATH REPLACE_IGNITION_INCLUDE_PATH VERSION_SUFFIX) # TODO(CH3): REPLACE_IGNITION_INCLUDE_PATH IS DEPRECATED. - set(multiValueArgs) # We are not using multiValueArgs yet + set(multiValueArgs CONFIG_EXTRAS) #------------------------------------ # Parse the arguments @@ -144,6 +144,52 @@ macro(gz_configure_project) message(STATUS "${PROJECT_NAME} version ${PROJECT_VERSION_FULL}") + #============================================================================ + # Handle extra cmake configurations + set(PACKAGE_CONFIG_EXTRA_FILES "") + set(extras) + + if (DEFINED gz_configure_project_CONFIG_EXTRAS) + list(APPEND extras ${gz_configure_project_CONFIG_EXTRAS}) + endif() + + foreach(extra ${extras}) + _gz_assert_file_exists("${extra}" + "gz_configure_project() called with extra file '${extra}' which does not exist") + _gz_stamp("${extra}") + + # expand template + _gz_string_ends_with("${extra}" ".cmake.in" is_template) + if(is_template) + get_filename_component(extra_filename "${extra}" NAME) + # cut of .in extension + string(LENGTH "${extra_filename}" length) + math(EXPR offset "${length} - 3") + string(SUBSTRING "${extra_filename}" 0 ${offset} extra_filename) + configure_file( + "${extra}" + ${CMAKE_CURRENT_BINARY_DIR}/gz-cmake/${extra_filename} + @ONLY + ) + set(extra + "${CMAKE_CURRENT_BINARY_DIR}/gz-cmake/${extra_filename}") + endif() + + # install cmake file and register for CMake config file + _gz_string_ends_with("${extra}" ".cmake" is_cmake) + if(is_cmake) + install(FILES + ${extra} + DESTINATION lib/cmake/${PROJECT_NAME}/ + ) + get_filename_component(extra_filename "${extra}" NAME) + list(APPEND PACKAGE_CONFIG_EXTRA_FILES "${extra_filename}") + else() + message(FATAL_ERROR "gz_configure_project() the CONFIG_EXTRAS file '${extra}' " + "does neither end with '.cmake' nor with '.cmake.in'.") + endif() + endforeach() + #============================================================================ # Identify the operating system gz_check_os() diff --git a/cmake/GzUtils.cmake b/cmake/GzUtils.cmake index c2636a71..99d803d5 100644 --- a/cmake/GzUtils.cmake +++ b/cmake/GzUtils.cmake @@ -24,6 +24,60 @@ include(GzInstallAllHeaders) include(GzRelocatableBinaries) include(GzStringAppend) +################################################# +# assert that a file exists +# From ament/ament_cmake_core/core/assert_file_exists.cmake (Apache 2.0) +function(_gz_assert_file_exists filename error_message) + if(NOT IS_ABSOLUTE "${filename}") + set(filename "${CMAKE_CURRENT_LIST_DIR}/${filename}") + endif() + if(NOT EXISTS "${filename}") + message(FATAL_ERROR "${error_message}") + endif() +endfunction() + +################################################# +# From ament/ament_cmake_core/core/stamp.cmake (Apache 2.0) +# :param path: file name +# +# Uses ``configure_file`` to generate a file ``filepath.stamp`` hidden +# somewhere in the build tree. This will cause cmake to rebuild its +# cache when ``filepath`` is modified. +# +function(_gz_stamp path) + get_filename_component(filename "${path}" NAME) + configure_file( + "${path}" + "${CMAKE_CURRENT_BINARY_DIR}/gz-cmake/stamps/${filename}.stamp" + COPYONLY + ) +endfunction() + +################################################# +# From ament/ament_cmake_core/core/string_ends_with.cmake (Apache 2.0) +# Check if a string ends with a specific suffix. +# +# :param str: the string +# :type str: string +# :param suffix: the suffix +# :type suffix: string +# :param var: the output variable name +# :type var: bool +# +function(_gz_string_ends_with str suffix var) + string(LENGTH "${str}" str_length) + string(LENGTH "${suffix}" suffix_length) + set(value FALSE) + if(NOT ${str_length} LESS ${suffix_length}) + math(EXPR str_offset "${str_length} - ${suffix_length}") + string(SUBSTRING "${str}" ${str_offset} ${suffix_length} str_suffix) + if(str_suffix STREQUAL suffix) + set(value TRUE) + endif() + endif() + set(${var} ${value} PARENT_SCOPE) +endfunction() + ################################################# # Macro to turn a list into a string # Internal to gz-cmake. diff --git a/cmake/gz-config.cmake.in b/cmake/gz-config.cmake.in index 02b0e33a..1c853e87 100644 --- a/cmake/gz-config.cmake.in +++ b/cmake/gz-config.cmake.in @@ -182,3 +182,9 @@ set(@PROJECT_NAME_NO_VERSION_UPPER@_DOXYGEN_TAGFILE "${PACKAGE_PREFIX_DIR}/@GZ_D # Specify the API url. This is where the doxygen tag file will resolve URLS to. set(@PROJECT_NAME_NO_VERSION_UPPER@_API_URL "https://gazebosim.org/api/@GZ_DESIGNATION@/@PROJECT_VERSION_MAJOR@") + +# include all config extra files +set(_extras "@PACKAGE_CONFIG_EXTRA_FILES@") +foreach(_extra ${_extras}) + include("${@PROJECT_NAME@_DIR}/${_extra}") +endforeach()