$makes = [] $default = nil class Make def initialize(target, froms, args, block) @target = target @froms = froms @args = args @block = block end def string_target? @target.class == String end def match?(target) if string_target? @target == target else @target.match?(target) end end def try_build(target) reified_froms = string_target? ? @froms : reify_froms(target) reified_froms.each do |from| Make.make!(from) end if !!@args[:phony] || !File.exist?(target) || reified_froms.any? { |from| File.mtime(target) < File.mtime(from) } @block.call(target, reified_froms, @args) end end def reify_froms(target) match = @target.match(target) @froms.map do |from| if match.names.empty? from.gsub(/\$(\d+)/) {|m| match[m[1..].to_i]} else from.gsub(/\$#{match.names.join(?|)}/) {|m| match[m[1..]]} end end end def self.make!(target = nil) print "Making: " pp target if target.nil? target = ARGV.shift if target.nil? if $default.nil? puts "No target given and no default set" exit 1 else target = $default puts "Using default target: #{target}" end end end makes = $makes.select { |make| make.match?(target) } if makes.empty? puts "No valid target" else string_makes = makes.select(&:string_target?) if string_makes.empty? makes.first.try_build(target) else string_makes.first.try_build(target) end end end end def to(target, *froms, **args, &block) $makes << Make.new(target, froms, args, block) end def default(target) $default = target end