Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ign plugin --info to print plugin info #32

Merged
merged 12 commits into from
Feb 4, 2021
1 change: 1 addition & 0 deletions .github/ci/packages.apt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
libignition-cmake2-dev
libignition-tools-dev
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
#============================================================================
Expand Down
25 changes: 25 additions & 0 deletions loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
# "tests" variable
ign_get_libsources_and_unittests(sources tests)

# Disable ign_TEST if ignition-tools is not found
if (MSVC OR NOT IGNITION-TOOLS_BINARY_DIRS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we open a ticket to track command line support on Windows?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think gazebosim/gz-tools#7 will help with windows support eventually

list(REMOVE_ITEM tests src/ign_TEST.cc)
endif()

# Create the library target
ign_add_component(loader
SOURCES ${sources}
Expand All @@ -29,8 +34,28 @@ foreach(test ${test_targets})
target_compile_definitions(${test} PRIVATE
"IGNDummyPlugins_LIB=\"$<TARGET_FILE:IGNDummyPlugins>\"")

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})

#============================================================================
# ign command line support
#============================================================================
add_subdirectory(conf)
chapulina marked this conversation as resolved.
Show resolved Hide resolved
add_subdirectory(src)
23 changes: 23 additions & 0 deletions loader/conf/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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/)
8 changes: 8 additions & 0 deletions loader/conf/plugin.yaml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--- # Subcommands available inside ignition-plugin.
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.
---
2 changes: 2 additions & 0 deletions loader/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Command line support.
add_subdirectory(cmd)
44 changes: 44 additions & 0 deletions loader/src/cmd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 "$<TARGET_FILE:${loader}>")

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}/$<TARGET_FILE_NAME:${loader}>")

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)
185 changes: 185 additions & 0 deletions loader/src/cmd/cmdplugin.rb.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#!/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 <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 Path to 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

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."
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

# 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 <plugin>)'
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
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
Loading