From 58d4e94b50b3cc1610dceb561459915a46e9b50a Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Thu, 9 Oct 2025 15:24:24 -0500 Subject: [PATCH] Fix CMake --find-package mode There is a CMake mode which can be used to extract basic compile and linker flags as would be produced by a call to find_package(). Existing ament_cmake code always assumes that we're being invoked under a "PROJECT" role. This change skips certain project-specific parts of ament_cmake_core and ament_cmake_test which shouldn't be run unless we're actually configuring a CMakeLists.txt project. The smoke tests added by this change validate that the "extra" CMake functionality provided by these packages continues to be loadable outside of a project context. It does not validate that the defined functions can actually be used, but will serve as a validation that features like CMake --find-package should work. Signed-off-by: Scott K Logan --- ament_cmake_core/CMakeLists.txt | 5 ++ .../ament_cmake_core-extras.cmake | 10 +-- ...ament_cmake_package_templates-extras.cmake | 69 ++++++++++--------- .../ament_cmake_uninstall_target-extras.cmake | 37 +++++----- ament_cmake_core/cmake/core/all.cmake | 5 +- ament_cmake_core/test/CMakeLists.txt | 2 + ament_cmake_core/test/smoke.cmake | 2 + ament_cmake_test/CMakeLists.txt | 5 ++ .../ament_cmake_test-extras.cmake | 7 +- ament_cmake_test/test/CMakeLists.txt | 2 + ament_cmake_test/test/smoke.cmake | 2 + 11 files changed, 89 insertions(+), 57 deletions(-) create mode 100644 ament_cmake_core/test/CMakeLists.txt create mode 100644 ament_cmake_core/test/smoke.cmake create mode 100644 ament_cmake_test/test/CMakeLists.txt create mode 100644 ament_cmake_test/test/smoke.cmake diff --git a/ament_cmake_core/CMakeLists.txt b/ament_cmake_core/CMakeLists.txt index 5eaf4773..d28c42c5 100644 --- a/ament_cmake_core/CMakeLists.txt +++ b/ament_cmake_core/CMakeLists.txt @@ -29,6 +29,11 @@ ament_package( "ament_cmake_symlink_install-extras.cmake" # must be after uninstall_target ) +include(CTest) +if(BUILD_TESTING) + add_subdirectory(test) +endif() + install( DIRECTORY cmake DESTINATION share/${PROJECT_NAME} diff --git a/ament_cmake_core/ament_cmake_core-extras.cmake b/ament_cmake_core/ament_cmake_core-extras.cmake index 671cf0ff..3f549d28 100644 --- a/ament_cmake_core/ament_cmake_core-extras.cmake +++ b/ament_cmake_core/ament_cmake_core-extras.cmake @@ -16,7 +16,9 @@ include("${ament_cmake_core_DIR}/core/all.cmake" NO_POLICY_SCOPE) -# Add AMENT_IGNORE to CMAKE_BINARY_DIR to avoid picking up cmake specific folders created by -# CLion in `colcon build` and `colcon test` commands -file(WRITE ${CMAKE_BINARY_DIR}/AMENT_IGNORE "") - +get_property(_cmake_role GLOBAL PROPERTY CMAKE_ROLE) +if("${_cmake_role}" STREQUAL "PROJECT") + # Add AMENT_IGNORE to CMAKE_BINARY_DIR to avoid picking up cmake specific folders created by + # CLion in `colcon build` and `colcon test` commands + file(WRITE ${CMAKE_BINARY_DIR}/AMENT_IGNORE "") +endif() diff --git a/ament_cmake_core/ament_cmake_package_templates-extras.cmake b/ament_cmake_core/ament_cmake_package_templates-extras.cmake index 24f34884..bedeecb5 100644 --- a/ament_cmake_core/ament_cmake_package_templates-extras.cmake +++ b/ament_cmake_core/ament_cmake_package_templates-extras.cmake @@ -12,39 +12,42 @@ # See the License for the specific language governing permissions and # limitations under the License. -# extract information from ament_package.templates -if(NOT TARGET Python3::Interpreter) - message(FATAL_ERROR - "ament_cmake_package_templates: target 'Python3::Interpreter' must exist") -endif() +get_property(_cmake_role GLOBAL PROPERTY CMAKE_ROLE) +if("${_cmake_role}" STREQUAL "PROJECT") + # extract information from ament_package.templates + if(NOT TARGET Python3::Interpreter) + message(FATAL_ERROR + "ament_cmake_package_templates: target 'Python3::Interpreter' must exist") + endif() -# stamp script to generate CMake code -set(_generator - "${ament_cmake_core_DIR}/package_templates/templates_2_cmake.py") -stamp("${_generator}") + # stamp script to generate CMake code + set(_generator + "${ament_cmake_core_DIR}/package_templates/templates_2_cmake.py") + stamp("${_generator}") -# invoke generator script -set(_generated_file - "${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_package_templates/templates.cmake") -get_executable_path(_python_interpreter Python3::Interpreter CONFIGURE) -set(_cmd - "${_python_interpreter}" - "${_generator}" - "${_generated_file}" -) -execute_process( - COMMAND ${_cmd} - RESULT_VARIABLE _res -) -if(NOT _res EQUAL 0) - string(REPLACE ";" " " _cmd_str "${_cmd}") - message(FATAL_ERROR - "execute_process(${_cmd_str}) returned error code ${_res}") -endif() + # invoke generator script + set(_generated_file + "${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_package_templates/templates.cmake") + get_executable_path(_python_interpreter Python3::Interpreter CONFIGURE) + set(_cmd + "${_python_interpreter}" + "${_generator}" + "${_generated_file}" + ) + execute_process( + COMMAND ${_cmd} + RESULT_VARIABLE _res + ) + if(NOT _res EQUAL 0) + string(REPLACE ";" " " _cmd_str "${_cmd}") + message(FATAL_ERROR + "execute_process(${_cmd_str}) returned error code ${_res}") + endif() -# load extracted variables into cmake -# for each environment hook defined in `ament_package` -# (e.g. `library_path.bat|sh`) a CMake variable is defined starting with -# `ament_cmake_package_templates_ENVIRONMENT_HOOK_` -# (e.g. `ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH`) -include("${_generated_file}") + # load extracted variables into cmake + # for each environment hook defined in `ament_package` + # (e.g. `library_path.bat|sh`) a CMake variable is defined starting with + # `ament_cmake_package_templates_ENVIRONMENT_HOOK_` + # (e.g. `ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH`) + include("${_generated_file}") +endif() diff --git a/ament_cmake_core/ament_cmake_uninstall_target-extras.cmake b/ament_cmake_core/ament_cmake_uninstall_target-extras.cmake index a572d06a..5fce4701 100644 --- a/ament_cmake_core/ament_cmake_uninstall_target-extras.cmake +++ b/ament_cmake_core/ament_cmake_uninstall_target-extras.cmake @@ -21,24 +21,27 @@ if(AMENT_CMAKE_UNINSTALL_TARGET) include( "${ament_cmake_core_DIR}/uninstall_target/ament_cmake_uninstall_target_append_uninstall_code.cmake") - # create the install script from the template - # ament_cmake_core/uninstall_target/ament_cmake_uninstall_target.cmake.in - set(AMENT_CMAKE_UNINSTALL_TARGET_UNINSTALL_SCRIPT - "${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_uninstall_target/ament_cmake_uninstall_target.cmake") - configure_file( - "${ament_cmake_core_DIR}/uninstall_target/ament_cmake_uninstall_target.cmake.in" - "${AMENT_CMAKE_UNINSTALL_TARGET_UNINSTALL_SCRIPT}" - @ONLY - ) + get_property(_cmake_role GLOBAL PROPERTY CMAKE_ROLE) + if("${_cmake_role}" STREQUAL "PROJECT") + # create the install script from the template + # ament_cmake_core/uninstall_target/ament_cmake_uninstall_target.cmake.in + set(AMENT_CMAKE_UNINSTALL_TARGET_UNINSTALL_SCRIPT + "${CMAKE_CURRENT_BINARY_DIR}/ament_cmake_uninstall_target/ament_cmake_uninstall_target.cmake") + configure_file( + "${ament_cmake_core_DIR}/uninstall_target/ament_cmake_uninstall_target.cmake.in" + "${AMENT_CMAKE_UNINSTALL_TARGET_UNINSTALL_SCRIPT}" + @ONLY + ) - if(NOT TARGET uninstall) - add_custom_target(uninstall) - endif() + if(NOT TARGET uninstall) + add_custom_target(uninstall) + endif() - if(NOT TARGET ${PROJECT_NAME}_uninstall) - # register uninstall target to run generated CMake script - add_custom_target(${PROJECT_NAME}_uninstall - COMMAND ${CMAKE_COMMAND} -P "${AMENT_CMAKE_UNINSTALL_TARGET_UNINSTALL_SCRIPT}") - add_dependencies(uninstall ${PROJECT_NAME}_uninstall) + if(NOT TARGET ${PROJECT_NAME}_uninstall) + # register uninstall target to run generated CMake script + add_custom_target(${PROJECT_NAME}_uninstall + COMMAND ${CMAKE_COMMAND} -P "${AMENT_CMAKE_UNINSTALL_TARGET_UNINSTALL_SCRIPT}") + add_dependencies(uninstall ${PROJECT_NAME}_uninstall) + endif() endif() endif() diff --git a/ament_cmake_core/cmake/core/all.cmake b/ament_cmake_core/cmake/core/all.cmake index 63bca131..a4d5fc4c 100644 --- a/ament_cmake_core/cmake/core/all.cmake +++ b/ament_cmake_core/cmake/core/all.cmake @@ -30,7 +30,10 @@ endif() # the following operations must be performed inside a project context if(NOT PROJECT_NAME) - project(ament_cmake_internal NONE) + get_property(_cmake_role GLOBAL PROPERTY CMAKE_ROLE) + if("${_cmake_role}" STREQUAL "PROJECT") + project(ament_cmake_internal NONE) + endif() endif() # use BUILD_TESTING to avoid warnings about not using it diff --git a/ament_cmake_core/test/CMakeLists.txt b/ament_cmake_core/test/CMakeLists.txt new file mode 100644 index 00000000..6aa22aa5 --- /dev/null +++ b/ament_cmake_core/test/CMakeLists.txt @@ -0,0 +1,2 @@ +add_test(NAME smoke + COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/smoke.cmake") diff --git a/ament_cmake_core/test/smoke.cmake b/ament_cmake_core/test/smoke.cmake new file mode 100644 index 00000000..9083fc44 --- /dev/null +++ b/ament_cmake_core/test/smoke.cmake @@ -0,0 +1,2 @@ +set(ament_cmake_core_DIR "${CMAKE_CURRENT_LIST_DIR}/../cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../ament_cmake_core-extras.cmake") diff --git a/ament_cmake_test/CMakeLists.txt b/ament_cmake_test/CMakeLists.txt index 52ad290f..c5382b65 100644 --- a/ament_cmake_test/CMakeLists.txt +++ b/ament_cmake_test/CMakeLists.txt @@ -11,6 +11,11 @@ ament_package( CONFIG_EXTRAS "ament_cmake_test-extras.cmake" ) +include(CTest) +if(BUILD_TESTING) + add_subdirectory(test) +endif() + install( DIRECTORY cmake DESTINATION share/${PROJECT_NAME} diff --git a/ament_cmake_test/ament_cmake_test-extras.cmake b/ament_cmake_test/ament_cmake_test-extras.cmake index 6e231a5a..dea7af1a 100644 --- a/ament_cmake_test/ament_cmake_test-extras.cmake +++ b/ament_cmake_test/ament_cmake_test-extras.cmake @@ -14,7 +14,10 @@ # copied from ament_cmake_test/ament_cmake_test-extras.cmake -enable_testing() +get_property(_cmake_role GLOBAL PROPERTY CMAKE_ROLE) +if("${_cmake_role}" STREQUAL "PROJECT") + enable_testing() +endif() # same option as in the CTest module option(BUILD_TESTING "Build the testing tree." ON) @@ -24,7 +27,7 @@ set( CACHE PATH "The path where test results are generated" ) -if(BUILD_TESTING) +if(BUILD_TESTING AND "${_cmake_role}" STREQUAL "PROJECT") # configure ctest not to truncate the dashboard summary file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake" "set(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 0)\n" diff --git a/ament_cmake_test/test/CMakeLists.txt b/ament_cmake_test/test/CMakeLists.txt new file mode 100644 index 00000000..6aa22aa5 --- /dev/null +++ b/ament_cmake_test/test/CMakeLists.txt @@ -0,0 +1,2 @@ +add_test(NAME smoke + COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/smoke.cmake") diff --git a/ament_cmake_test/test/smoke.cmake b/ament_cmake_test/test/smoke.cmake new file mode 100644 index 00000000..d2102bda --- /dev/null +++ b/ament_cmake_test/test/smoke.cmake @@ -0,0 +1,2 @@ +set(ament_cmake_test_DIR "${CMAKE_CURRENT_LIST_DIR}/../cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../ament_cmake_test-extras.cmake")