Parse task parameters; handle configure task specially

This commit is contained in:
Josh Holtrop 2022-01-25 22:20:29 -05:00
parent 55dc22db05
commit b1b94595f6
6 changed files with 83 additions and 63 deletions

View File

@ -42,8 +42,8 @@ module Rscons
# #
# @param script [Script] # @param script [Script]
# The script. # The script.
# @param tasks_and_params [Array<Array<String>>] # @param tasks [Array<String>]
# List of task(s) to execute and possibly parameter(s) for them. # List of task(s) to execute.
# @param options [Hash] # @param options [Hash]
# Optional parameters. # Optional parameters.
# @option sub_op [Boolean] # @option sub_op [Boolean]
@ -51,13 +51,12 @@ module Rscons
# #
# @return [Integer] # @return [Integer]
# Process exit code (0 on success). # Process exit code (0 on success).
def run(script, tasks_and_params, options = {}) def run(script, tasks, options = {})
@script = script @script = script
Cache.instance["failed_commands"] = [] Cache.instance["failed_commands"] = []
begin begin
tasks_and_params.each do |task_and_params| tasks.each do |task|
task_name, *task_params = task_and_params Task[task].check_execute
Task[task_name].check_execute
end end
0 0
rescue RsconsError => e rescue RsconsError => e
@ -140,8 +139,7 @@ module Rscons
# #
# @return [void] # @return [void]
def configure def configure
options = {project_name: @script.project_name} co = ConfigureOp.new(@script)
co = ConfigureOp.new(options)
begin begin
@script.configure(co) @script.configure(co)
rescue RsconsError => e rescue RsconsError => e

View File

@ -32,17 +32,36 @@ module Rscons
private private
def parse_task_options(task, argv) def parse_task_params(task, argv)
while argv.size > 0
if argv[0].start_with?("-")
valid_arg = false
if argv[0] =~ /^--(\S+?)(?:=(.*))$/
param_name, value = $1, $2
if param = Task[task].params[param_name]
param.value = value || argv[0]
argv.slice!(0)
valid_arg = true
end
end
unless valid_arg
$stderr.puts "Invalid task '#{task}' argument '#{argv[0].split("=").first}'"
exit 2
end
else
return
end
end
end end
def parse_tasks_and_options(argv) def parse_tasks_and_params(argv)
tasks_and_options = [] tasks = []
while argv.size > 0 while argv.size > 0
task = argv.shift task = argv.shift
task_options = parse_task_options(task, argv) parse_task_params(task, argv)
tasks_and_options << [task, task_options] tasks << task
end end
tasks_and_options tasks
end end
def run_toplevel(argv) def run_toplevel(argv)
@ -135,16 +154,16 @@ module Rscons
# Parse the rest of the command line. This is done after loading the # 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 # build script so that script-defined tasks and task options can be
# taken into account. # taken into account.
tasks_and_params = parse_tasks_and_options(argv) tasks = parse_tasks_and_params(argv)
# If no user specified tasks, run "default" task. # If no user specified tasks, run "default" task.
if tasks_and_params.empty? if tasks.empty?
tasks_and_params << ["default"] tasks << "default"
end end
# Finally, with the script fully loaded and command-line parsed, run # Finally, with the script fully loaded and command-line parsed, run
# the application to execute all required tasks. # the application to execute all required tasks.
Rscons.application.run(@script, tasks_and_params) Rscons.application.run(@script, tasks)
end end
def usage def usage
@ -167,7 +186,11 @@ EOF
if task.desc if task.desc
usage += %[ #{sprintf("%-27s", name)} #{task.desc}\n] usage += %[ #{sprintf("%-27s", name)} #{task.desc}\n]
task.params.each do |name, param| task.params.each do |name, param|
usage += %[ #{sprintf("%-25s", "--#{param.cli_option}")} #{param.description}\n] arg_text = "--#{name}"
if param.takes_arg
arg_text += "=#{name.upcase}"
end
usage += %[ #{sprintf("%-25s", "#{arg_text}")} #{param.description}\n]
end end
end end
end end

View File

@ -7,29 +7,26 @@ module Rscons
# Create a ConfigureOp. # Create a ConfigureOp.
# #
# @param options [Hash] # @param script [Script]
# Optional parameters. # Build script.
# @option options [String] :prefix def initialize(script)
# Install prefix.
# @option options [String] :project_name
# Project name.
def initialize(options)
# Default options.
options[:prefix] ||= "/usr/local"
@work_dir = "#{Rscons.application.build_dir}/_configure" @work_dir = "#{Rscons.application.build_dir}/_configure"
FileUtils.mkdir_p(@work_dir) FileUtils.mkdir_p(@work_dir)
@log_fh = File.open("#{@work_dir}/config.log", "wb") @log_fh = File.open("#{@work_dir}/config.log", "wb")
cache = Cache.instance cache = Cache.instance
cache["failed_commands"] = [] cache["failed_commands"] = []
cache["configuration_data"] = {} cache["configuration_data"] = {}
cache["configuration_data"]["prefix"] = options[:prefix] if project_name = script.project_name
if project_name = options[:project_name]
Ansi.write($stdout, "Configuring ", :cyan, project_name, :reset, "...\n") Ansi.write($stdout, "Configuring ", :cyan, project_name, :reset, "...\n")
else else
$stdout.puts "Configuring project..." $stdout.puts "Configuring project..."
end end
Ansi.write($stdout, "Setting prefix... ", :green, options[:prefix], :reset, "\n") vars = {}
store_merge("prefix" => options[:prefix]) Task["configure"].params.each do |name, param|
Ansi.write($stdout, "Setting #{name}... ", :green, param.value, :reset, "\n")
vars[name] = param.value
end
store_merge(vars)
end end
# Close the log file handle. # Close the log file handle.

View File

@ -43,12 +43,12 @@ module Rscons
# Param name. # Param name.
# @param value [String, nil] # @param value [String, nil]
# Param value. # Param value.
# @param cli_option [String] # @param takes_arg [String]
# Param CLI option text. # Whether the parameter takes an argument.
# @param description [String] # @param description [String]
# Param description. # Param description.
def param(name, value, cli_option, description) def param(name, value, takes_arg, description)
Task::Param.new(name, value, cli_option, description) Task::Param.new(name, value, takes_arg, description)
end end
# Return path components from the PATH variable. # Return path components from the PATH variable.
@ -309,9 +309,7 @@ module Rscons
task("configure", task("configure",
desc: "Configure the project", desc: "Configure the project",
autoconf: false, autoconf: false,
params: [param("prefix", "/usr/local", "prefix=PREFIX", "Set installation prefix (default: /usr/local)")]) do params: [param("prefix", "/usr/local", true, "Set installation prefix (default: /usr/local)")])
Rscons.application.configure
end
task("distclean", task("distclean",
desc: "Remove build directory and configuration", desc: "Remove build directory and configuration",
autoconf: false) do autoconf: false) do
@ -339,9 +337,11 @@ module Rscons
end end
# Perform configure action. # Perform configure action.
def configure(configure_op, action) def configure(configure_op)
cdsl = ConfigureDsl.new(self, configure_op) cdsl = ConfigureDsl.new(self, configure_op)
cdsl.instance_eval(&action) Task["configure"].actions.each do |action|
cdsl.instance_eval(&action)
end
end end
end end

View File

@ -56,17 +56,17 @@ module Rscons
# Param name. # Param name.
attr_reader :name attr_reader :name
# @return [String]
# Param CLI option text.
attr_reader :cli_option
# @return [String] # @return [String]
# Param description. # Param description.
attr_reader :description attr_reader :description
# @return [Boolean]
# Whether the parameter takes an argument.
attr_reader :takes_arg
# @return [String, nil] # @return [String, nil]
# Param value. # Param value.
attr_reader :value attr_accessor :value
# Construct a Param. # Construct a Param.
# #
@ -74,19 +74,23 @@ module Rscons
# Param name. # Param name.
# @param value [String, nil] # @param value [String, nil]
# Param value. # Param value.
# @param cli_option [String] # @param takes_arg [String]
# Param CLI option text. # Whether the parameter takes an argument.
# @param description [String] # @param description [String]
# Param description. # Param description.
def initialize(name, value, cli_option, description) def initialize(name, value, takes_arg, description)
@name = name @name = name
@value = value @value = value
@cli_option = cli_option @takes_arg = takes_arg
@description = description @description = description
end end
end end
# @return [Array<Proc>]
# Task action blocks.
attr_reader :actions
# @return [Boolean] # @return [Boolean]
# Whether to automatically configure before running this task. # Whether to automatically configure before running this task.
attr_reader :autoconf attr_reader :autoconf
@ -138,9 +142,14 @@ module Rscons
end end
end end
@deps.each do |dep| @deps.each do |dep|
Task[dep].check_execute
end end
@actions.each do |action| if @name == "configure"
action[] Rscons.application.configure
else
@actions.each do |action|
action[]
end
end end
end end

View File

@ -410,7 +410,7 @@ EOF
expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.c.o")).to be_falsey expect(File.exists?("build/e.1/src/one/one.c.o")).to be_falsey
result = run_rscons(args: %w[-f install.rb uninstall -v]) result = run_rscons(args: %w[-f install.rb -v uninstall])
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(result.stdout).to match %r{Removing #{prefix}/bin/program.exe} expect(result.stdout).to match %r{Removing #{prefix}/bin/program.exe}
expect(Dir.entries(prefix)).to match_array %w[. ..] expect(Dir.entries(prefix)).to match_array %w[. ..]
@ -2434,13 +2434,6 @@ EOF
expect(result.stdout).to match /gcc.*-o.*simple/ expect(result.stdout).to match /gcc.*-o.*simple/
end end
it "echoes commands by default with -v after build operation" do
test_dir('simple')
result = run_rscons(args: %w[build -v])
expect(result.stderr).to eq ""
expect(result.stdout).to match /gcc.*-o.*simple/
end
it "prints operation start time" do it "prints operation start time" do
test_dir("simple") test_dir("simple")
result = run_rscons(args: %w[-v]) result = run_rscons(args: %w[-v])
@ -2597,7 +2590,7 @@ EOF
result = run_rscons(args: %w[-f install.rb install]) result = run_rscons(args: %w[-f install.rb install])
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
result = run_rscons(args: %w[-f install.rb uninstall -v]) result = run_rscons(args: %w[-f install.rb -v uninstall])
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(result.stdout).to match %r{Removing #{prefix}/bin/program.exe} expect(result.stdout).to match %r{Removing #{prefix}/bin/program.exe}
expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey
@ -2615,7 +2608,7 @@ EOF
result = run_rscons(args: %w[-f install.rb install]) result = run_rscons(args: %w[-f install.rb install])
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
result = run_rscons(args: %w[-f install.rb uninstall -v]) result = run_rscons(args: %w[-f install.rb -v uninstall])
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(result.stdout).to match %r{Removing #{prefix}/bin/program.exe} expect(result.stdout).to match %r{Removing #{prefix}/bin/program.exe}
expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey
@ -2623,7 +2616,7 @@ EOF
FileUtils.mkdir_p("#{prefix}/bin") FileUtils.mkdir_p("#{prefix}/bin")
File.open("#{prefix}/bin/program.exe", "w") {|fh| fh.write("hi")} File.open("#{prefix}/bin/program.exe", "w") {|fh| fh.write("hi")}
result = run_rscons(args: %w[-f install.rb uninstall -v]) result = run_rscons(args: %w[-f install.rb -v uninstall])
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(result.stdout).to_not match /Removing/ expect(result.stdout).to_not match /Removing/
end end