From 975464dd3fa7a79964a01d491549851a8f889e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Hern=C3=A1ndez=20Cordero?= Date: Thu, 22 Jul 2021 20:12:46 +0200 Subject: [PATCH] Add standalone executables (#121) * Add standalone executables Signed-off-by: ahcorde * Added feedback and more tests Signed-off-by: ahcorde * Add one more test Signed-off-by: ahcorde * Fixed test Signed-off-by: ahcorde --- CMakeLists.txt | 5 + examples/ls.ign | 6 + src/CMakeLists.txt | 92 +++----------- src/cmd/CMakeLists.txt | 126 ++++++++++++++++++++ src/cmd/cmdlaunch.rb.in | 65 ++++++++++ src/{ => cmd}/ign.cc | 13 +- src/{ => cmd}/ign.hh | 8 +- src/{ => cmd}/ign_TEST.cc | 49 ++++++-- src/{ => cmd}/launch.yaml.in | 0 src/cmd/launch_main.cc | 141 ++++++++++++++++++++++ src/cmdlaunch.rb.in | 224 ----------------------------------- test/config/erb.ign | 12 ++ 12 files changed, 422 insertions(+), 319 deletions(-) create mode 100644 examples/ls.ign create mode 100644 src/cmd/CMakeLists.txt create mode 100755 src/cmd/cmdlaunch.rb.in rename src/{ => cmd}/ign.cc (75%) rename src/{ => cmd}/ign.hh (83%) rename src/{ => cmd}/ign_TEST.cc (67%) rename src/{ => cmd}/launch.yaml.in (100%) create mode 100644 src/cmd/launch_main.cc delete mode 100755 src/cmdlaunch.rb.in create mode 100644 test/config/erb.ign diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ae8e621..7a0c82d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,11 @@ ign_find_package(TINYXML2 REQUIRED PRIVATE PRETTY tinyxml2) ign_find_package(ignition-common3 REQUIRED PRIVATE) set(IGN_COMMON_MAJOR_VER ${ignition-common3_VERSION_MAJOR}) +#-------------------------------------- +# Find ignition-utils +ign_find_package(ignition-utils1 REQUIRED COMPONENTS cli) +set(IGN_UTILS_VER ${ignition-utils1_VERSION_MAJOR}) + #-------------------------------------- # Find ignition-plugin ign_find_package(ignition-plugin1 REQUIRED_BY launch COMPONENTS loader register) diff --git a/examples/ls.ign b/examples/ls.ign new file mode 100644 index 00000000..ed1f36b9 --- /dev/null +++ b/examples/ls.ign @@ -0,0 +1,6 @@ + + + + ls + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a168daf5..eb850e49 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,13 +1,11 @@ # add_subdirectory(plugins) set (sources - ign.cc Manager.cc ) set (gtest_sources Manager_TEST.cc - ign_TEST.cc ) # Create the library target. @@ -35,80 +33,22 @@ ign_build_tests(TYPE UNIT SOURCES ${gtest_sources} ignition-common${IGN_COMMON_MAJOR_VER}::ignition-common${IGN_COMMON_MAJOR_VER} ) -if(TARGET UNIT_ign_TEST) - # Running `ign launch` on macOS has problems when run with /usr/bin/ruby - # due to System Integrity Protection (SIP). Try to find ruby from - # homebrew as a workaround. - if (APPLE) - find_program(BREW_RUBY ruby HINTS /usr/local/opt/ruby/bin) - endif() - - target_compile_definitions(UNIT_ign_TEST PRIVATE - "BREW_RUBY=\"${BREW_RUBY} \"") - - target_compile_definitions(UNIT_ign_TEST PRIVATE - "IGN_PATH=\"${HAVE_IGN_TOOLS}\"") -endif() - -# Generate a the ruby script. -# Note that the major version of the library is included in the name. -# Ex: cmdlaunch0.rb -if (APPLE) - set(IGN_LIBRARY_NAME lib${PROJECT_LIBRARY_TARGET_NAME}.dylib) -else() - set(IGN_LIBRARY_NAME lib${PROJECT_LIBRARY_TARGET_NAME}.so) -endif() - -configure_file( - "cmdlaunch.rb.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmdlaunch${PROJECT_VERSION_MAJOR}.rb" @ONLY) - - -# Install the ruby command line library in an unversioned location. -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmdlaunch${PROJECT_VERSION_MAJOR}.rb DESTINATION lib/ruby/ignition) - -set(ign_library_path - "${CMAKE_INSTALL_PREFIX}/lib/ruby/ignition/cmdlaunch${PROJECT_VERSION_MAJOR}") - -# Generate a configuration file. -# Note that the major version of the library is included in the name. -# Ex: fuel0.yaml -configure_file( - "launch.yaml.in" - "${CMAKE_CURRENT_BINARY_DIR}/launch${PROJECT_VERSION_MAJOR}.yaml" @ONLY) - -# Install the yaml configuration files in an unversioned location. -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/launch${PROJECT_VERSION_MAJOR}.yaml DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/ignition/) - -#=============================================================================== -# Generate the ruby script for internal testing. -# Note that the major version of the library is included in the name. -# Ex: cmdlaunch0.rb -set(cmd_script_generated_test "${CMAKE_BINARY_DIR}/test/lib/ruby/ignition/cmdlaunch${PROJECT_VERSION_MAJOR}.rb") -set(cmd_script_configured_test "${cmd_script_generated_test}.configured") - -# Set the library_location variable to the full path of the library file within -# the build directory. -set(IGN_LIBRARY_NAME "$") - -configure_file( - "cmdlaunch.rb.in" - "${cmd_script_configured_test}" - @ONLY) - -file(GENERATE - OUTPUT "${cmd_script_generated_test}" - INPUT "${cmd_script_configured_test}") - -# Used only for internal testing. -set(ign_library_path "${CMAKE_BINARY_DIR}/test/lib/ruby/ignition/cmdlaunch${PROJECT_VERSION_MAJOR}") - -# Generate a configuration file for internal testing. -# Note that the major version of the library is included in the name. -# Ex: launch0.yaml -configure_file( - "launch.yaml.in" - "${CMAKE_BINARY_DIR}/test/conf/launch${PROJECT_VERSION_MAJOR}.yaml" @ONLY) +# if(TARGET UNIT_ign_TEST) +# # Running `ign launch` on macOS has problems when run with /usr/bin/ruby +# # due to System Integrity Protection (SIP). Try to find ruby from +# # homebrew as a workaround. +# if (APPLE) +# find_program(BREW_RUBY ruby HINTS /usr/local/opt/ruby/bin) +# endif() +# +# target_compile_definitions(UNIT_ign_TEST PRIVATE +# "BREW_RUBY=\"${BREW_RUBY} \"") +# +# target_compile_definitions(UNIT_ign_TEST PRIVATE +# "IGN_PATH=\"${HAVE_IGN_TOOLS}\"") +# endif() + +add_subdirectory(cmd) #=============================================================================== # Bash completion diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt new file mode 100644 index 00000000..9db26ec1 --- /dev/null +++ b/src/cmd/CMakeLists.txt @@ -0,0 +1,126 @@ +# Collect source files into the "sources" variable and unit test files into the +# "gtest_sources" variable. +ign_get_libsources_and_unittests(sources gtest_sources) + +add_library(ign STATIC ign.cc) +target_include_directories(ign PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(ign PUBLIC + ${PROJECT_LIBRARY_TARGET_NAME} + ignition-common${IGN_COMMON_MAJOR_VER}::ignition-common${IGN_COMMON_MAJOR_VER} +) + +set(launch_executable ign-launch) +add_executable(${launch_executable} launch_main.cc) +target_link_libraries(${launch_executable} + ign + ignition-utils${IGN_UTILS_VER}::cli + ignition-common${IGN_COMMON_MAJOR_VER}::ignition-common${IGN_COMMON_MAJOR_VER} +) + +install( + TARGETS + ${launch_executable} + DESTINATION + ${IGN_LIB_INSTALL_DIR}/ignition/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}/ +) + +# Build the unit tests. +ign_build_tests(TYPE UNIT SOURCES ${gtest_sources} + TEST_LIST test_list + LIB_DEPS ${EXTRA_TEST_LIB_DEPS}) + +foreach(test ${test_list}) + target_link_libraries(${test} ign) + + # Inform each test of its output directory so it knows where to call the + # auxiliary files from. Using a generator expression here is useful for + # multi-configuration generators, like Visual Studio. + target_compile_definitions(${test} PRIVATE + "DETAIL_IGN_TRANSPORT_TEST_DIR=\"$\"" + "IGN_TEST_LIBRARY_PATH=\"$\"") + +endforeach() + +if (TARGET UNIT_ign_TEST) + set_tests_properties( + UNIT_ign_TEST + PROPERTIES + ENVIRONMENT + "IGN_CONFIG_PATH=${CMAKE_BINARY_DIR}/test/conf/$" + ) +endif() + +#=============================================================================== +# Generate the ruby script for internal testing. +# Note that the major version of the library is included in the name. +# Ex: cmdlaunch5.rb +set(cmd_script_generated_test "${CMAKE_BINARY_DIR}/test/lib/ruby/ignition/cmd${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.rb") +set(cmd_script_configured_test "${CMAKE_CURRENT_BINARY_DIR}/test_cmd${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.rb.configured") + +# Set the library_location variable to the full path of the library file within +# the build directory. +set(launch_exe_location "$") + +configure_file( + "cmd${IGN_DESIGNATION}.rb.in" + "${cmd_script_configured_test}" + @ONLY +) + +file(GENERATE + OUTPUT "${cmd_script_generated_test}" + INPUT "${cmd_script_configured_test}" +) + +#=============================================================================== +# Used for the installed version. +# Generate the ruby script that gets installed. +# Note that the major version of the library is included in the name. +# Ex: cmdlaunch5.rb +set(cmd_script_generated "${CMAKE_CURRENT_BINARY_DIR}/cmd${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.rb") +set(cmd_script_configured "${cmd_script_generated}.configured") + +# Set the library_location variable to the relative path to the library file +# within the install directory structure. +set(launch_exe_location "../../../${CMAKE_INSTALL_LIBDIR}/ignition/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}/$") + +message("launch_exe_location " ${launch_exe_location}) + +configure_file( + "cmd${IGN_DESIGNATION}.rb.in" + "${cmd_script_configured}" + @ONLY) + +file(GENERATE + OUTPUT "${cmd_script_generated}" + INPUT "${cmd_script_configured}") + +set(ign_library_path "${CMAKE_BINARY_DIR}/test/lib/ruby/ignition/cmd${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}") + +# Generate a configuration file for internal testing. +# Note that the major version of the library is included in the name. +# Ex: launch5.yaml +configure_file( + "${IGN_DESIGNATION}.yaml.in" + "${CMAKE_CURRENT_BINARY_DIR}/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml.configured" @ONLY) + +file(GENERATE + OUTPUT "${CMAKE_BINARY_DIR}/test/conf/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml" + INPUT "${CMAKE_CURRENT_BINARY_DIR}/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml.configured") + +# Used for the installed version. +set(ign_library_path "${CMAKE_INSTALL_PREFIX}/lib/ruby/ignition/cmd${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}") + +# Generate the configuration file that is installed. +# Note that the major version of the library is included in the name. +# Ex: launch5.yaml +configure_file( + "${IGN_DESIGNATION}.yaml.in" + "${CMAKE_CURRENT_BINARY_DIR}/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml" @ONLY) + +# Install the yaml configuration files in an unversioned location. +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/ignition/) + +# Install the ruby command line library in an unversioned location. +install(FILES ${cmd_script_generated} DESTINATION lib/ruby/ignition) diff --git a/src/cmd/cmdlaunch.rb.in b/src/cmd/cmdlaunch.rb.in new file mode 100755 index 00000000..0e44e756 --- /dev/null +++ b/src/cmd/cmdlaunch.rb.in @@ -0,0 +1,65 @@ +#!/usr/bin/env ruby + +# Copyright (C) 2014 Open Source Robotics Foundation +# +# 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. + +require 'open3' + +# Constants. +LIBRARY_VERSION = '@PROJECT_VERSION_FULL@' +COMMANDS = { + "launch" => "@launch_exe_location@", +} + +# +# Class for the Ignition launch command line tools. +# +class Cmd + def execute(args) + command = args[0] + exe_name = COMMANDS[command] + + if exe_name[0] == '/' + # If the first character is a slash, we'll assume that we've been given an + # absolute path to the executable. This is only used during test mode. + else + # We're assuming that the library path is relative to the current + # location of this script. + exe_name = File.expand_path(File.join(File.dirname(__FILE__), exe_name)) + end + conf_version = LIBRARY_VERSION + exe_version = `#{exe_name} --version`.strip + + # Sanity check: Verify that the version of the yaml file matches the version + # of the library that we are using. + unless exe_version.eql? conf_version + puts "Error: Version mismatch. Your configuration file version is + [#{conf_version}] but #{exe_name} version is [#{exe_version}]." + exit(-1) + end + + # Drop command from list of arguments + Open3.popen2e(exe_name, *args[1..-1]) do |_in, out_err, wait_thr| + begin + out_err.each do |line| + print line + end + exit(wait_thr.value.exitstatus) + rescue Interrupt => e + print e.message + exit(-1) + end + end + end +end diff --git a/src/ign.cc b/src/cmd/ign.cc similarity index 75% rename from src/ign.cc rename to src/cmd/ign.cc index c8fdc2f6..ce80f9cd 100644 --- a/src/ign.cc +++ b/src/cmd/ign.cc @@ -19,29 +19,28 @@ #include "ignition/launch/config.hh" #include "ign.hh" -#include "Manager.hh" +#include "../Manager.hh" ////////////////////////////////////////////////// -extern "C" IGNITION_LAUNCH_VISIBLE char *ignitionVersion() +extern "C" char *ignitionVersion() { return strdup(IGNITION_LAUNCH_VERSION_FULL); } ////////////////////////////////////////////////// -extern "C" IGNITION_LAUNCH_VISIBLE const char *configPath() +extern "C" const char *configPath() { return IGNITION_LAUNCH_INITIAL_CONFIG_PATH; } ////////////////////////////////////////////////// -extern "C" IGNITION_LAUNCH_VISIBLE void cmdVerbosity( - const char *_verbosity) +extern "C" void cmdVerbosity(const int _verbosity) { - ignition::common::Console::SetVerbosity(std::atoi(_verbosity)); + ignition::common::Console::SetVerbosity(_verbosity); } ////////////////////////////////////////////////// -extern "C" IGNITION_LAUNCH_VISIBLE int run(const char *_config) +extern "C" int run(const char *_config) { ignition::launch::Manager mgr; return mgr.RunConfig(_config); diff --git a/src/ign.hh b/src/cmd/ign.hh similarity index 83% rename from src/ign.hh rename to src/cmd/ign.hh index e35d923e..e5c99133 100644 --- a/src/ign.hh +++ b/src/cmd/ign.hh @@ -21,17 +21,17 @@ /// \brief External hook to read the library version. /// \return C-string representing the version. Ex.: 0.1.2 -extern "C" IGNITION_LAUNCH_VISIBLE char *ignitionVersion(); +extern "C" char *ignitionVersion(); /// \brief Set verbosity level /// \param[in] _verbosity 0 to 4 -extern "C" IGNITION_LAUNCH_VISIBLE void cmdVerbosity( - const char *_verbosity); +extern "C" void cmdVerbosity( + const int _verbosity); /// \brief External hook to execute 'ign fuel list -t model' from the command /// line. /// \param[in] _config Config file to run. /// \return 1 if successful, 0 if not. -extern "C" IGNITION_LAUNCH_VISIBLE int run(const char *_config); +extern "C" int run(const char *_config); #endif diff --git a/src/ign_TEST.cc b/src/cmd/ign_TEST.cc similarity index 67% rename from src/ign_TEST.cc rename to src/cmd/ign_TEST.cc index a9af15e9..67164719 100644 --- a/src/ign_TEST.cc +++ b/src/cmd/ign_TEST.cc @@ -21,13 +21,8 @@ #include -#include #include "ignition/launch/test_config.hh" // NOLINT(build/include) -static const std::string kIgnCommand( - std::string("IGN_CONFIG_PATH=") + IGN_CONFIG_PATH + " " + - std::string(BREW_RUBY) + std::string(IGN_PATH) + " launch "); - ///////////////////////////////////////////////// std::string customExecStr(std::string _cmd) { @@ -53,8 +48,8 @@ std::string customExecStr(std::string _cmd) ///////////////////////////////////////////////// TEST(CmdLine, Ls) { - std::string cmd = kIgnCommand + - std::string(PROJECT_SOURCE_PATH) + "/test/config/ls.ign"; + std::string cmd = std::string("IGN_CONFIG_PATH=") + IGN_CONFIG_PATH + + " ign launch " + std::string(PROJECT_SOURCE_PATH) + "/test/config/ls.ign"; std::cout << "Running command [" << cmd << "]" << std::endl; @@ -70,7 +65,8 @@ TEST(CmdLine, EchoSelf) std::string filePath = std::string(PROJECT_SOURCE_PATH) + "/test/config/echo.ign"; - std::string cmd = kIgnCommand + filePath; + std::string cmd = std::string("IGN_CONFIG_PATH=") + IGN_CONFIG_PATH + + " ign launch " + filePath; std::string output = customExecStr(cmd); EXPECT_EQ(filePath, output) << output; @@ -106,3 +102,40 @@ TEST(CmdLine, HelpVsCompletionFlags) EXPECT_NE(std::string::npos, helpOutput.find(flag)) << helpOutput; } } + +///////////////////////////////////////////////// +TEST(CmdLine, HelpSelf) +{ + std::string cmd = std::string("IGN_CONFIG_PATH=") + IGN_CONFIG_PATH + + " ign launch --help"; + + std::string output = customExecStr(cmd); + EXPECT_NE(std::string::npos, + output.find("Introspect Ignition launch")) << output; +} + +///////////////////////////////////////////////// +TEST(CmdLine, EchoErb) +{ + std::string filePath = + std::string(PROJECT_SOURCE_PATH) + "/test/config/erb.ign"; + + std::string cmd = std::string("IGN_CONFIG_PATH=") + IGN_CONFIG_PATH + + " ign launch " + filePath + " testVar:=erb1234"; + + std::string output = customExecStr(cmd); + EXPECT_EQ("erb1234", output) << output; +} + +///////////////////////////////////////////////// +TEST(CmdLine, EchoBadErb) +{ + std::string filePath = + std::string(PROJECT_SOURCE_PATH) + "/test/config/erb.ign"; + + std::string cmd = std::string("IGN_CONFIG_PATH=") + IGN_CONFIG_PATH + + " ign launch " + filePath + " badargument"; + + std::string output = customExecStr(cmd); + EXPECT_NE(std::string::npos, output.find("is wrong for erb")) << output; +} diff --git a/src/launch.yaml.in b/src/cmd/launch.yaml.in similarity index 100% rename from src/launch.yaml.in rename to src/cmd/launch.yaml.in diff --git a/src/cmd/launch_main.cc b/src/cmd/launch_main.cc new file mode 100644 index 00000000..6327432d --- /dev/null +++ b/src/cmd/launch_main.cc @@ -0,0 +1,141 @@ + +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * 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 "ignition/launch/config.hh" +#include "ign.hh" + + +///////////////////////////////////////////////// +std::string erbExec(std::string _cmd) +{ + _cmd += " 2>&1"; + FILE *pipe = popen(_cmd.c_str(), "r"); + + if (!pipe) + return "ERROR"; + + char buffer[128]; + std::string result = ""; + + while (!feof(pipe)) + { + if (fgets(buffer, 128, pipe) != nullptr) + result += buffer; + } + + pclose(pipe); + return result; +} + +////////////////////////////////////////////////// +/// \brief Enumeration of available commands +enum class LaunchCommand +{ + kNone, +}; + +////////////////////////////////////////////////// +/// \brief Structure to hold all available topic options +struct LaunchOptions +{ + /// \brief Command to execute + LaunchCommand command{LaunchCommand::kNone}; + + std::string launchfile; + + std::vector more_comms; + + int verboseLevel = 1; +}; + +void runLaunchCommand(const LaunchOptions &_opt) +{ + cmdVerbosity(_opt.verboseLevel); + + if (!_opt.launchfile.empty()) + { + if (!ignition::common::isFile(_opt.launchfile)) + { + ignerr << "File [" + _opt.launchfile + "] does not exists" + << std::endl; + exit(-1); + } + + std::string cmd = "erb -v "; + for (auto & arg : _opt.more_comms) + { + auto tokens = ignition::common::split(arg, ":="); + if (tokens.size() == 2) + { + cmd += " " + tokens[0] + "=" + tokens[1]; + } + else + { + ignerr << "This argument [" << arg << "] is wrong for erb" + << std::endl; + exit(1); + } + } + cmd += " " + _opt.launchfile; + std::string config = erbExec(cmd); + run(config.c_str()); + return; + } + + if (_opt.command == LaunchCommand::kNone) + { + // In the event that there is no command, display help + throw CLI::CallForHelp(); + } +} + +void addLaunchFlags(CLI::App &_app) +{ + auto opt = std::make_shared(); + + _app.add_option("-v,--verbose", + opt->verboseLevel, + "Verbose level"); + _app.add_option("launch", opt->launchfile, "launch_file")->take_last(); + _app.allow_extras(); + _app.callback([&_app, opt](){ + opt->more_comms = _app.remaining(); + runLaunchCommand(*opt); + }); +} + +////////////////////////////////////////////////// +int main(int argc, char** argv) +{ + CLI::App app{"Introspect Ignition launch"}; + + app.set_help_all_flag("--help-all", "Show all help"); + + app.add_flag_callback("--version", [](){ + std::cout << ignitionVersion() << std::endl; + throw CLI::Success(); + }); + + addLaunchFlags(app); + CLI11_PARSE(app, argc, argv); +} diff --git a/src/cmdlaunch.rb.in b/src/cmdlaunch.rb.in deleted file mode 100755 index 45f1b005..00000000 --- a/src/cmdlaunch.rb.in +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/ruby - -# Copyright (C) 2019 Open Source Robotics Foundation -# -# 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. - -# We use 'dl' for Ruby <= 1.9.x and 'fiddle' for Ruby >= 2.0.x -if RUBY_VERSION.split('.')[0] < '2' - require 'dl' - require 'dl/import' - include DL -else - require 'fiddle' - require 'fiddle/import' - include Fiddle -end - -require 'optparse' -require 'erb' - -# Constants. -LIBRARY_NAME = '@IGN_LIBRARY_NAME@' -LIBRARY_VERSION = '@PROJECT_VERSION_FULL@' - -COMMON_OPTIONS = - " -h [--help] Print this help message.\n"\ - " \n" + - " --force-version Use a specific library version.\n"\ - " \n" + - ' --versions Show the available versions.' - -COMMANDS = { 'launch' => - "Manage executables and plugins. \n"\ - " \n"\ - " ign launch [options] [launch_file] \n"\ - " \n"\ - " \n"\ - "Available Options: \n"\ - " -v [ --verbose ] [arg] Adjust the level of console output (0~4). \n"\ - " The default verbosity is 1, use -v without \n"\ - " arguments for level 3. \n" + - COMMON_OPTIONS -} - -# -# Class for the Ignition Fuel command line tools. -# -class Cmd - # Command-line variable bindings. - @variableBinding - - # Initialize the class - def initialize() - @variableBinding = binding - end - - # - # Return a structure describing the options. - # - def parse(args) - options = { - 'verbose' => '1', - } - - usage = COMMANDS[args[0]] - - opt_parser = OptionParser.new do |opts| - opts.banner = usage - - opts.on('-h', '--help') do - puts usage - exit - end - opts.on('-v [verbose]', '--verbose [verbose]', String, - 'Adjust level of console output') do |v| - options['verbose'] = v || '3' - end - end # opt_parser do - - opt_parser.parse!(args) - - while !args.empty? - arg = args.shift - # Store variables if the := is present - if arg.include?(":=") - name, value = arg.split(/:=/) - - # Make sure the name is present. It's okay if the value is empty or - # nil, in case the user wants to explicity clear a variable. - if name != nil && !name.empty? - @variableBinding.local_variable_set("#{name}", value) - else - puts "Missing varialbe name in argument: #{arg}" - end - - # Launch file as positional argument - elsif arg and arg != 'launch' and not options.key?('file') - options['file'] = arg - # Store the command - elsif not options.key?('command') - options['command'] = arg - else - puts "Error processing command line argument: #{arg}" - end - end - - options - end # parse() - - def execute(args) - options = parse(args) - - # Read the plugin that handles the command. - plugin = LIBRARY_NAME - conf_version = LIBRARY_VERSION - - begin - Importer.dlload plugin - rescue DLError - puts "Library error: [#{plugin}] not found." - exit(-1) - end - - # Read the library version. - Importer.extern 'char* ignitionVersion()' - begin - plugin_version = Importer.ignitionVersion.to_s - rescue DLError - puts "Library error: Problem running 'ignitionVersion()' from #{plugin}." - exit(-1) - end - - # Sanity check: Verify that the version of the yaml file matches the version - # of the library that we are using. - unless plugin_version.eql? conf_version - puts "Error: Version mismatch. Your configuration file version is - [#{conf_version}] but #{plugin} version is [#{plugin_version}]." - exit(-1) - end - - usage = COMMANDS[args[0]] - - begin - - # Global configurations - if options.key?('verbose') - Importer.extern 'void cmdVerbosity(const char *)' - Importer.cmdVerbosity(options['verbose']) - end - - if options.key?('file') - # Check if the passed in file exists. - path = '' - if File.exists?(options['file']) - path = options['file'] - end - # If not, then first check the IGN_LAUNCH_CONFIG_PATH environment - # variable, then the configuration path from the launch library. - if path.empty? - configPathEnv = ENV['IGN_LAUNCH_CONFIG_PATH'] - if !configPathEnv.nil? - configPaths = configPathEnv.split(File::PATH_SEPARATOR) - for configPath in configPaths - filePath = File.join(configPath, options['file']) - if File.exists?(filePath) - path = filePath - break - end - end - end - end - # get the configuration path from the launch library. - if path.empty? - Importer.extern 'char *configPath()' - path = File.join(Importer.configPath().to_s, options['file']) - end - if path.empty? or !File.exists?(path) - puts "Unable to find file " + options['file'] - exit(-1) - end - - # ERB parse the file with the variable bindings - begin - erb = ERB.new(File.read(path)) - erb.filename = path - parsed = erb.result(@variableBinding) - - # todo(nkoenig) Also ERB parse elements inside - # a launch configuration. This will allow use to pass variables - # all the way down through the world and (eventually) model files. - # An approach would be to find the tags using a Ruby XML - # parser, and ERB each file. The tag would be - # changed to something like . We would probably need - # a helper function to find the location on disk of the - # . - rescue Exception => e - puts "Failed to parse #{path} because of #{e}" - exit(-1) - end - - # Run the parsed file. - Importer.extern 'int run(const char *)' - if not Importer.run(parsed) - exit(-1) - end - else - puts usage - end - rescue - puts "Library error: Problem running [#{options['command']}]() "\ - "from @IGN_LIBRARY_NAME@." - end # begin - end # execute -end # class diff --git a/test/config/erb.ign b/test/config/erb.ign new file mode 100644 index 00000000..d7d6f8e1 --- /dev/null +++ b/test/config/erb.ign @@ -0,0 +1,12 @@ + +<% + # Check if testVar is not defined or is empty/nil + if !defined?(testVar) || testVar == nil || testVar.empty? + testVar = "" + end +%> + + + echo -n <%= testVar %> + +