From 21dac3c3a68c5f0fb5911910db96753ac95bc780 Mon Sep 17 00:00:00 2001 From: Dan Rose Date: Wed, 25 Sep 2019 15:22:12 -0500 Subject: [PATCH] Rework dynamic RMW Defer list of available RMWs to build time of downstream packages so you can build a dependent package even if RMW_IMPLEMENTATION is set to a value not available when the rmw_implementation package was built. Remove CMake Config flag "RMW_IMPLEMENTATION_FORCE_DYNAMIC_LOADING". Add CMake Config flag "RMW_IMPLEMENTATION_DISABLE_RUNTIME_SELECTION" so you can statically link a middleware, even if multiple present at build time. This value can be explicitly set, but by default preserves the behavior of "statically link if one middleware found". Add a scary message if the user tries to change the implementation and built with RMW_IMPLEMENTATION_DISABLE_RUNTIME_SELECTION=ON Signed-off-by: Dan Rose --- rmw_implementation/CMakeLists.txt | 52 ++++------- .../rmw_implementation-extras.cmake.in | 91 ++++++++----------- 2 files changed, 57 insertions(+), 86 deletions(-) diff --git a/rmw_implementation/CMakeLists.txt b/rmw_implementation/CMakeLists.txt index da0da9fc..d05f2673 100644 --- a/rmw_implementation/CMakeLists.txt +++ b/rmw_implementation/CMakeLists.txt @@ -15,9 +15,6 @@ find_package(ament_cmake REQUIRED) find_package(rcutils REQUIRED) -# provides FindPoco.cmake and Poco on platforms without it -find_package(poco_vendor) -find_package(Poco COMPONENTS Foundation) find_package(rmw_implementation_cmake REQUIRED) if(BUILD_TESTING) @@ -27,42 +24,34 @@ endif() get_default_rmw_implementation(RMW_IMPLEMENTATION) -get_available_rmw_implementations(RMW_IMPLEMENTATIONS) -message(STATUS "") -message(STATUS "Found these rmw implementations:") -foreach(impl IN LISTS RMW_IMPLEMENTATIONS) - message(STATUS " '${impl}'") -endforeach() - message(STATUS "") message(STATUS "Default rmw implementation: '${RMW_IMPLEMENTATION}'") message(STATUS "") -option(RMW_IMPLEMENTATION_FORCE_DYNAMIC_LOADING - "Force use of dynamic loading (via poco), even if there is only one implementation available" - OFF) - -# Nominally use dynamic loading if poco is available. -set(RMW_IMPLEMENTATION_SUPPORTS_POCO ${Poco_FOUND}) -# Determine if we're going to actually support dynamic loading. -if(RMW_IMPLEMENTATION_FORCE_DYNAMIC_LOADING) - # Force usage. - if(NOT Poco_FOUND) - message(FATAL_ERROR "Dynamic loading forced, but poco is not found!") - endif() - set(RMW_IMPLEMENTATION_SUPPORTS_POCO TRUE) -elseif(NOT RMW_IMPLEMENTATIONS MATCHES ";") - set(RMW_IMPLEMENTATION_SUPPORTS_POCO FALSE) +get_available_rmw_implementations(available_rmw_implementations) +list(LENGTH available_rmw_implementations count_available_rmw_implementations) +if(count_available_rmw_implementations EQUAL 1) + set(rmw_implementation_disable_runtime_selection_default ON) +else() + set(rmw_implementation_disable_runtime_selection_default OFF) endif() -if(NOT RMW_IMPLEMENTATION_SUPPORTS_POCO) - message(STATUS "Dynamic loading disabled; directly referencing '${RMW_IMPLEMENTATION}'") - message(STATUS "") +option(RMW_IMPLEMENTATION_DISABLE_RUNTIME_SELECTION "\ + Use only the RMW implementation specified at build time via the \ + 'RMW_IMPLEMENTATION' environment variable and the 'RMW_IMPLEMENTATION' \ + CMake option, ignoring the runtime value of the 'RMW_IMPLEMENTATION' \ + environment variable" + ${rmw_implementation_disable_runtime_selection_default}) +if(RMW_IMPLEMENTATION_DISABLE_RUNTIME_SELECTION) + message(STATUS "Runtime selection of RMW disabled; Only using " + "'${RMW_IMPLEMENTATION}'") else() - message(STATUS "Dynamic loading enabled with any of the available rmw implementations") - message(STATUS "") + message(STATUS "Runtime selection of RMW enabled") + # provides FindPoco.cmake and Poco on platforms without it + find_package(poco_vendor REQUIRED) + find_package(Poco REQUIRED COMPONENTS Foundation) find_package(rmw REQUIRED) link_directories(${Poco_LIBRARY_DIR}) @@ -73,7 +62,6 @@ else() "rmw") target_compile_definitions(${PROJECT_NAME} PUBLIC "DEFAULT_RMW_IMPLEMENTATION=${RMW_IMPLEMENTATION}") - target_link_libraries(${PROJECT_NAME}) configure_rmw_library(${PROJECT_NAME}) ament_export_libraries(${PROJECT_NAME}) @@ -91,8 +79,6 @@ register_rmw_implementation( "cpp:rosidl_typesupport_cpp" ) -# necessary since get_available_rmw_implementations excludes rmw_implementation -list(APPEND RMW_IMPLEMENTATIONS "rmw_implementation") ament_package( CONFIG_EXTRAS "rmw_implementation-extras.cmake.in" ) diff --git a/rmw_implementation/rmw_implementation-extras.cmake.in b/rmw_implementation/rmw_implementation-extras.cmake.in index 372e2613..caae5a8c 100644 --- a/rmw_implementation/rmw_implementation-extras.cmake.in +++ b/rmw_implementation/rmw_implementation-extras.cmake.in @@ -15,68 +15,53 @@ # generated from rmw_implementation/rmw_implementation-extras.cmake.in find_package(rmw_implementation_cmake REQUIRED) -set(default_rmw_implementation "@RMW_IMPLEMENTATION@") -set(available_rmw_implementations "@RMW_IMPLEMENTATIONS@") if(NOT "${RMW_IMPLEMENTATION}" STREQUAL "") - set(requested_rmw_implementation ${RMW_IMPLEMENTATION}) - if(@RMW_IMPLEMENTATION_SUPPORTS_POCO@) - if(NOT requested_rmw_implementation IN_LIST available_rmw_implementations) - message(FATAL_ERROR - "The RMW implementation has been specified as " - "'${requested_rmw_implementation}' through CMake, " - "however it is not in the list of supported rmw implementations, " - "which was specified when the 'rmw_implementation' package was built.") - endif() - else() - if(NOT requested_rmw_implementation STREQUAL default_rmw_implementation) - message(FATAL_ERROR - "The RMW implementation has been specified as " - "'${requested_rmw_implementation}' through CMake, " - "however this needs to match the RMW implementation " - "'${default_rmw_implementation}', " - "which was specified when the 'rmw_implementation' package was built.") - endif() - endif() + set(requested_rmw_implementation "${RMW_IMPLEMENTATION}") + set(requested_rmw_implementation_from "CMake") +elseif(NOT "$ENV{RMW_IMPLEMENTATION}" STREQUAL "") + set(requested_rmw_implementation "$ENV{RMW_IMPLEMENTATION}") + set(requested_rmw_implementation_from + "environment variable 'RMW_IMPLEMENTATION'") +else() + set(requested_rmw_implementation "@RMW_IMPLEMENTATION@") + set(requested_rmw_implementation_from + "the default when @PROJECT_NAME@ was built") endif() -if(NOT "$ENV{RMW_IMPLEMENTATION}" STREQUAL "") - set(requested_rmw_implementation $ENV{RMW_IMPLEMENTATION}) - if(@RMW_IMPLEMENTATION_SUPPORTS_POCO@) - if(NOT requested_rmw_implementation IN_LIST available_rmw_implementations) - message(FATAL_ERROR - "The RMW implementation has been specified as " - "'${requested_rmw_implementation}' through the environment variable " - "'RMW_IMPLEMENTATION', " - "however it is not in the list of supported rmw implementations, " - "which was specified when the 'rmw_implementation' package was built.") - endif() - else() - if(NOT requested_rmw_implementation STREQUAL default_rmw_implementation) - message(FATAL_ERROR - "The RMW implementation has been specified as " - "'${requested_rmw_implementation}' " - "through the environment variable 'RMW_IMPLEMENTATION', " - "however this needs to match the RMW implementation " - "'${default_rmw_implementation}', " - "which was specified when the 'rmw_implementation' package was built.") - endif() +if(@RMW_IMPLEMENTATION_DISABLE_RUNTIME_SELECTION@) + message(STATUS "Using RMW implementation '@RMW_IMPLEMENTATION@'") + if(NOT requested_rmw_implementation STREQUAL "@RMW_IMPLEMENTATION@") + message(FATAL_ERROR + "The RMW implementation has been specified as " + "'${requested_rmw_implementation}' via " + "${requested_rmw_implementation_from}, but rmw_implementation was built " + "only with support for '@RMW_IMPLEMENTATION@'.") + endif() + find_package("@RMW_IMPLEMENTATION@" REQUIRED) + + # TODO should never need definitions and include dirs? + list(APPEND rmw_implementation_DEFINITIONS + ${@RMW_IMPLEMENTATION@_DEFINITIONS}) + list(APPEND rmw_implementation_INCLUDE_DIRS + ${@RMW_IMPLEMENTATION@_INCLUDE_DIRS}) + list(APPEND rmw_implementation_LIBRARIES + ${@RMW_IMPLEMENTATION@_LIBRARIES}) +else() + get_available_rmw_implementations(available_rmw_implementations) + + if(NOT requested_rmw_implementation IN_LIST available_rmw_implementations) + message(FATAL_ERROR + "The RMW implementation has been specified as " + "'${requested_rmw_implementation}' via " + "${requested_rmw_implementation_from}, but it is not available at this " + "time.\n\nCurrently available middlewares:\n" + "'${available_rmw_implementations}'") endif() -endif() -if(@RMW_IMPLEMENTATION_SUPPORTS_POCO@) set(selected_rmw_implementation "@PROJECT_NAME@") # no need to find_package @PROJECT_NAME@ # since this code is already part of a find_package call of that package -else() - set(selected_rmw_implementation "${default_rmw_implementation}") - message(STATUS "Using RMW implementation '${selected_rmw_implementation}' as default") - find_package("${selected_rmw_implementation}" REQUIRED) - - # TODO should never need definitions and include dirs? - list(APPEND rmw_implementation_DEFINITIONS ${${selected_rmw_implementation}_DEFINITIONS}) - list(APPEND rmw_implementation_INCLUDE_DIRS ${${selected_rmw_implementation}_INCLUDE_DIRS}) - list(APPEND rmw_implementation_LIBRARIES ${${selected_rmw_implementation}_LIBRARIES}) endif() find_package(Threads REQUIRED)