Add shortcut method for creating environments - close #149
Add env() method to create environments. Process all environments created at build script top level before executing any autoconf-enabled tasks, or if no tasks are specified by the user.
This commit is contained in:
1 parent
6d5f44d4e5
commit
ef7e9259cb
129 files changed
+742
-901
No files matched your search
@@ -39,15 +39,32 @@ module Rscons
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# @param tasks [Array<String>]
|
||||
# @param rsconscript [String]
|
||||
# Build script file name.
|
||||
# @param tasks_and_params [Hash<String => Hash<String => String>>]
|
||||
# List of task(s) to execute.
|
||||
# @param show_tasks [Boolean]
|
||||
# Flag to show tasks and exit.
|
||||
#
|
||||
# @return [Integer]
|
||||
# Process exit code (0 on success).
|
||||
def run(tasks)
|
||||
def run(rsconscript, tasks_and_params, show_tasks)
|
||||
Cache.instance["failed_commands"] = []
|
||||
tasks.each do |task|
|
||||
Task[task].check_execute
|
||||
@script.load(rsconscript)
|
||||
if show_tasks
|
||||
show_script_tasks
|
||||
return 0
|
||||
end
|
||||
apply_task_params(tasks_and_params)
|
||||
if tasks_and_params.empty?
|
||||
check_process_environments
|
||||
if Task.tasks["default"]
|
||||
Task["default"].check_execute
|
||||
end
|
||||
else
|
||||
tasks_and_params.each do |task_name, params|
|
||||
Task[task_name].check_execute
|
||||
end
|
||||
end
|
||||
0
|
||||
end
|
||||
@@ -111,6 +128,20 @@ module Rscons
|
||||
end
|
||||
end
|
||||
|
||||
# Check if environments need to be processed.
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# @return [void]
|
||||
def check_process_environments
|
||||
unless @_processed_environments
|
||||
Environment[].each do |env|
|
||||
env.process
|
||||
end
|
||||
@_processed_environments = true
|
||||
end
|
||||
end
|
||||
|
||||
# Configure the project.
|
||||
#
|
||||
# @api private
|
||||
@@ -158,6 +189,36 @@ module Rscons
|
||||
cache.write
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def show_script_tasks
|
||||
puts "Tasks:"
|
||||
Task[].each do |task_name, task|
|
||||
if task.description
|
||||
puts %[ #{sprintf("%-27s", task_name)} #{task.description}]
|
||||
task.params.each do |param_name, param|
|
||||
arg_text = "--#{param_name}"
|
||||
if param.takes_arg
|
||||
arg_text += "=#{param_name.upcase}"
|
||||
end
|
||||
puts %[ #{sprintf("%-25s", "#{arg_text}")} #{param.description}]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def apply_task_params(tasks_and_params)
|
||||
tasks_and_params.each do |task_name, task_params|
|
||||
task_params.each do |param_name, param_value|
|
||||
if param = Task[task_name].params[param_name]
|
||||
param.value = param_value
|
||||
else
|
||||
raise RsconsError.new("Unknown parameter #{param_name.inspect} for task #{task_name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
+32
-71
@@ -28,41 +28,32 @@ module Rscons
|
||||
private
|
||||
|
||||
def parse_task_params(task, argv)
|
||||
task_params = {}
|
||||
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}'"
|
||||
$stderr.puts usage
|
||||
exit 2
|
||||
end
|
||||
if argv[0] =~ /^--(\S+?)(?:=(.*))?$/
|
||||
param_name, param_value = $1, $2
|
||||
param_value ||= true
|
||||
task_params[param_name] = param_value
|
||||
argv.slice!(0)
|
||||
else
|
||||
return
|
||||
break
|
||||
end
|
||||
end
|
||||
task_params
|
||||
end
|
||||
|
||||
def parse_tasks_and_params(argv)
|
||||
tasks = []
|
||||
tasks_and_params = {}
|
||||
while argv.size > 0
|
||||
task = argv.shift
|
||||
parse_task_params(task, argv)
|
||||
tasks << task
|
||||
tasks_and_params[task] = parse_task_params(task, argv)
|
||||
end
|
||||
tasks
|
||||
tasks_and_params
|
||||
end
|
||||
|
||||
def run_toplevel(argv)
|
||||
rsconscript = nil
|
||||
do_help = false
|
||||
show_tasks = false
|
||||
|
||||
OptionParser.new do |opts|
|
||||
|
||||
@@ -80,7 +71,8 @@ module Rscons
|
||||
end
|
||||
|
||||
opts.on("-h", "--help") do
|
||||
do_help = true
|
||||
puts usage
|
||||
return 0
|
||||
end
|
||||
|
||||
opts.on("-j NTHREADS") do |n_threads|
|
||||
@@ -96,6 +88,10 @@ module Rscons
|
||||
end
|
||||
end
|
||||
|
||||
opts.on("-T", "--tasks") do
|
||||
show_tasks = true
|
||||
end
|
||||
|
||||
opts.on("-v", "--verbose") do
|
||||
Rscons.application.verbose = true
|
||||
end
|
||||
@@ -107,6 +103,9 @@ module Rscons
|
||||
|
||||
end.order!(argv)
|
||||
|
||||
# Parse the rest of the command line.
|
||||
tasks_and_params = parse_tasks_and_params(argv)
|
||||
|
||||
# Find the build script.
|
||||
if rsconscript
|
||||
unless File.exists?(rsconscript)
|
||||
@@ -119,40 +118,16 @@ module Rscons
|
||||
end
|
||||
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
|
||||
|
||||
begin
|
||||
# Load the build script.
|
||||
if rsconscript
|
||||
Rscons.application.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 = parse_tasks_and_params(argv)
|
||||
|
||||
# If no user specified tasks, run "default" task.
|
||||
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(tasks)
|
||||
Rscons.application.run(rsconscript, tasks_and_params, show_tasks)
|
||||
rescue RsconsError => e
|
||||
Ansi.write($stderr, :red, e.message, :reset, "\n")
|
||||
1
|
||||
@@ -160,7 +135,7 @@ module Rscons
|
||||
end
|
||||
|
||||
def usage
|
||||
usage = <<EOF
|
||||
<<EOF
|
||||
Usage: #{$0} [global options] [[task] [task options] ...]
|
||||
|
||||
Global options:
|
||||
@@ -170,24 +145,10 @@ Global options:
|
||||
-h, --help Show rscons help and exit
|
||||
-j N, --nthreads=N Set number of threads (local default: #{Rscons.application.n_threads})
|
||||
-r COLOR, --color=COLOR Set color mode (off, auto, force)
|
||||
-T, --tasks Show task list and parameters and exit
|
||||
-v, --verbose Run verbosely
|
||||
--version Show rscons version and exit
|
||||
|
||||
Tasks:
|
||||
EOF
|
||||
Task[].each do |name, task|
|
||||
if task.desc
|
||||
usage += %[ #{sprintf("%-27s", name)} #{task.desc}\n]
|
||||
task.params.each do |name, param|
|
||||
arg_text = "--#{name}"
|
||||
if param.takes_arg
|
||||
arg_text += "=#{name.upcase}"
|
||||
end
|
||||
usage += %[ #{sprintf("%-25s", "#{arg_text}")} #{param.description}\n]
|
||||
end
|
||||
end
|
||||
end
|
||||
usage
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+49
-27
@@ -10,16 +10,13 @@ module Rscons
|
||||
|
||||
class << self
|
||||
|
||||
# @return [Array<Environment>]
|
||||
# All Environments.
|
||||
attr_reader :environments
|
||||
|
||||
# @return [Environment]
|
||||
# The Environment that is currently executing a construction block.
|
||||
attr_accessor :open_environment
|
||||
attr_accessor :running_environment
|
||||
|
||||
# Initialize class instance variables.
|
||||
def class_init
|
||||
@environments_by_name = {}
|
||||
@environments = []
|
||||
end
|
||||
|
||||
@@ -36,9 +33,24 @@ module Rscons
|
||||
|
||||
# Register an Environment.
|
||||
def register(env)
|
||||
@environments ||= []
|
||||
@environments << env
|
||||
if env.name
|
||||
@environments_by_name[env.name] = env
|
||||
end
|
||||
end
|
||||
|
||||
# Get an Environment by name.
|
||||
#
|
||||
# @param name [String]
|
||||
# Environment name.
|
||||
def [](name = nil)
|
||||
if name
|
||||
@environments_by_name[name]
|
||||
else
|
||||
@environments
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# @return [Hash] Set of !{"builder_name" => builder_object} pairs.
|
||||
@@ -61,28 +73,36 @@ module Rscons
|
||||
|
||||
# Create an Environment object.
|
||||
#
|
||||
# @overload initialize(name, options)
|
||||
# @overload initialize(options)
|
||||
#
|
||||
# @param name [String]
|
||||
# Environment name. This determines the folder name used to store all
|
||||
# environment build files under the top-level build directory.
|
||||
# @param options [Hash]
|
||||
# @option options [Symbol] :echo
|
||||
# :command, :short, or :off (default :short)
|
||||
# @option options [Boolean] :exclude_builders
|
||||
# Whether to omit adding default builders (default false)
|
||||
# @option options [String, nil] :name
|
||||
# Environment name. This determines the folder name used to store all
|
||||
# environment build files under the top-level build directory.
|
||||
# @option options [String, Array<String>] :use
|
||||
# Use flag(s). If specified, any configuration flags which were saved
|
||||
# with a corresponding `:use` value will be applied to this Environment.
|
||||
#
|
||||
# If a block is given, the Environment object is yielded to the block and
|
||||
# when the block returns, the {#process} method is automatically called.
|
||||
def initialize(options = {})
|
||||
def initialize(*args, &block)
|
||||
@id = self.class.get_id
|
||||
if args.first.is_a?(String)
|
||||
@name = args.slice!(0)
|
||||
else
|
||||
@name = "e.#{@id}"
|
||||
end
|
||||
options = args.first || {}
|
||||
Rscons.application.check_configure
|
||||
unless Cache.instance["configuration_data"]["configured"]
|
||||
raise "Project must be configured before creating an Environment"
|
||||
end
|
||||
super(options)
|
||||
@id = self.class.get_id
|
||||
self.class.register(self)
|
||||
# Hash of Thread object => {Command} or {Builder}.
|
||||
@threads = {}
|
||||
@registered_build_dependencies = {}
|
||||
@@ -109,15 +129,13 @@ module Rscons
|
||||
else
|
||||
:short
|
||||
end
|
||||
@name = options[:name] || "e.#{@id}"
|
||||
@build_root = "#{Rscons.application.build_dir}/#{@name}"
|
||||
@n_threads = Rscons.application.n_threads
|
||||
|
||||
if block_given?
|
||||
Environment.open_environment = self
|
||||
yield self
|
||||
Environment.open_environment = nil
|
||||
process
|
||||
self.class.register(self)
|
||||
if block
|
||||
Environment.running_environment = self
|
||||
block[self]
|
||||
Environment.running_environment = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -140,7 +158,11 @@ module Rscons
|
||||
# Any options that #initialize receives can also be specified here.
|
||||
#
|
||||
# @return [Environment] The newly created {Environment} object.
|
||||
def clone(options = {})
|
||||
def clone(*args, &block)
|
||||
if args.first.is_a?(String)
|
||||
name = args.slice!(0)
|
||||
end
|
||||
options = args.first || {}
|
||||
options = options.dup
|
||||
clone = options[:clone] || :all
|
||||
clone = Set[:variables, :builders, :build_hooks] if clone == :all
|
||||
@@ -148,7 +170,9 @@ module Rscons
|
||||
clone = Set.new(clone) if clone.is_a?(Array)
|
||||
clone.delete(:builders) if options[:exclude_builders]
|
||||
options[:echo] ||= @echo
|
||||
env = self.class.new(options.merge(exclude_builders: true))
|
||||
new_args = name ? [name] : []
|
||||
new_args << options.merge(exclude_builders: true)
|
||||
env = self.class.new(*new_args)
|
||||
if clone.include?(:builders)
|
||||
@builders.each do |builder_name, builder|
|
||||
env.add_builder(builder)
|
||||
@@ -164,12 +188,10 @@ module Rscons
|
||||
end
|
||||
end
|
||||
env.instance_variable_set(:@n_threads, @n_threads)
|
||||
|
||||
if block_given?
|
||||
Environment.open_environment = env
|
||||
yield env
|
||||
Environment.open_environment = nil
|
||||
env.process
|
||||
if block
|
||||
Environment.running_environment = self
|
||||
block[env]
|
||||
Environment.running_environment = nil
|
||||
end
|
||||
env
|
||||
end
|
||||
|
||||
@@ -93,6 +93,11 @@ module Rscons
|
||||
end
|
||||
end
|
||||
|
||||
# Create an environment.
|
||||
def env(*args, &block)
|
||||
Environment.new(*args, &block)
|
||||
end
|
||||
|
||||
# Construct a task parameter.
|
||||
#
|
||||
# @param name [String]
|
||||
@@ -235,13 +240,8 @@ module Rscons
|
||||
end
|
||||
|
||||
# Create or modify a task.
|
||||
def task(name, options = {}, &block)
|
||||
if task = Task.tasks[name]
|
||||
task.modify(options, &block)
|
||||
else
|
||||
task = Task.new(name, options, &block)
|
||||
end
|
||||
task
|
||||
def task(*args, &block)
|
||||
Util.task(*args, &block)
|
||||
end
|
||||
|
||||
[
|
||||
|
||||
+10
-13
@@ -95,13 +95,9 @@ module Rscons
|
||||
# Whether to automatically configure before running this task.
|
||||
attr_reader :autoconf
|
||||
|
||||
# @return [Array<String>]
|
||||
# Task dependencies.
|
||||
attr_reader :deps
|
||||
|
||||
# @return [String, nil]
|
||||
# Task description, if given.
|
||||
attr_reader :desc
|
||||
attr_reader :description
|
||||
|
||||
# @return [String]
|
||||
# Task name.
|
||||
@@ -122,8 +118,8 @@ module Rscons
|
||||
# true).
|
||||
def initialize(name, options, &block)
|
||||
@autoconf = true
|
||||
@deps = []
|
||||
@desc = nil
|
||||
@dependencies = []
|
||||
@description = nil
|
||||
@name = name
|
||||
@params = {}
|
||||
@actions = []
|
||||
@@ -153,9 +149,10 @@ module Rscons
|
||||
@executed = true
|
||||
if @autoconf
|
||||
Rscons.application.check_configure
|
||||
Rscons.application.check_process_environments
|
||||
end
|
||||
@deps.each do |dep|
|
||||
Task[dep].check_execute
|
||||
@dependencies.each do |dependency|
|
||||
Task[dependency].check_execute
|
||||
end
|
||||
if @name == "configure"
|
||||
Rscons.application.configure
|
||||
@@ -193,10 +190,10 @@ module Rscons
|
||||
@autoconf = options[:autoconf]
|
||||
end
|
||||
if options.include?(:desc)
|
||||
@desc = options[:desc]
|
||||
@description = options[:desc]
|
||||
end
|
||||
if options.include?(:deps)
|
||||
@deps += Array(options[:deps])
|
||||
if options.include?(:depends)
|
||||
@dependencies += Array(options[:depends])
|
||||
end
|
||||
if options.include?(:params)
|
||||
Array(options[:params]).each do |param|
|
||||
@@ -204,7 +201,7 @@ module Rscons
|
||||
end
|
||||
end
|
||||
if block
|
||||
if env = Environment.open_environment
|
||||
if env = Environment.running_environment
|
||||
@actions << proc do
|
||||
block[]
|
||||
env.process
|
||||
|
||||
@@ -191,6 +191,16 @@ module Rscons
|
||||
deps
|
||||
end
|
||||
|
||||
# Create or modify a task.
|
||||
def task(name, options = {}, &block)
|
||||
if task = Task.tasks[name]
|
||||
task.modify(options, &block)
|
||||
else
|
||||
task = Task.new(name, options, &block)
|
||||
end
|
||||
task
|
||||
end
|
||||
|
||||
# Wait for any of a number of threads to complete.
|
||||
#
|
||||
# @param threads [Array<Thread>]
|
||||
|
||||
Reference in new issue
Block a user