From 6d3482f89105717bb275d9035f1b5e2274a73618 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Sat, 28 Nov 2020 23:18:54 -0800 Subject: [PATCH 01/11] Add `ign plugin --info` to print plugin info Given a library file, `ign plugin --info` will print the names of plugins exported within that library and the interfaces exposed. The --verbose flag can provide extra information. Signed-off-by: Steve Peters --- loader/CMakeLists.txt | 6 ++ loader/conf/CMakeLists.txt | 23 +++++ loader/conf/plugin.yaml.in | 8 ++ loader/src/CMakeLists.txt | 4 + loader/src/cmd/CMakeLists.txt | 44 ++++++++ loader/src/cmd/cmdplugin.rb.in | 177 +++++++++++++++++++++++++++++++++ loader/src/ign.cc | 79 +++++++++++++++ 7 files changed, 341 insertions(+) create mode 100644 loader/conf/CMakeLists.txt create mode 100644 loader/conf/plugin.yaml.in create mode 100644 loader/src/CMakeLists.txt create mode 100644 loader/src/cmd/CMakeLists.txt create mode 100644 loader/src/cmd/cmdplugin.rb.in create mode 100644 loader/src/ign.cc diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 82f5436d..8e43e92b 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -34,3 +34,9 @@ endforeach() install( DIRECTORY include/ DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) + +#============================================================================ +# ign command line support +#============================================================================ +add_subdirectory(conf) +add_subdirectory(src) diff --git a/loader/conf/CMakeLists.txt b/loader/conf/CMakeLists.txt new file mode 100644 index 00000000..6e988372 --- /dev/null +++ b/loader/conf/CMakeLists.txt @@ -0,0 +1,23 @@ +# Used only for internal testing. +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: plugin1.yaml +configure_file( + "${IGN_DESIGNATION}.yaml.in" + "${CMAKE_BINARY_DIR}/test/conf/${IGN_DESIGNATION}${PROJECT_VERSION_MAJOR}.yaml" @ONLY) + +# 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: plugin1.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/) diff --git a/loader/conf/plugin.yaml.in b/loader/conf/plugin.yaml.in new file mode 100644 index 00000000..b27dccf3 --- /dev/null +++ b/loader/conf/plugin.yaml.in @@ -0,0 +1,8 @@ +--- # Subcommands available inside ignition-transport. +format: 1.0.0 +library_name: @PROJECT_NAME_NO_VERSION@ +library_version: @PROJECT_VERSION_FULL@ +library_path: @ign_library_path@ +commands: + - plugin : Print information about plugins. +--- diff --git a/loader/src/CMakeLists.txt b/loader/src/CMakeLists.txt new file mode 100644 index 00000000..eb84c64c --- /dev/null +++ b/loader/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# Command line support. +if(NOT WIN32) + add_subdirectory(cmd) +endif() diff --git a/loader/src/cmd/CMakeLists.txt b/loader/src/cmd/CMakeLists.txt new file mode 100644 index 00000000..d5e0a2ff --- /dev/null +++ b/loader/src/cmd/CMakeLists.txt @@ -0,0 +1,44 @@ +#=============================================================================== +# Generate the ruby script for internal testing. +# Note that the major version of the library is included in the name. +# Ex: cmdplugin1.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 "${cmd_script_generated_test}.configured") + +# Set the library_location variable to the full path of the library file within +# the build directory. +set(library_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: cmdplugin1.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(library_location "../../../${CMAKE_INSTALL_LIBDIR}/$") + +configure_file( + "cmd${IGN_DESIGNATION}.rb.in" + "${cmd_script_configured}" + @ONLY) + +file(GENERATE + OUTPUT "${cmd_script_generated}" + INPUT "${cmd_script_configured}") + +# Install the ruby command line library in an unversioned location. +install(FILES ${cmd_script_generated} DESTINATION lib/ruby/ignition) diff --git a/loader/src/cmd/cmdplugin.rb.in b/loader/src/cmd/cmdplugin.rb.in new file mode 100644 index 00000000..e2b7dc23 --- /dev/null +++ b/loader/src/cmd/cmdplugin.rb.in @@ -0,0 +1,177 @@ +#!/usr/bin/ruby + +# Copyright (C) 2020 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' + +# Constants. +LIBRARY_NAME = '@library_location@' +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 = { 'plugin' => + "Print information about plugins.\n\n" + + " ign plugin [options]\n\n" + + "Options:\n\n" + + " -i [ --info ] Get info about a plugin.\n" + + " Requires the -p option.\n" + + "\n" + + " -p [ --plugin ] arg Name of a plugin.\n" + + " Required with -i.\n" + + "\n" + + " -v [ --verbose ] Print verbose info.\n" + + "\n" + + COMMON_OPTIONS + } + +# +# Class for the Ignition plugin command line tools. +# +class Cmd + # + # Return a structure describing the options. + # + def parse(args) + options = {} + + usage = COMMANDS[args[0]] + + # Read the command line arguments. + opt_parser = OptionParser.new do |opts| + opts.banner = usage + + opts.on('-h', '--help', 'Print this help message') do + puts usage + exit(0) + end + + opts.on('-i', '--info', String, + 'Print information about a plugin') do |t| + options['info'] = t + end + + opts.on('-p plugin', '--plugin', String, + 'Plugin name') do |t| + options['plugin'] = t + end + + options["verbose"] = 0 + opts.on('-v', '--verbose', 'Print verbose info') do + options["verbose"] = 1 + end + + end + begin + opt_parser.parse!(args) + rescue + puts usage + exit(-1) + end + + # Check that there is at least one command and there is a plugin that knows + # how to handle it. + if ARGV.empty? || !COMMANDS.key?(ARGV[0]) || + options.empty? + puts usage + exit(-1) + end + + options['command'] = ARGV[0] + + options + end # parse() + + def execute(args) + options = parse(args) + + # puts 'Parsed:' + # puts options + + # Read the plugin that handles the command. + if LIBRARY_NAME[0] == '/' + # If the first character is a slash, we'll assume that we've been given an + # absolute path to the library. This is only used during test mode. + plugin = LIBRARY_NAME + else + # We're assuming that the library path is relative to the current + # location of this script. + plugin = File.expand_path(File.join(File.dirname(__FILE__), LIBRARY_NAME)) + end + 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 + + begin + case options['command'] + when 'plugin' + if options.key?('info') + if not options.key?('plugin') + puts 'ign plugin --info: missing plugin name (-p )' + puts 'Try ign plugin --help' + else + Importer.extern 'void cmdPluginInfo(const char *, int)' + Importer.cmdPluginInfo(options['plugin'], options["verbose"]) + end + else + puts 'Command error: I do not have an implementation '\ + 'for this command.' + end + else + puts 'Command error: I do not have an implementation for '\ + "command [ign #{options['command']}]." + end + rescue + puts "Library error: Problem running [#{options['command']}]() "\ + "from #{plugin}." + end + end +end diff --git a/loader/src/ign.cc b/loader/src/ign.cc new file mode 100644 index 00000000..7f17739c --- /dev/null +++ b/loader/src/ign.cc @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 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 "ignition/plugin/Loader.hh" +#include "ignition/plugin/config.hh" + +using namespace ignition; +using namespace plugin; + +////////////////////////////////////////////////// +extern "C" void IGNITION_PLUGIN_LOADER_VISIBLE cmdPluginInfo( + const char *_plugin, int _verbose) +{ + if (!_plugin || std::string(_plugin).empty()) + { + std::cerr << "Invalid plugin file name. Plugin name must not be empty.\n"; + return; + } + + ignition::plugin::Loader pl; + std::cout << "Loading plugin library file [" << _plugin << "]\n"; + + // Print names of plugins exported by library file + std::unordered_set pluginNames = pl.LoadLib(_plugin); + + if (_verbose) + { + std::cout << pl.PrettyStr() << std::endl; + return; + } + + std::cout << "* Found " << pluginNames.size() << " plugin"; + if (pluginNames.size() != 1u) + { + std::cout << 's'; + } + std::cout << " in library file:" << std::endl; + + for (const auto & pluginName : pluginNames) + { + std::cout << " - " << pluginName << std::endl; + } + + auto interfacesImplemented = pl.InterfacesImplemented(); + std::cout << "* Found " << interfacesImplemented.size() << " interface"; + if (interfacesImplemented.size() != 1u) + { + std::cout << 's'; + } + std::cout << " in library file:" << std::endl; + + for (const auto & interfaceImplemented : interfacesImplemented) + { + std::cout << " - " << interfaceImplemented << std::endl; + } +} + +////////////////////////////////////////////////// +extern "C" const char IGNITION_PLUGIN_LOADER_VISIBLE *ignitionVersion() +{ + return IGNITION_PLUGIN_VERSION_FULL; +} From 5b011fff3522aeb30ac22e9574215d46fd11f2de Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 30 Nov 2020 00:21:59 -0800 Subject: [PATCH 02/11] Add test for `ign plugin --info` Signed-off-by: Steve Peters --- CMakeLists.txt | 5 ++ loader/CMakeLists.txt | 19 +++++ loader/src/ign_TEST.cc | 185 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 loader/src/ign_TEST.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index f904eeef..04fa34b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,11 @@ ign_find_package(DL PRETTY libdl PURPOSE "Required for loading plugins") +#-------------------------------------- +# Find ignition-tools +ign_find_package(ignition-tools QUIET) + + #============================================================================ # Configure the build #============================================================================ diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 8e43e92b..a07d17ff 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -3,6 +3,11 @@ # "tests" variable ign_get_libsources_and_unittests(sources tests) +# Disable ign_TEST if ignition-tools is not found +if (NOT IGNITION-TOOLS_BINARY_DIRS) + list(REMOVE_ITEM gtest_sources ign_TEST.cc) +endif() + # Create the library target ign_add_component(loader SOURCES ${sources} @@ -29,8 +34,22 @@ foreach(test ${test_targets}) target_compile_definitions(${test} PRIVATE "IGNDummyPlugins_LIB=\"$\"") + target_compile_definitions(${test} PRIVATE + "IGN_PATH=\"${IGNITION-TOOLS_BINARY_DIRS}\"") + + target_compile_definitions(${test} PRIVATE + "IGN_VERSION_FULL=\"${PROJECT_VERSION_FULL}\"") + endforeach() +if(TARGET UNIT_ign_TEST) + set(_env_vars) + list(APPEND _env_vars "IGN_CONFIG_PATH=${CMAKE_BINARY_DIR}/test/conf") + + set_tests_properties(UNIT_ign_TEST PROPERTIES + ENVIRONMENT "${_env_vars}") +endif() + install( DIRECTORY include/ DESTINATION ${IGN_INCLUDE_INSTALL_DIR_FULL}) diff --git a/loader/src/ign_TEST.cc b/loader/src/ign_TEST.cc new file mode 100644 index 00000000..07285497 --- /dev/null +++ b/loader/src/ign_TEST.cc @@ -0,0 +1,185 @@ +/* + * 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. + * +*/ + +#include +#include + +#include "gtest/gtest.h" +#include "ignition/plugin/Loader.hh" + +#ifdef _MSC_VER +# define popen _popen +# define pclose _pclose +#endif + +using namespace ignition; + +static const std::string g_ignVersion("--force-version " + // NOLINT(*) + std::string(IGN_VERSION_FULL)); + +///////////////////////////////////////////////// +std::string custom_exec_str(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) != NULL) + result += buffer; + } + + pclose(pipe); + return result; +} + +////////////////////////////////////////////////// +/// \brief Check 'ign plugin --info' for a non-existent file. +TEST(ignTest, PluginInfoNonexistentLibrary) +{ + // Path to ign executable + std::string ign = std::string(IGN_PATH) + "/ign"; + + std::string output = custom_exec_str(ign + " plugin --info --plugin " + + "/path/to/libDoesNotExist.so"); + + EXPECT_NE(std::string::npos, output.find("Error while loading the library")) + << output; + EXPECT_NE(std::string::npos, output.find("Found 0 plugins in library file")) + << output; + EXPECT_NE(std::string::npos, output.find("Found 0 interfaces in library")) + << output; +} + +////////////////////////////////////////////////// +/// \brief Check 'ign plugin --info' for a file that isn't a shared library. +TEST(ignTest, PluginInfoNonLibrary) +{ + // Path to ign executable + std::string ign = std::string(IGN_PATH) + "/ign"; + + std::string output = custom_exec_str(ign + " plugin --info --plugin " + + std::string(IGN_PLUGIN_SOURCE_DIR) + "/core/src/Plugin.cc"); + + EXPECT_NE(std::string::npos, output.find("Error while loading the library")) + << output; + EXPECT_NE(std::string::npos, output.find("Found 0 plugins in library file")) + << output; + EXPECT_NE(std::string::npos, output.find("Found 0 interfaces in library")) + << output; +} + +////////////////////////////////////////////////// +/// \brief Check 'ign plugin --info' for a library that has no plugins. +TEST(ignTest, PluginInfoNonPluginLibrary) +{ + // Path to ign executable + std::string ign = std::string(IGN_PATH) + "/ign"; + + std::string output = custom_exec_str(ign + " plugin --info --plugin " + + IGN_PLUGIN_LIB); + + EXPECT_NE(std::string::npos, output.find("does not export any plugins. The " + "symbol [IgnitionPluginHook] is missing, or it is not externally visible.")) + << output; + EXPECT_NE(std::string::npos, output.find("Found 0 plugins in library file")) + << output; + EXPECT_NE(std::string::npos, output.find("Found 0 interfaces in library")) + << output; +} + +////////////////////////////////////////////////// +/// \brief Check 'ign plugin --info' for a library with plugins. +TEST(ignTest, PluginInfoDummyPlugins) +{ + // Path to ign executable + std::string ign = std::string(IGN_PATH) + "/ign"; + + std::string output = custom_exec_str(ign + " plugin --info --plugin " + + IGNDummyPlugins_LIB); + + EXPECT_NE(std::string::npos, output.find("Found 3 plugins in library file")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyMultiPlugin")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyNoAliasPlugin")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummySinglePlugin")) + << output; + + EXPECT_NE(std::string::npos, output.find("Found 7 interfaces in library")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyNameBase")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyGetObjectBase")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyIntBase")) + << output; + EXPECT_NE(std::string::npos, + output.find("test::util::DummyGetPluginInstancePtr")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyDoubleBase")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummySetterBase")) + << output; + EXPECT_NE(std::string::npos, + output.find("ignition::plugin::EnablePluginFromThis")) + << output; +} + +////////////////////////////////////////////////// +/// \brief Check 'ign plugin --info' with verbose output. +TEST(ignTest, PluginInfoVerboseDummyPlugins) +{ + // Path to ign executable + std::string ign = std::string(IGN_PATH) + "/ign"; + + std::string output = custom_exec_str(ign + " plugin --info --plugin " + + IGNDummyPlugins_LIB + " --verbose"); + + EXPECT_NE(std::string::npos, output.find("Known Interfaces: 7")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyNameBase")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyGetObjectBase")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyIntBase")) + << output; + EXPECT_NE(std::string::npos, + output.find("test::util::DummyGetPluginInstancePtr")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummyDoubleBase")) + << output; + EXPECT_NE(std::string::npos, output.find("test::util::DummySetterBase")) + << output; + EXPECT_NE(std::string::npos, + output.find("ignition::plugin::EnablePluginFromThis")) + << output; + + EXPECT_NE(std::string::npos, output.find("Known Plugins: 3")) + << output; + + EXPECT_NE(std::string::npos, + output.find("There are 2 aliases with a name collision")) + << output; +} From 8a1b9cfb390eac75d733be1dac86cca4ebbc110c Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 30 Nov 2020 01:01:12 -0800 Subject: [PATCH 03/11] Add libignition-tools-dev to packages.apt Signed-off-by: Steve Peters --- .github/ci/packages.apt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ci/packages.apt b/.github/ci/packages.apt index ee689d74..e222fd3d 100644 --- a/.github/ci/packages.apt +++ b/.github/ci/packages.apt @@ -1 +1,2 @@ libignition-cmake2-dev +libignition-tools-dev From c716c4b08f6bd7dfc25e0a7c6b970a0383d6190f Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 30 Nov 2020 16:23:59 -0800 Subject: [PATCH 04/11] Disable ign_TEST on windows Also follow suggestions from review comments. Signed-off-by: Steve Peters --- loader/CMakeLists.txt | 2 +- loader/conf/plugin.yaml.in | 2 +- loader/src/CMakeLists.txt | 4 +--- loader/src/cmd/cmdplugin.rb.in | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index a07d17ff..32bd080c 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -4,7 +4,7 @@ ign_get_libsources_and_unittests(sources tests) # Disable ign_TEST if ignition-tools is not found -if (NOT IGNITION-TOOLS_BINARY_DIRS) +if (WIN32 OR NOT IGNITION-TOOLS_BINARY_DIRS) list(REMOVE_ITEM gtest_sources ign_TEST.cc) endif() diff --git a/loader/conf/plugin.yaml.in b/loader/conf/plugin.yaml.in index b27dccf3..f878d39c 100644 --- a/loader/conf/plugin.yaml.in +++ b/loader/conf/plugin.yaml.in @@ -1,4 +1,4 @@ ---- # Subcommands available inside ignition-transport. +--- # Subcommands available inside ignition-plugin. format: 1.0.0 library_name: @PROJECT_NAME_NO_VERSION@ library_version: @PROJECT_VERSION_FULL@ diff --git a/loader/src/CMakeLists.txt b/loader/src/CMakeLists.txt index eb84c64c..f880e721 100644 --- a/loader/src/CMakeLists.txt +++ b/loader/src/CMakeLists.txt @@ -1,4 +1,2 @@ # Command line support. -if(NOT WIN32) - add_subdirectory(cmd) -endif() +add_subdirectory(cmd) diff --git a/loader/src/cmd/cmdplugin.rb.in b/loader/src/cmd/cmdplugin.rb.in index e2b7dc23..42f8eb02 100644 --- a/loader/src/cmd/cmdplugin.rb.in +++ b/loader/src/cmd/cmdplugin.rb.in @@ -43,7 +43,7 @@ COMMANDS = { 'plugin' => " -i [ --info ] Get info about a plugin.\n" + " Requires the -p option.\n" + "\n" + - " -p [ --plugin ] arg Name of a plugin.\n" + + " -p [ --plugin ] arg Path to a plugin.\n" + " Required with -i.\n" + "\n" + " -v [ --verbose ] Print verbose info.\n" + From 59f53e77a2188a538fe4cbd649064180bc129216 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 30 Nov 2020 16:38:00 -0800 Subject: [PATCH 05/11] Actually disable test on MSVC Signed-off-by: Steve Peters --- loader/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 32bd080c..6bee7cc9 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -4,7 +4,7 @@ ign_get_libsources_and_unittests(sources tests) # Disable ign_TEST if ignition-tools is not found -if (WIN32 OR NOT IGNITION-TOOLS_BINARY_DIRS) +if (MSVC OR NOT IGNITION-TOOLS_BINARY_DIRS) list(REMOVE_ITEM gtest_sources ign_TEST.cc) endif() From 2c6c5e5d4853af54bda80d50e666fb01694afa06 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 30 Nov 2020 22:46:39 -0800 Subject: [PATCH 06/11] fix ign_TEST.cc path Signed-off-by: Steve Peters --- loader/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 6bee7cc9..f276fdd9 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -2,10 +2,10 @@ # Collect source files into the "sources" variable and unit test files into the # "tests" variable ign_get_libsources_and_unittests(sources tests) - +message(STATUS "tests ${tests}") # Disable ign_TEST if ignition-tools is not found if (MSVC OR NOT IGNITION-TOOLS_BINARY_DIRS) - list(REMOVE_ITEM gtest_sources ign_TEST.cc) + list(REMOVE_ITEM gtest_sources src/ign_TEST.cc) endif() # Create the library target From c36472210fc7229edfd1b0e71c6be8f97ace146b Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 30 Nov 2020 22:54:09 -0800 Subject: [PATCH 07/11] fix variable name Signed-off-by: Steve Peters --- loader/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index f276fdd9..30d4c8cd 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -2,10 +2,10 @@ # Collect source files into the "sources" variable and unit test files into the # "tests" variable ign_get_libsources_and_unittests(sources tests) -message(STATUS "tests ${tests}") + # Disable ign_TEST if ignition-tools is not found if (MSVC OR NOT IGNITION-TOOLS_BINARY_DIRS) - list(REMOVE_ITEM gtest_sources src/ign_TEST.cc) + list(REMOVE_ITEM tests src/ign_TEST.cc) endif() # Create the library target From f138e5262f9c1807269c84680c086547b43bbef6 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Fri, 4 Dec 2020 15:08:25 -0800 Subject: [PATCH 08/11] use installed loader library Signed-off-by: Steve Peters --- loader/src/cmd/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/cmd/CMakeLists.txt b/loader/src/cmd/CMakeLists.txt index d5e0a2ff..63d52354 100644 --- a/loader/src/cmd/CMakeLists.txt +++ b/loader/src/cmd/CMakeLists.txt @@ -29,7 +29,7 @@ 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(library_location "../../../${CMAKE_INSTALL_LIBDIR}/$") +set(library_location "../../../${CMAKE_INSTALL_LIBDIR}/$") configure_file( "cmd${IGN_DESIGNATION}.rb.in" From d81240e0e25ecd6e67e73ba938a6687f6b842d17 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Fri, 4 Dec 2020 15:27:12 -0800 Subject: [PATCH 09/11] Fix options so `ign plugin` displays help message Signed-off-by: Steve Peters --- loader/src/cmd/cmdplugin.rb.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/cmd/cmdplugin.rb.in b/loader/src/cmd/cmdplugin.rb.in index 42f8eb02..58c1c0c0 100644 --- a/loader/src/cmd/cmdplugin.rb.in +++ b/loader/src/cmd/cmdplugin.rb.in @@ -82,7 +82,6 @@ class Cmd options['plugin'] = t end - options["verbose"] = 0 opts.on('-v', '--verbose', 'Print verbose info') do options["verbose"] = 1 end @@ -158,6 +157,7 @@ class Cmd puts 'ign plugin --info: missing plugin name (-p )' puts 'Try ign plugin --help' else + options["verbose"] = 0 if !options.key?('verbose') Importer.extern 'void cmdPluginInfo(const char *, int)' Importer.cmdPluginInfo(options['plugin'], options["verbose"]) end From 92593cefa4d294caf27dad16ec89e065c34f5433 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Fri, 4 Dec 2020 18:45:17 -0800 Subject: [PATCH 10/11] Recommend workaround if dylib fails to load There are some issues with loading plugins from `ign` when run with /usr/bin/ruby on macOS due to System Integrity Protection. If a plugin ending in ".dylib" fails to load, print a workaround suggestion using ruby from brew. Signed-off-by: Steve Peters --- loader/src/cmd/cmdplugin.rb.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/loader/src/cmd/cmdplugin.rb.in b/loader/src/cmd/cmdplugin.rb.in index 58c1c0c0..d4b5c682 100644 --- a/loader/src/cmd/cmdplugin.rb.in +++ b/loader/src/cmd/cmdplugin.rb.in @@ -129,6 +129,14 @@ class Cmd Importer.dlload plugin rescue DLError puts "Library error: [#{plugin}] not found." + if plugin.end_with? ".dylib" + puts "If this script was executed with /usr/bin/ruby, this error may be caused by +macOS System Integrity Protection. One workaround is to use a different +version of ruby, for example: + brew install ruby +and add the following line to your shell profile: + export PATH=/usr/local/opt/ruby/bin:$PATH" + end exit(-1) end From 38fa3b1b801fd9408f8f1169b6614fa7ef7f4411 Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 7 Dec 2020 17:42:17 -0800 Subject: [PATCH 11/11] fix copyright date Signed-off-by: Steve Peters --- loader/src/ign_TEST.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/ign_TEST.cc b/loader/src/ign_TEST.cc index 07285497..eb97ed4b 100644 --- a/loader/src/ign_TEST.cc +++ b/loader/src/ign_TEST.cc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Open Source Robotics Foundation + * Copyright (C) 2020 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.