Rework Cli, fix a couple Task items

This commit is contained in:
Josh Holtrop 2022-01-23 19:38:21 -05:00
parent 125ab4c171
commit 1b3e459ada
5 changed files with 175 additions and 152 deletions

View File

@ -3,5 +3,5 @@
require "rscons/cli"
if __FILE__ == $0
Rscons::Cli.run(ARGV)
Rscons::Cli.new.run(ARGV)
end

View File

@ -1,8 +1,154 @@
require "rscons"
require "optparse"
# CLI usage string.
USAGE = <<EOF
module Rscons
# Command-Line Interface functionality.
class Cli
# Default files to look for to execute if none specified.
DEFAULT_RSCONSCRIPTS = %w[Rsconscript Rsconscript.rb]
# Create an instance of the rscons command-line interpreter.
def initialize
@script = Script.new
end
# Run the Rscons CLI.
#
# @param argv [Array]
# Command-line parameters.
#
# @return [void]
def run(argv)
argv = argv.dup
begin
exit run_toplevel(argv)
rescue OptionParser::InvalidOption => io
$stderr.puts io.message
$stderr.puts usage
exit 2
end
end
private
def parse_task_options(task, argv)
end
def parse_tasks_and_options(argv)
tasks_and_options = []
while argv.size > 0
task = argv.shift
task_options = parse_task_options(task, argv)
tasks_and_options << [task, task_options]
end
tasks_and_options
end
def run_toplevel(argv)
rsconscript = nil
do_help = false
OptionParser.new do |opts|
opts.on("-b", "--build DIR") do |build_dir|
Rscons.application.build_dir = build_dir
end
opts.on("-f FILE") do |f|
rsconscript = f
end
opts.on("-F", "--show-failure") do
Rscons.application.show_failure
return 0
end
opts.on("-h", "--help") do
do_help = true
end
opts.on("-j NTHREADS") do |n_threads|
Rscons.application.n_threads = n_threads.to_i
end
opts.on("-r", "--color MODE") do |color_mode|
case color_mode
when "off"
Rscons.application.do_ansi_color = false
when "force"
Rscons.application.do_ansi_color = true
end
end
opts.on("-v", "--verbose") do
Rscons.application.verbose = true
end
opts.on("--version") do
puts "Rscons version #{Rscons::VERSION}"
return 0
end
end.order!(argv)
# Set vars before loading the build script so the build script can
# refer to them.
argv.each do |arg|
if arg =~ /^([^=]+)=(.*)$/
Rscons.application.vars[$1] = $2
end
end
# Find the build script.
if rsconscript
unless File.exists?(rsconscript)
$stderr.puts "Cannot read #{rsconscript}"
return 1
end
else
rsconscript = DEFAULT_RSCONSCRIPTS.find do |f|
File.exists?(f)
end
end
# Load the build script.
if rsconscript
@script.load(rsconscript)
end
# Do help after loading the build script (if found) so that any
# script-defined tasks and task options can be displayed.
if do_help
puts usage
return 0
end
# Anything else requires a build script, so complain if we didn't find
# one.
unless rsconscript
$stderr.puts "Could not find the Rsconscript to execute."
$stderr.puts "Looked for: #{DEFAULT_RSCONSCRIPTS.join(", ")}"
return 1
end
# Parse the rest of the command line. This is done after loading the
# build script so that script-defined tasks and task options can be
# taken into account.
tasks_and_params = parse_tasks_and_options(argv)
# If no user specified tasks, run "default" task.
if tasks_and_params.empty?
tasks_and_params << ["default"]
end
# Finally, with the script fully loaded and command-line parsed, run
# the application to execute all required tasks.
Rscons.application.run(@script, tasks_and_params)
end
def usage
usage = <<EOF
Usage: #{$0} [global options] [task] [task options]
Global options:
@ -17,136 +163,13 @@ Global options:
Tasks:
EOF
module Rscons
# Command-Line Interface functionality.
module Cli
# Default files to look for to execute if none specified.
DEFAULT_RSCONSCRIPTS = %w[Rsconscript Rsconscript.rb]
class << self
# Run the Rscons CLI.
#
# @param argv [Array]
# Command-line parameters.
#
# @return [void]
def run(argv)
argv = argv.dup
begin
exit run_toplevel(argv)
rescue OptionParser::InvalidOption => io
$stderr.puts io.message
$stderr.puts USAGE
exit 2
Task[].each do |name, task|
if task.desc
usage += %[ #{sprintf("%-27s", name)} #{task.desc}\n]
end
end
private
def parse_tasks_and_params(argv)
tasks_and_params = []
argv.each do |arg|
if arg.start_with?("-")
tasks_and_params[-1] << arg
else
tasks_and_params << [arg]
end
end
tasks_and_params
end
def run_toplevel(argv)
rsconscript = nil
do_help = false
OptionParser.new do |opts|
opts.on("-b", "--build DIR") do |build_dir|
Rscons.application.build_dir = build_dir
end
opts.on("-f FILE") do |f|
rsconscript = f
end
opts.on("-F", "--show-failure") do
Rscons.application.show_failure
exit 0
end
opts.on("-h", "--help") do
do_help = true
end
opts.on("-j NTHREADS") do |n_threads|
Rscons.application.n_threads = n_threads.to_i
end
opts.on("-r", "--color MODE") do |color_mode|
case color_mode
when "off"
Rscons.application.do_ansi_color = false
when "force"
Rscons.application.do_ansi_color = true
end
end
opts.on("-v", "--verbose") do
Rscons.application.verbose = true
end
opts.on("--version") do
puts "Rscons version #{Rscons::VERSION}"
exit 0
end
end.order!(argv)
tasks_and_params = parse_tasks_and_params(argv)
if tasks_and_params.empty?
tasks_and_params << ["default"]
end
argv.each do |arg|
if arg =~ /^([^=]+)=(.*)$/
Rscons.application.vars[$1] = $2
end
end
if rsconscript
unless File.exists?(rsconscript)
$stderr.puts "Cannot read #{rsconscript}"
exit 1
end
else
rsconscript = DEFAULT_RSCONSCRIPTS.find do |f|
File.exists?(f)
end
end
if rsconscript
script = Script.new
script.load(rsconscript)
end
if do_help
puts USAGE
exit 0
end
unless rsconscript
$stderr.puts "Could not find the Rsconscript to execute."
$stderr.puts "Looked for: #{DEFAULT_RSCONSCRIPTS.join(", ")}"
exit 1
end
exit Rscons.application.run(script, tasks_and_params)
end
usage
end
end
end

View File

@ -283,26 +283,10 @@ module Rscons
# before calling a normal task (default: true).
attr_accessor :autoconf
# @return [Hash]
# Tasks.
attr_reader :tasks
# Construct a Script.
def initialize
@autoconf = true
@tasks = {}
end
# Load a script from the specified file.
#
# @param path [String]
# File name of the rscons script to load.
#
# @return [void]
def load(path)
script_contents = File.read(path, mode: "rb")
dsl = TopLevelDsl.new(self)
dsl.instance_eval do
TopLevelDsl.new(self).instance_eval do
task("clean",
desc: "Remove build artifacts (but not configuration)",
autoconf: false) do
@ -318,7 +302,7 @@ module Rscons
autoconf: false) do
Rscons.application.distclean
end
task("install"
task("install",
desc: "Install project to configured installation prefix")
task("uninstall",
desc: "Uninstall project",
@ -326,7 +310,17 @@ module Rscons
Rscons.application.uninstall
end
end
dsl.instance_eval(script_contents, path, 1)
end
# Load a script from the specified file.
#
# @param path [String]
# File name of the rscons script to load.
#
# @return [void]
def load(path)
script_contents = File.read(path, mode: "rb")
TopLevelDsl.new(self).instance_eval(script_contents, path, 1)
end
# Perform configure action.

View File

@ -13,7 +13,7 @@ module Rscons
# @return [Hash, Task, nil]
# Hash of all tasks if name is nil, otherwise Task with the given name,
# if found.
def [](name)
def [](name = nil)
if name
if task = tasks[name]
task
@ -126,6 +126,12 @@ module Rscons
if options.include?(:autoconf)
@autoconf = options[:autoconf]
end
if options.include?(:desc)
@desc = options[:desc]
end
if options.include?(:deps)
@deps += options[:deps]
end
if block
if env = Environment.open_environment
@actions << proc do

View File

@ -88,7 +88,7 @@ unless File.exists?(script)
end
load script
if __FILE__ == $0
Rscons::Cli.run(ARGV)
Rscons::Cli.new.run(ARGV)
end
#==>#{encoded_compressed_script}
EOF