Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

Location:
EcnlProtoTool/trunk/mruby-2.1.1
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/mruby-2.1.1/minirake

    r331 r439  
    1 #!/usr/bin/env ruby
    2 
    3 # Original is https://github.com/jimweirich/rake/
    4 # Copyright (c) 2003 Jim Weirich
    5 # License: MIT-LICENSE
    6 
    7 require 'getoptlong'
    8 require 'fileutils'
    9 
    10 class String
    11   def ext(newext='')
    12     return self.dup if ['.', '..'].include? self
    13     if newext != ''
    14       newext = (newext =~ /^\./) ? newext : ("." + newext)
    15     end
    16     self.chomp(File.extname(self)) << newext
    17   end
    18 
    19   def pathmap(spec=nil, &block)
    20     return self if spec.nil?
    21     result = ''
    22     spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
    23       case frag
    24       when '%f'
    25         result << File.basename(self)
    26       when '%n'
    27         result << File.basename(self).ext
    28       when '%d'
    29         result << File.dirname(self)
    30       when '%x'
    31         result << File.extname(self)
    32       when '%X'
    33         result << self.ext
    34       when '%p'
    35         result << self
    36       when '%s'
    37         result << (File::ALT_SEPARATOR || File::SEPARATOR)
    38       when '%-'
    39         # do nothing
    40       when '%%'
    41         result << "%"
    42       when /%(-?\d+)d/
    43         result << pathmap_partial($1.to_i)
    44       when /^%\{([^}]*)\}(\d*[dpfnxX])/
    45         patterns, operator = $1, $2
    46         result << pathmap('%' + operator).pathmap_replace(patterns, &block)
    47       when /^%/
    48         fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
    49       else
    50         result << frag
    51       end
    52     end
    53     result
    54   end
    55 end
    56 
    57 module MiniRake
    58   class Task
    59     TASKS = Hash.new
    60     RULES = Array.new
    61 
    62     # List of prerequisites for a task.
    63     attr_reader :prerequisites
    64 
    65     # Source dependency for rule synthesized tasks.  Nil if task was not
    66     # sythesized from a rule.
    67     attr_accessor :source
    68 
    69     # Create a task named +task_name+ with no actions or prerequisites..
    70     # use +enhance+ to add actions and prerequisites.
    71     def initialize(task_name)
    72       @name = task_name
    73       @prerequisites = []
    74       @actions = []
    75     end
    76 
    77     # Enhance a task with prerequisites or actions.  Returns self.
    78     def enhance(deps=nil, &block)
    79       @prerequisites |= deps if deps
    80       @actions << block if block_given?
    81       self
    82     end
    83 
    84     # Name of the task.
    85     def name
    86       @name.to_s
    87     end
    88 
    89     # Invoke the task if it is needed.  Prerequites are invoked first.
    90     def invoke
    91       puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
    92       return if @already_invoked
    93       @already_invoked = true
    94       prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
    95       prerequisites.each { |n| Task[n].invoke }
    96       execute if needed?
    97     end
    98 
    99     # Execute the actions associated with this task.
    100     def execute
    101       puts "Execute #{name}" if $trace
    102       self.class.enhance_with_matching_rule(name) if @actions.empty?
    103       unless $dryrun
    104         @actions.each { |act| act.call(self) }
    105       end
    106     end
    107 
    108     # Is this task needed?
    109     def needed?
    110       true
    111     end
    112 
    113     # Timestamp for this task.  Basic tasks return the current time for
    114     # their time stamp.  Other tasks can be more sophisticated.
    115     def timestamp
    116       Time.now
    117     end
    118 
    119     # Class Methods ----------------------------------------------------
    120 
    121     class << self
    122 
    123       # Clear the task list.  This cause rake to immediately forget all
    124       # the tasks that have been assigned.  (Normally used in the unit
    125       # tests.)
    126       def clear
    127         TASKS.clear
    128         RULES.clear
    129       end
    130 
    131       # List of all defined tasks.
    132       def tasks
    133         TASKS.keys.sort.collect { |tn| Task[tn] }
    134       end
    135 
    136       # Return a task with the given name.  If the task is not currently
    137       # known, try to synthesize one from the defined rules.  If no
    138       # rules are found, but an existing file matches the task name,
    139       # assume it is a file task with no dependencies or actions.
    140       def [](task_name)
    141         task_name = task_name.to_s
    142         if task_name.end_with?(":")
    143           task_name = task_name.slice(0, task_name.length - 1)
    144         end
    145         if task = TASKS[task_name]
    146           return task
    147         end
    148         if task = enhance_with_matching_rule(task_name)
    149           return task
    150         end
    151         if File.exist?(task_name)
    152           return FileTask.define_task(task_name)
    153         end
    154         fail "Don't know how to rake #{task_name}"
    155       end
    156 
    157       # Define a task given +args+ and an option block.  If a rule with
    158       # the given name already exists, the prerequisites and actions are
    159       # added to the existing task.
    160       def define_task(args, &block)
    161         task_name, deps = resolve_args(args)
    162         lookup(task_name).enhance([deps].flatten, &block)
    163       end
    164 
    165       # Define a rule for synthesizing tasks.
    166       def create_rule(args, &block)
    167         pattern, deps = resolve_args(args)
    168         pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
    169         RULES << [pattern, deps, block]
    170       end
    171 
    172 
    173       # Lookup a task.  Return an existing task if found, otherwise
    174       # create a task of the current type.
    175       def lookup(task_name)
    176         name = task_name.to_s
    177         TASKS[name] ||= self.new(name)
    178       end
    179 
    180       # If a rule can be found that matches the task name, enhance the
    181       # task with the prerequisites and actions from the rule.  Set the
    182       # source attribute of the task appropriately for the rule.  Return
    183       # the enhanced task or nil of no rule was found.
    184       def enhance_with_matching_rule(task_name)
    185         RULES.each do |pattern, extensions, block|
    186           if pattern.match(task_name)
    187             ext = extensions.first
    188             deps = extensions[1..-1]
    189             case ext
    190             when String
    191               source = task_name.sub(/\.[^.]*$/, ext)
    192             when Proc
    193               source = ext.call(task_name)
    194             else
    195               fail "Don't know how to handle rule dependent: #{ext.inspect}"
    196             end
    197             if File.exist?(source)
    198               task = FileTask.define_task({task_name => [source]+deps}, &block)
    199               task.source = source
    200               return task
    201             end
    202           end
    203         end
    204         nil
    205       end
    206 
    207       private
    208 
    209       # Resolve the arguments for a task/rule.
    210       def resolve_args(args)
    211         case args
    212         when Hash
    213           fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
    214           fail "No Task Name Given" if args.size < 1
    215           task_name = args.keys[0]
    216           deps = args[task_name]
    217           deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
    218         else
    219           task_name = args
    220           deps = []
    221         end
    222         [task_name, deps]
    223       end
    224     end
    225   end
    226 
    227 
    228   ######################################################################
    229   class FileTask < Task
    230     # Is this file task needed?  Yes if it doesn't exist, or if its time
    231     # stamp is out of date.
    232     def needed?
    233       return true unless File.exist?(name)
    234       prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
    235       latest_prereq = prerequisites.collect{|n| Task[n].timestamp}.max
    236       return false if latest_prereq.nil?
    237       timestamp < latest_prereq
    238     end
    239 
    240     # Time stamp for file task.
    241     def timestamp
    242       return Time.at(0) unless File.exist?(name)
    243       stat = File::stat(name.to_s)
    244       stat.directory? ? Time.at(0) : stat.mtime
    245     end
    246   end
    247 
    248   module DSL
    249     # Declare a basic task.
    250     def task(args, &block)
    251       MiniRake::Task.define_task(args, &block)
    252     end
    253 
    254     # Declare a file task.
    255     def file(args, &block)
    256       MiniRake::FileTask.define_task(args, &block)
    257     end
    258 
    259     # Declare a set of files tasks to create the given directories on
    260     # demand.
    261     def directory(args, &block)
    262       MiniRake::FileTask.define_task(args) do |t|
    263         block.call(t) unless block.nil?
    264         dir = args.is_a?(Hash) ? args.keys.first : args
    265         (dir.split(File::SEPARATOR) + ['']).inject do |acc, part|
    266           (acc + File::SEPARATOR).tap do |d|
    267             Dir.mkdir(d) unless File.exists? d
    268           end + part
    269         end
    270       end
    271     end
    272 
    273     # Declare a rule for auto-tasks.
    274     def rule(args, &block)
    275       MiniRake::Task.create_rule(args, &block)
    276     end
    277 
    278     # Write a message to standard out if $verbose is enabled.
    279     def log(msg)
    280       print "  " if $trace && $verbose
    281       puts msg if $verbose
    282     end
    283 
    284     # Run the system command +cmd+.
    285     def sh(cmd)
    286       puts cmd if $verbose
    287       system(cmd) or fail "Command Failed: [#{cmd}]"
    288     end
    289 
    290     def desc(text)
    291     end
    292   end
    293 end
    294 
    295 Rake = MiniRake
    296 extend MiniRake::DSL
    297 
    298 
    299 ######################################################################
    300 # Task Definition Functions ...
    301 
    302 ######################################################################
    303 # Rake main application object.  When invoking +rake+ from the command
    304 # line, a RakeApp object is created and run.
    305 #
    306 class RakeApp
    307   RAKEFILES = ['rakefile', 'Rakefile']
    308 
    309   OPTIONS = [
    310     ['--dry-run',  '-n', GetoptLong::NO_ARGUMENT,
    311       "Do a dry run without executing actions."],
    312     ['--help',     '-H', GetoptLong::NO_ARGUMENT,
    313       "Display this help message."],
    314     ['--libdir',   '-I', GetoptLong::REQUIRED_ARGUMENT,
    315       "Include LIBDIR in the search path for required modules."],
    316     ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
    317       "Do not search parent directories for the Rakefile."],
    318     ['--quiet',    '-q', GetoptLong::NO_ARGUMENT,
    319       "Do not log messages to standard output (default)."],
    320     ['--rakefile', '-f', GetoptLong::REQUIRED_ARGUMENT,
    321       "Use FILE as the rakefile."],
    322     ['--require',  '-r', GetoptLong::REQUIRED_ARGUMENT,
    323       "Require MODULE before executing rakefile."],
    324     ['--tasks',    '-T', GetoptLong::NO_ARGUMENT,
    325       "Display the tasks and dependencies, then exit."],
    326     ['--pull-gems','-p', GetoptLong::NO_ARGUMENT,
    327       "Pull all git mrbgems."],
    328     ['--trace',    '-t', GetoptLong::NO_ARGUMENT,
    329       "Turn on invoke/execute tracing."],
    330     ['--usage',    '-h', GetoptLong::NO_ARGUMENT,
    331       "Display usage."],
    332     ['--verbose',  '-v', GetoptLong::NO_ARGUMENT,
    333       "Log message to standard output."],
    334     ['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT,
    335       "Change executing directory of rakefiles."]
    336   ]
    337 
    338   # Create a RakeApp object.
    339   def initialize
    340     @rakefile = nil
    341     @nosearch = false
    342   end
    343 
    344   # True if one of the files in RAKEFILES is in the current directory.
    345   # If a match is found, it is copied into @rakefile.
    346   def have_rakefile
    347     RAKEFILES.each do |fn|
    348       if File.exist?(fn)
    349         @rakefile = fn
    350         return true
    351       end
    352     end
    353     return false
    354   end
    355 
    356   # Display the program usage line.
    357   def usage
    358       puts "rake [-f rakefile] {options} targets..."
    359   end
    360 
    361   # Display the rake command line help.
    362   def help
    363     usage
    364     puts
    365     puts "Options are ..."
    366     puts
    367     OPTIONS.sort.each do |long, short, mode, desc|
    368       if mode == GetoptLong::REQUIRED_ARGUMENT
    369         if desc =~ /\b([A-Z]{2,})\b/
    370           long = long + "=#{$1}"
    371         end
    372       end
    373       printf "  %-20s (%s)\n", long, short
    374       printf "      %s\n", desc
    375     end
    376   end
    377 
    378   # Display the tasks and dependencies.
    379   def display_tasks
    380     MiniRake::Task.tasks.each do |t|
    381       puts "#{t.class} #{t.name}"
    382       t.prerequisites.each { |pre| puts "    #{pre}" }
    383     end
    384   end
    385 
    386   # Return a list of the command line options supported by the
    387   # program.
    388   def command_line_options
    389     OPTIONS.collect { |lst| lst[0..-2] }
    390   end
    391 
    392   # Do the option defined by +opt+ and +value+.
    393   def do_option(opt, value)
    394     case opt
    395     when '--dry-run'
    396       $dryrun = true
    397       $trace = true
    398     when '--help'
    399       help
    400       exit
    401     when '--libdir'
    402       $:.push(value)
    403     when '--nosearch'
    404       @nosearch = true
    405     when '--quiet'
    406       $verbose = false
    407     when '--rakefile'
    408       RAKEFILES.clear
    409       RAKEFILES << value
    410     when '--require'
    411       require value
    412     when '--tasks'
    413       $show_tasks = true
    414     when '--pull-gems'
    415       $pull_gems = true
    416     when '--trace'
    417       $trace = true
    418     when '--usage'
    419       usage
    420       exit
    421     when '--verbose'
    422       $verbose = true
    423     when '--version'
    424       puts "rake, version #{RAKEVERSION}"
    425       exit
    426     when '--directory'
    427       Dir.chdir value
    428     else
    429       fail "Unknown option: #{opt}"
    430     end
    431   end
    432 
    433   # Read and handle the command line options.
    434   def handle_options
    435     $verbose = false
    436     $pull_gems = false
    437     opts = GetoptLong.new(*command_line_options)
    438     opts.each { |opt, value| do_option(opt, value) }
    439   end
    440 
    441   # Run the +rake+ application.
    442   def run
    443     handle_options
    444     begin
    445       here = Dir.pwd
    446       while ! have_rakefile
    447         Dir.chdir("..")
    448         if Dir.pwd == here || @nosearch
    449           fail "No Rakefile found (looking for: #{RAKEFILES.join(', ')})"
    450         end
    451         here = Dir.pwd
    452       end
    453       tasks = []
    454       ARGV.each do |task_name|
    455         if /^(\w+)=(.*)/.match(task_name)
    456           ENV[$1] = $2
    457         else
    458           tasks << task_name
    459         end
    460       end
    461       puts "(in #{Dir.pwd})"
    462       $rakefile = @rakefile
    463       load @rakefile
    464       if $show_tasks
    465         display_tasks
    466       else
    467         tasks.push("default") if tasks.size == 0
    468         tasks.each do |task_name|
    469           MiniRake::Task[task_name].invoke
    470         end
    471       end
    472     rescue Exception => ex
    473       puts "rake aborted!"
    474       puts ex.message
    475       if $trace
    476         puts ex.backtrace.join("\n")
    477       else
    478         puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
    479       end
    480       exit 1
    481     end
    482   end
    483 end
    484 
    485 if __FILE__ == $0 then
    486   RakeApp.new.run
    487 end
     1#! /usr/bin/env ruby
     2exec "rake", *ARGV
Note: See TracChangeset for help on using the changeset viewer.