module Rscons class Environment # Values: # :none - do not print anything # :short - rscons will print a short representation of the step # being performed # :command (default) - print the full command being executed attr_accessor :echo # Hash of Builder Name => Builder Class attr_reader :builders def initialize(options = {}) @echo = :command @variables = options.reject { |key, val| not key[0] =~ /[A-Z]/ } @builders = {} @build_dirs = {} unless @variables[:omit_default_builders] DEFAULT_BUILDERS.each do |builder_class| add_builder(builder_class) end end @echo = options[:echo] if options[:echo] end def add_builder(builder_class) @builders[builder_class.to_s.split(':').last] = builder_class var_defs = builder_class.default_variables(self) if var_defs var_defs.each_pair do |var, val| unless @variables.has_key?(var) @variables[var] = val end end end end def [](key) @variables[key] end def []=(key, val) @variables[key] = val end def build_dir(src_dir, build_dir) @build_dirs[src_dir] = build_dir end def execute(short_desc, command, extra_vars) merged_variables = @variables.merge(extra_vars) expand_varref = proc do |varref| if varref.is_a?(Array) varref.map do |ent| expand_varref.call(ent) end else if varref =~ /^(.*)\$\[(\w+)\](.*)$/ # expand array with given prefix, suffix prefix, varname, suffix = $1, $2, $3 varval = merged_variables[varname] unless varval.is_a?(Array) raise "Array expected for $#{varname}" end varval.map {|e| "#{prefix}#{e}#{suffix}"} elsif varref[0] == '$' # expand a single variable reference varname = varref[1, varref.size] varval = merged_variables[varname] if varval expand_varref.call(varval) else raise "Could not find variable #{varname.inspect}" end else varref end end end command = expand_varref.call(command.flatten).flatten if @echo == :command puts command.join(' ') elsif @echo == :short puts short_desc end system(*command) end def stem(fname) fname.sub(/\.[^.]*$/, '') end alias_method :orig_method_missing, :method_missing def method_missing(method, *args) if @builders.has_key?(method.to_s) # TODO: build sources if necessary builder = @builders[method.to_s].new builder.run(self, *args) else orig_method_missing(method, *args) end end end end