From b214324bf268e6342c366e50c986844211597859 Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Wed, 24 Jul 2019 09:15:37 -0700 Subject: [PATCH] Cmake infrastructure for creating components (#784) *cmake macro to create components for libraries with multiple nodes Signed-off-by: Siddharth Kucheria --- rclcpp_components/CMakeLists.txt | 7 +- .../rclcpp_components_register_node.cmake | 52 +++++++++++++++ ...make => rclcpp_components-extras.cmake.in} | 4 +- rclcpp_components/src/node_main.cpp.in | 66 +++++++++++++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 rclcpp_components/cmake/rclcpp_components_register_node.cmake rename rclcpp_components/{rclcpp_components-extras.cmake => rclcpp_components-extras.cmake.in} (86%) create mode 100644 rclcpp_components/src/node_main.cpp.in diff --git a/rclcpp_components/CMakeLists.txt b/rclcpp_components/CMakeLists.txt index 95ba47fa93..a83a5434a3 100644 --- a/rclcpp_components/CMakeLists.txt +++ b/rclcpp_components/CMakeLists.txt @@ -41,6 +41,11 @@ ament_target_dependencies(component_container "rclcpp" ) +set(node_main_template_install_dir "share/${PROJECT_NAME}") +install(FILES + src/node_main.cpp.in + DESTINATION ${node_main_template_install_dir}) + add_executable( component_container_mt src/component_container_mt.cpp @@ -119,4 +124,4 @@ install( ament_export_include_directories(include) ament_export_dependencies(class_loader) ament_export_dependencies(rclcpp) -ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake) +ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake.in) diff --git a/rclcpp_components/cmake/rclcpp_components_register_node.cmake b/rclcpp_components/cmake/rclcpp_components_register_node.cmake new file mode 100644 index 0000000000..930bd03de5 --- /dev/null +++ b/rclcpp_components/cmake/rclcpp_components_register_node.cmake @@ -0,0 +1,52 @@ +# Copyright 2019 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# usage: rclcpp_components_register_node( +# PLUGIN EXECUTABLE ) +# +# Register an rclcpp component with the ament +# resource index and create an executable. +# +# :param target: the shared library target +# :type target: string +# :param PLUGIN: the plugin name +# :type PLUGIN: string +# :type EXECUTABLE: the node's executable name +# :type EXECUTABLE: string +# +macro(rclcpp_components_register_node target) + cmake_parse_arguments(ARGS "" "PLUGIN;EXECUTABLE" "" ${ARGN}) + set(component ${ARGS_PLUGIN}) + set(node ${ARGS_EXECUTABLE}) + _rclcpp_components_register_package_hook() + set(_path "lib") + set(library_name "$") + if(WIN32) + set(_path "bin") + endif() + set(_RCLCPP_COMPONENTS__NODES + "${_RCLCPP_COMPONENTS__NODES}${component};${_path}/$\n") + configure_file(${rclcpp_components_NODE_TEMPLATE} + ${PROJECT_BINARY_DIR}/node_main_configured.cpp.in) + file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp + INPUT ${PROJECT_BINARY_DIR}/node_main_configured.cpp.in) + add_executable(${node} ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp) + ament_target_dependencies(${node} + "rclcpp" + "class_loader" + "rclcpp_components") + install(TARGETS + ${node} + DESTINATION lib/${PROJECT_NAME}) +endmacro() diff --git a/rclcpp_components/rclcpp_components-extras.cmake b/rclcpp_components/rclcpp_components-extras.cmake.in similarity index 86% rename from rclcpp_components/rclcpp_components-extras.cmake rename to rclcpp_components/rclcpp_components-extras.cmake.in index ce77ab671b..f1956c1107 100644 --- a/rclcpp_components/rclcpp_components-extras.cmake +++ b/rclcpp_components/rclcpp_components-extras.cmake.in @@ -25,5 +25,7 @@ macro(_rclcpp_components_register_package_hook) endif() endmacro() -include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake") +set(@PROJECT_NAME@_NODE_TEMPLATE "@CMAKE_INSTALL_PREFIX@/@node_main_template_install_dir@/node_main.cpp.in") +include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake") +include("${rclcpp_components_DIR}/rclcpp_components_register_node.cmake") diff --git a/rclcpp_components/src/node_main.cpp.in b/rclcpp_components/src/node_main.cpp.in new file mode 100644 index 0000000000..bfebc4aa7d --- /dev/null +++ b/rclcpp_components/src/node_main.cpp.in @@ -0,0 +1,66 @@ +// Copyright 2019 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "class_loader/class_loader.hpp" +#include "rclcpp/rclcpp.hpp" +#include "rclcpp_components/node_factory.hpp" +#include "rclcpp_components/node_factory_template.hpp" + +#define NODE_MAIN_LOGGER_NAME "@node@" + +int main(int argc, char * argv[]) +{ + auto args = rclcpp::init_and_remove_ros_arguments(argc, argv); + rclcpp::Logger logger = rclcpp::get_logger(NODE_MAIN_LOGGER_NAME); + rclcpp::executors::SingleThreadedExecutor exec; + rclcpp::NodeOptions options; + options.arguments(args); + std::vector loaders; + std::vector node_wrappers; + + std::string library_name = "@library_name@"; + std::string class_name = "rclcpp_components::NodeFactoryTemplate<@component@>"; + + RCLCPP_DEBUG(logger, "Load library %s", library_name.c_str()); + auto loader = new class_loader::ClassLoader(library_name); + auto classes = loader->getAvailableClasses(); + for (auto clazz : classes) { + std::string name = clazz.c_str(); + if (!(name.compare(class_name))) { + RCLCPP_DEBUG(logger, "Instantiate class %s", clazz.c_str()); + auto node_factory = loader->createInstance(clazz); + auto wrapper = node_factory->create_node_instance(options); + auto node = wrapper.get_node_base_interface(); + node_wrappers.push_back(wrapper); + exec.add_node(node); + } + } + loaders.push_back(loader); + + + exec.spin(); + + for (auto wrapper : node_wrappers) { + exec.remove_node(wrapper.get_node_base_interface()); + } + node_wrappers.clear(); + + rclcpp::shutdown(); + + return 0; +}