From b1b94595f6bf5ed1c1b605075fa9776a16909b64 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 25 Jan 2022 22:20:29 -0500 Subject: [PATCH] Parse task parameters; handle configure task specially --- lib/rscons/application.rb | 14 +++++------- lib/rscons/cli.rb | 45 ++++++++++++++++++++++++++++---------- lib/rscons/configure_op.rb | 23 +++++++++---------- lib/rscons/script.rb | 18 +++++++-------- lib/rscons/task.rb | 31 ++++++++++++++++---------- spec/build_tests_spec.rb | 15 ++++--------- 6 files changed, 83 insertions(+), 63 deletions(-) diff --git a/lib/rscons/application.rb b/lib/rscons/application.rb index 860244f..4ffa50d 100644 --- a/lib/rscons/application.rb +++ b/lib/rscons/application.rb @@ -42,8 +42,8 @@ module Rscons # # @param script [Script] # The script. - # @param tasks_and_params [Array>] - # List of task(s) to execute and possibly parameter(s) for them. + # @param tasks [Array] + # List of task(s) to execute. # @param options [Hash] # Optional parameters. # @option sub_op [Boolean] @@ -51,13 +51,12 @@ module Rscons # # @return [Integer] # Process exit code (0 on success). - def run(script, tasks_and_params, options = {}) + def run(script, tasks, options = {}) @script = script Cache.instance["failed_commands"] = [] begin - tasks_and_params.each do |task_and_params| - task_name, *task_params = task_and_params - Task[task_name].check_execute + tasks.each do |task| + Task[task].check_execute end 0 rescue RsconsError => e @@ -140,8 +139,7 @@ module Rscons # # @return [void] def configure - options = {project_name: @script.project_name} - co = ConfigureOp.new(options) + co = ConfigureOp.new(@script) begin @script.configure(co) rescue RsconsError => e diff --git a/lib/rscons/cli.rb b/lib/rscons/cli.rb index 07feb1a..5f19d15 100644 --- a/lib/rscons/cli.rb +++ b/lib/rscons/cli.rb @@ -32,17 +32,36 @@ module Rscons 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 - def parse_tasks_and_options(argv) - tasks_and_options = [] + def parse_tasks_and_params(argv) + tasks = [] while argv.size > 0 task = argv.shift - task_options = parse_task_options(task, argv) - tasks_and_options << [task, task_options] + parse_task_params(task, argv) + tasks << task end - tasks_and_options + tasks end def run_toplevel(argv) @@ -135,16 +154,16 @@ module Rscons # 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) + tasks = parse_tasks_and_params(argv) # If no user specified tasks, run "default" task. - if tasks_and_params.empty? - tasks_and_params << ["default"] + if tasks.empty? + tasks << "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) + Rscons.application.run(@script, tasks) end def usage @@ -167,7 +186,11 @@ EOF if task.desc usage += %[ #{sprintf("%-27s", name)} #{task.desc}\n] 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 diff --git a/lib/rscons/configure_op.rb b/lib/rscons/configure_op.rb index 5a3f419..9e59722 100644 --- a/lib/rscons/configure_op.rb +++ b/lib/rscons/configure_op.rb @@ -7,29 +7,26 @@ module Rscons # Create a ConfigureOp. # - # @param options [Hash] - # Optional parameters. - # @option options [String] :prefix - # Install prefix. - # @option options [String] :project_name - # Project name. - def initialize(options) - # Default options. - options[:prefix] ||= "/usr/local" + # @param script [Script] + # Build script. + def initialize(script) @work_dir = "#{Rscons.application.build_dir}/_configure" FileUtils.mkdir_p(@work_dir) @log_fh = File.open("#{@work_dir}/config.log", "wb") cache = Cache.instance cache["failed_commands"] = [] cache["configuration_data"] = {} - cache["configuration_data"]["prefix"] = options[:prefix] - if project_name = options[:project_name] + if project_name = script.project_name Ansi.write($stdout, "Configuring ", :cyan, project_name, :reset, "...\n") else $stdout.puts "Configuring project..." end - Ansi.write($stdout, "Setting prefix... ", :green, options[:prefix], :reset, "\n") - store_merge("prefix" => options[:prefix]) + vars = {} + 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 # Close the log file handle. diff --git a/lib/rscons/script.rb b/lib/rscons/script.rb index b6ef25a..dc828e7 100644 --- a/lib/rscons/script.rb +++ b/lib/rscons/script.rb @@ -43,12 +43,12 @@ module Rscons # Param name. # @param value [String, nil] # Param value. - # @param cli_option [String] - # Param CLI option text. + # @param takes_arg [String] + # Whether the parameter takes an argument. # @param description [String] # Param description. - def param(name, value, cli_option, description) - Task::Param.new(name, value, cli_option, description) + def param(name, value, takes_arg, description) + Task::Param.new(name, value, takes_arg, description) end # Return path components from the PATH variable. @@ -309,9 +309,7 @@ module Rscons task("configure", desc: "Configure the project", autoconf: false, - params: [param("prefix", "/usr/local", "prefix=PREFIX", "Set installation prefix (default: /usr/local)")]) do - Rscons.application.configure - end + params: [param("prefix", "/usr/local", true, "Set installation prefix (default: /usr/local)")]) task("distclean", desc: "Remove build directory and configuration", autoconf: false) do @@ -339,9 +337,11 @@ module Rscons end # Perform configure action. - def configure(configure_op, action) + def configure(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 diff --git a/lib/rscons/task.rb b/lib/rscons/task.rb index a724121..e0e2946 100644 --- a/lib/rscons/task.rb +++ b/lib/rscons/task.rb @@ -56,17 +56,17 @@ module Rscons # Param name. attr_reader :name - # @return [String] - # Param CLI option text. - attr_reader :cli_option - # @return [String] # Param description. attr_reader :description + # @return [Boolean] + # Whether the parameter takes an argument. + attr_reader :takes_arg + # @return [String, nil] # Param value. - attr_reader :value + attr_accessor :value # Construct a Param. # @@ -74,19 +74,23 @@ module Rscons # Param name. # @param value [String, nil] # Param value. - # @param cli_option [String] - # Param CLI option text. + # @param takes_arg [String] + # Whether the parameter takes an argument. # @param description [String] # Param description. - def initialize(name, value, cli_option, description) + def initialize(name, value, takes_arg, description) @name = name @value = value - @cli_option = cli_option + @takes_arg = takes_arg @description = description end end + # @return [Array] + # Task action blocks. + attr_reader :actions + # @return [Boolean] # Whether to automatically configure before running this task. attr_reader :autoconf @@ -138,9 +142,14 @@ module Rscons end end @deps.each do |dep| + Task[dep].check_execute end - @actions.each do |action| - action[] + if @name == "configure" + Rscons.application.configure + else + @actions.each do |action| + action[] + end end end diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 63815a7..345c4a1 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -410,7 +410,7 @@ EOF expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy 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.stdout).to match %r{Removing #{prefix}/bin/program.exe} expect(Dir.entries(prefix)).to match_array %w[. ..] @@ -2434,13 +2434,6 @@ EOF expect(result.stdout).to match /gcc.*-o.*simple/ 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 test_dir("simple") result = run_rscons(args: %w[-v]) @@ -2597,7 +2590,7 @@ EOF result = run_rscons(args: %w[-f install.rb install]) 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.stdout).to match %r{Removing #{prefix}/bin/program.exe} expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey @@ -2615,7 +2608,7 @@ EOF result = run_rscons(args: %w[-f install.rb install]) 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.stdout).to match %r{Removing #{prefix}/bin/program.exe} expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey @@ -2623,7 +2616,7 @@ EOF FileUtils.mkdir_p("#{prefix}/bin") 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.stdout).to_not match /Removing/ end