summaryrefslogtreecommitdiffhomepage
path: root/minirake
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2019-12-20 22:36:44 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2019-12-21 22:11:08 +0900
commitde17f63b4567cad3b02f1f1f9386eaf8dd704bbe (patch)
tree222d4fa4c2bcdc982c0afa32855df56e43e7798e /minirake
parentfee3c1c2422f74839419edf296651a3570cded61 (diff)
downloadmruby-de17f63b4567cad3b02f1f1f9386eaf8dd704bbe.tar.gz
mruby-de17f63b4567cad3b02f1f1f9386eaf8dd704bbe.zip
Abandon `minirake`. Use `rake` for compilation; fix #4884
Diffstat (limited to 'minirake')
-rwxr-xr-xminirake621
1 files changed, 0 insertions, 621 deletions
diff --git a/minirake b/minirake
deleted file mode 100755
index 8df395e97..000000000
--- a/minirake
+++ /dev/null
@@ -1,621 +0,0 @@
-#!/usr/bin/env ruby
-
-# Original is https://github.com/jimweirich/rake/
-# Copyright (c) 2003 Jim Weirich
-# License: MIT-LICENSE
-
-require 'getoptlong'
-require 'fileutils'
-
-$rake_fiber_table = {}
-$rake_jobs = 1
-$rake_failed = []
-
-class String
- def ext(newext='')
- return self.dup if ['.', '..'].include? self
- if newext != ''
- newext = (newext =~ /^\./) ? newext : ("." + newext)
- end
- self.chomp(File.extname(self)) << newext
- end
-
- def pathmap(spec=nil, &block)
- return self if spec.nil?
- result = ''
- spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
- case frag
- when '%f'
- result << File.basename(self)
- when '%n'
- result << File.basename(self).ext
- when '%d'
- result << File.dirname(self)
- when '%x'
- result << File.extname(self)
- when '%X'
- result << self.ext
- when '%p'
- result << self
- when '%s'
- result << (File::ALT_SEPARATOR || File::SEPARATOR)
- when '%-'
- # do nothing
- when '%%'
- result << "%"
- when /%(-?\d+)d/
- result << pathmap_partial($1.to_i)
- when /^%\{([^}]*)\}(\d*[dpfnxX])/
- patterns, operator = $1, $2
- result << pathmap('%' + operator).pathmap_replace(patterns, &block)
- when /^%/
- fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
- else
- result << frag
- end
- end
- result
- end
-end
-
-module MiniRake
- class Task
- TASKS = Hash.new
- RULES = Array.new
-
- # List of prerequisites for a task.
- attr_reader :prerequisites
-
- # Source dependency for rule synthesized tasks. Nil if task was not
- # sythesized from a rule.
- attr_accessor :source
-
- # Create a task named +task_name+ with no actions or prerequisites..
- # use +enhance+ to add actions and prerequisites.
- def initialize(task_name)
- @name = task_name
- @prerequisites = []
- @actions = []
- end
-
- # Enhance a task with prerequisites or actions. Returns self.
- def enhance(deps=nil, &block)
- @prerequisites |= deps if deps
- @actions << block if block_given?
- self
- end
-
- # Name of the task.
- def name
- @name.to_s
- end
-
- def done?; @done end
- def running?; @running end
-
- # Invoke the task if it is needed. Prerequisites are invoked first.
- def invoke
- puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
- return if @already_invoked
- prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
- prerequisites.each do |n|
- t = Task[n]
- unless t.done?
- return prerequisites.select{|v| v = Task[v]; v && (!v.done? || !v.running?) }
- end
- end
-
- @already_invoked = true
-
- if needed?
- @running = true
- if $rake_root_fiber
- return Fiber.new do
- self.execute
- $rake_root_fiber.transfer
- end
- else
- self.execute
- end
- end
-
- @done = true
- end
-
- # Execute the actions associated with this task.
- def execute
- puts "Execute #{name}" if $trace
- self.class.enhance_with_matching_rule(name) if @actions.empty?
- unless $dryrun
- @actions.each { |act| act.call(self) }
- end
- @done = true
- @running = false
- end
-
- # Is this task needed?
- def needed?
- true
- end
-
- # Timestamp for this task. Basic tasks return the current time for
- # their time stamp. Other tasks can be more sophisticated.
- def timestamp
- Time.now
- end
-
- # Class Methods ----------------------------------------------------
-
- class << self
-
- # Clear the task list. This cause rake to immediately forget all
- # the tasks that have been assigned. (Normally used in the unit
- # tests.)
- def clear
- TASKS.clear
- RULES.clear
- end
-
- # List of all defined tasks.
- def tasks
- TASKS.keys.sort.collect { |tn| Task[tn] }
- end
-
- # Return a task with the given name. If the task is not currently
- # known, try to synthesize one from the defined rules. If no
- # rules are found, but an existing file matches the task name,
- # assume it is a file task with no dependencies or actions.
- def [](task_name)
- task_name = task_name.to_s
- if task = TASKS[task_name]
- return task
- end
- if task = enhance_with_matching_rule(task_name)
- return task
- end
- if File.exist?(task_name)
- return FileTask.define_task(task_name)
- end
- fail "Don't know how to rake #{task_name}"
- end
-
- # Define a task given +args+ and an option block. If a rule with
- # the given name already exists, the prerequisites and actions are
- # added to the existing task.
- def define_task(args, &block)
- task_name, deps = resolve_args(args)
- lookup(task_name).enhance([deps].flatten, &block)
- end
-
- # Define a rule for synthesizing tasks.
- def create_rule(args, &block)
- pattern, deps = resolve_args(args)
- pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
- RULES << [pattern, deps, block]
- end
-
-
- # Lookup a task. Return an existing task if found, otherwise
- # create a task of the current type.
- def lookup(task_name)
- name = task_name.to_s
- TASKS[name] ||= self.new(name)
- end
-
- # If a rule can be found that matches the task name, enhance the
- # task with the prerequisites and actions from the rule. Set the
- # source attribute of the task appropriately for the rule. Return
- # the enhanced task or nil of no rule was found.
- def enhance_with_matching_rule(task_name, level=0)
- fail "Rule Recursion Too Deep: #{task_name}" if level >= 16
- RULES.each do |pattern, extensions, block|
- next unless pattern && pattern.match(task_name)
- sources = extensions.flat_map do |ext|
- case ext
- when /%/
- task_name.pathmap(ext)
- when %r{/}
- ext
- when /^\./
- source = task_name.sub(pattern, ext)
- source == ext ? task_name.ext(ext) : source
- when String
- ext
- when Proc, Method
- ext.arity == 1 ? ext.call(task_name) : ext.call
- else
- fail "Don't know how to handle rule dependent: #{ext.inspect}"
- end
- end
- prereqs = sources.map do |source|
- if File.exist?(source) || TASKS[source]
- source
- elsif parent = enhance_with_matching_rule(source, level + 1)
- parent.name
- else
- break nil
- end
- end
- if prereqs
- task = FileTask.define_task(task_name => prereqs, &block)
- task.source = prereqs.first
- return task
- end
- end
- nil
- end
-
- private
-
- # Resolve the arguments for a task/rule.
- def resolve_args(args)
- case args
- when Hash
- fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
- fail "No Task Name Given" if args.size < 1
- task_name = args.keys[0]
- deps = args[task_name]
- deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
- else
- task_name = args
- deps = []
- end
- [task_name, deps]
- end
- end
- end
-
-
- ######################################################################
- class FileTask < Task
- # Is this file task needed? Yes if it doesn't exist, or if its time
- # stamp is out of date.
- def needed?
- return true unless File.exist?(name)
- prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
- latest_prereq = prerequisites.collect{|n| Task[n].timestamp}.max
- return false if latest_prereq.nil?
- timestamp < latest_prereq
- end
-
- # Time stamp for file task.
- def timestamp
- return Time.at(0) unless File.exist?(name)
- stat = File::stat(name.to_s)
- stat.directory? ? Time.at(0) : stat.mtime
- end
- end
-
- module DSL
- # Declare a basic task.
- def task(args, &block)
- MiniRake::Task.define_task(args, &block)
- end
-
- # Declare a file task.
- def file(args, &block)
- MiniRake::FileTask.define_task(args, &block)
- end
-
- # Declare a set of files tasks to create the given directories on
- # demand.
- def directory(args, &block)
- MiniRake::FileTask.define_task(args) do |t|
- block.call(t) unless block.nil?
- dir = args.is_a?(Hash) ? args.keys.first : args
- (dir.split(File::SEPARATOR) + ['']).inject do |acc, part|
- (acc + File::SEPARATOR).tap do |d|
- Dir.mkdir(d) unless File.exists? d
- end + part
- end
- end
- end
-
- # Declare a rule for auto-tasks.
- def rule(args, &block)
- MiniRake::Task.create_rule(args, &block)
- end
-
- # Write a message to standard out if $verbose is enabled.
- def log(msg)
- print " " if $trace && $verbose
- puts msg if $verbose
- end
-
- # Run the system command +cmd+.
- def sh(cmd)
- puts cmd if $verbose
-
- if !$rake_root_fiber || Fiber.current == $rake_root_fiber
- system(cmd) or fail "Command Failed: [#{cmd}]"
- return
- end
-
- pid = Process.spawn(cmd)
- $rake_fiber_table[pid] = {
- fiber: Fiber.current,
- command: cmd,
- process_waiter: Process.detach(pid)
- }
- $rake_root_fiber.transfer
- end
-
- def desc(text)
- end
- end
-end
-
-Rake = MiniRake
-extend MiniRake::DSL
-
-
-######################################################################
-# Task Definition Functions ...
-
-######################################################################
-# Rake main application object. When invoking +rake+ from the command
-# line, a RakeApp object is created and run.
-#
-class RakeApp
- RAKEFILES = ['rakefile', 'Rakefile']
-
- OPTIONS = [
- ['--dry-run', '-n', GetoptLong::NO_ARGUMENT,
- "Do a dry run without executing actions."],
- ['--help', '-H', GetoptLong::NO_ARGUMENT,
- "Display this help message."],
- ['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT,
- "Include LIBDIR in the search path for required modules."],
- ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
- "Do not search parent directories for the Rakefile."],
- ['--quiet', '-q', GetoptLong::NO_ARGUMENT,
- "Do not log messages to standard output (default)."],
- ['--rakefile', '-f', GetoptLong::REQUIRED_ARGUMENT,
- "Use FILE as the rakefile."],
- ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
- "Require MODULE before executing rakefile."],
- ['--tasks', '-T', GetoptLong::NO_ARGUMENT,
- "Display the tasks and dependencies, then exit."],
- ['--pull-gems','-p', GetoptLong::NO_ARGUMENT,
- "Pull all git mrbgems."],
- ['--trace', '-t', GetoptLong::NO_ARGUMENT,
- "Turn on invoke/execute tracing."],
- ['--usage', '-h', GetoptLong::NO_ARGUMENT,
- "Display usage."],
- ['--verbose', '-v', GetoptLong::NO_ARGUMENT,
- "Log message to standard output."],
- ['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT,
- "Change executing directory of rakefiles."],
- ['--jobs', '-j', GetoptLong::REQUIRED_ARGUMENT,
- 'Execute rake with parallel jobs.']
- ]
-
- # Create a RakeApp object.
- def initialize
- @rakefile = nil
- @nosearch = false
- end
-
- # True if one of the files in RAKEFILES is in the current directory.
- # If a match is found, it is copied into @rakefile.
- def have_rakefile
- RAKEFILES.each do |fn|
- if File.exist?(fn)
- @rakefile = fn
- return true
- end
- end
- return false
- end
-
- # Display the program usage line.
- def usage
- puts "rake [-f rakefile] {options} targets..."
- end
-
- # Display the rake command line help.
- def help
- usage
- puts
- puts "Options are ..."
- puts
- OPTIONS.sort.each do |long, short, mode, desc|
- if mode == GetoptLong::REQUIRED_ARGUMENT
- if desc =~ /\b([A-Z]{2,})\b/
- long = long + "=#{$1}"
- end
- end
- printf " %-20s (%s)\n", long, short
- printf " %s\n", desc
- end
- end
-
- # Display the tasks and dependencies.
- def display_tasks
- MiniRake::Task.tasks.each do |t|
- puts "#{t.class} #{t.name}"
- t.prerequisites.each { |pre| puts " #{pre}" }
- end
- end
-
- # Return a list of the command line options supported by the
- # program.
- def command_line_options
- OPTIONS.collect { |lst| lst[0..-2] }
- end
-
- # Do the option defined by +opt+ and +value+.
- def do_option(opt, value)
- case opt
- when '--dry-run'
- $dryrun = true
- $trace = true
- when '--help'
- help
- exit
- when '--libdir'
- $:.push(value)
- when '--nosearch'
- @nosearch = true
- when '--quiet'
- $verbose = false
- when '--rakefile'
- RAKEFILES.clear
- RAKEFILES << value
- when '--require'
- require value
- when '--tasks'
- $show_tasks = true
- when '--pull-gems'
- $pull_gems = true
- when '--trace'
- $trace = true
- when '--usage'
- usage
- exit
- when '--verbose'
- $verbose = true
- when '--version'
- puts "rake, version #{RAKEVERSION}"
- exit
- when '--directory'
- Dir.chdir value
- when '--jobs'
- $rake_jobs = [value.to_i, 1].max
- else
- fail "Unknown option: #{opt}"
- end
- end
-
- # Read and handle the command line options.
- def handle_options
- $verbose = false
- $pull_gems = false
- opts = GetoptLong.new(*command_line_options)
- opts.each { |opt, value| do_option(opt, value) }
- end
-
- # Run the +rake+ application.
- def run
- handle_options
-
- unless $rake_root_fiber
- require 'fiber'
- $rake_root_fiber = Fiber.current
- end
-
- begin
- here = Dir.pwd
- while ! have_rakefile
- Dir.chdir("..")
- if Dir.pwd == here || @nosearch
- fail "No Rakefile found (looking for: #{RAKEFILES.join(', ')})"
- end
- here = Dir.pwd
- end
- root_tasks = []
- ARGV.each do |task_name|
- if /^(\w+)=(.*)/.match(task_name)
- ENV[$1] = $2
- else
- root_tasks << task_name
- end
- end
- puts "(in #{Dir.pwd})"
- $rakefile = @rakefile
- load @rakefile
- if $show_tasks
- display_tasks
- else
- root_tasks.push("default") if root_tasks.empty?
- # revese tasks for popping
- root_tasks.reverse!
-
- tasks = []
- until root_tasks.empty?
- root_name = root_tasks.pop
- tasks << root_name
- until tasks.empty?
- task_name = tasks.pop
- t = MiniRake::Task[task_name]
- f = t.invoke
-
- # append additional tasks to task queue
- if f.kind_of?(Array)
- tasks.push(*f)
- tasks.uniq!
- end
-
- unless f.kind_of? Fiber
- tasks.insert 0, task_name unless t.done?
- if root_name == task_name
- wait_process
- end
- next
- end
-
- wait_process while $rake_fiber_table.size >= $rake_jobs
-
- f.transfer
- end
- end
-
- wait_process until $rake_fiber_table.empty?
- end
- rescue Exception => e
- begin
- $rake_failed << e
- wait_process until $rake_fiber_table.empty?
- rescue Exception => next_e
- e = next_e
- retry
- end
- end
-
- return if $rake_failed.empty?
-
- puts "rake aborted!"
- $rake_failed.each do |ex|
- puts ex.message
- if $trace || $verbose
- puts ex.backtrace.join("\n")
- else
- puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
- end
- end
- exit 1
- end
-
- def wait_process(count = 0)
- dur = [0.0001 * (10 ** count), 1].min
- sleep dur
-
- exited = []
- $rake_fiber_table.each do |pid, v|
- exited << pid unless v[:process_waiter].alive?
- end
-
- exited.each do |pid|
- ent = $rake_fiber_table.delete pid
- st = ent[:process_waiter].value
-
- # ignore process that isn't created by `sh` method
- return if ent.nil?
-
- if st.exitstatus != 0
- raise "Command Failed: [#{ent[:command]}]"
- end
-
- fail 'task scheduling bug!' if $rake_fiber_table.size >= $rake_jobs
-
- ent[:fiber].transfer
- end
-
- wait_process(count + 1) if !$rake_fiber_table.empty? && exited.empty?
- end
-
-end
-
-if __FILE__ == $0 then
- RakeApp.new.run
-end