fill in CC, Program, Environment.process() to get simple builds working
This commit is contained in:
parent
5634b8856d
commit
760f698963
@ -4,6 +4,7 @@ require "rscons/environment"
|
||||
require "rscons/version"
|
||||
|
||||
require "rscons/monkey/module"
|
||||
require "rscons/monkey/string"
|
||||
|
||||
# default builders
|
||||
require "rscons/builders/cc"
|
||||
|
@ -3,5 +3,8 @@ module Rscons
|
||||
def initialize(env)
|
||||
@env = env
|
||||
end
|
||||
def default_variables(env)
|
||||
{}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,37 @@
|
||||
module Rscons
|
||||
class CC < Builder
|
||||
def default_variables(env)
|
||||
{
|
||||
'CC' => 'gcc',
|
||||
'CFLAGS' => [],
|
||||
'CPPFLAGS' => [],
|
||||
'OBJSUFFIX' => '.o',
|
||||
'CSUFFIX' => '.c',
|
||||
'CCDEPGEN' => ['-MMD', '-MF', '$DEPFILE'],
|
||||
'CCCOM' => ['$CC', '-c', '-o', '$TARGET', '$CCDEPGEN', '$CPPFLAGS', '$CFLAGS', '$SOURCES']
|
||||
}
|
||||
end
|
||||
|
||||
def produces?(target, source)
|
||||
target.has_suffix?(@env['OBJSUFFIX']) and source.has_suffix?(@env['CSUFFIX'])
|
||||
end
|
||||
|
||||
def run(target, sources, cache)
|
||||
unless cache.up_to_date?(target, sources)
|
||||
vars = {
|
||||
'TARGET' => target,
|
||||
'SOURCES' => sources,
|
||||
'DEPFILE' => target.set_suffix('.mf'),
|
||||
}
|
||||
@env.execute("CC #{target}", @env['CCCOM'], vars)
|
||||
deps = sources
|
||||
if File.exists?(vars['DEPFILE'])
|
||||
deps += @env.parse_makefile_deps(vars['DEPFILE'], target)
|
||||
FileUtils.rm_f(vars['DEPFILE'])
|
||||
end
|
||||
cache.register_build(target, deps.uniq)
|
||||
end
|
||||
target
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,19 +1,38 @@
|
||||
module Rscons
|
||||
class Program < Builder
|
||||
def default_variables
|
||||
def default_variables(env)
|
||||
{
|
||||
'CC' => 'gcc',
|
||||
'CFLAGS' => [],
|
||||
'CPPFLAGS' => [],
|
||||
'LD' => nil,
|
||||
'OBJSUFFIX' => '.o',
|
||||
'CSUFFIX' => '.c',
|
||||
'CCDEPGEN' => ['-MMD', '-MF', '$DEPFILE'],
|
||||
'CCCOM' => ['$CC', '-c', '-o', '$TARGET', '$CCDEPGEN', '$CPPFLAGS', '$CFLAGS', '$SOURCES']
|
||||
'LIBSUFFIX' => '.a',
|
||||
'LDFLAGS' => [],
|
||||
'LIBPATHS' => [],
|
||||
'LIBS' => [],
|
||||
'LDCOM' => ['$LD', '-o', '$TARGET', '$LDFLAGS', '$SOURCES', '-L$[LIBPATHS]', '-l$[LIBS]']
|
||||
}
|
||||
end
|
||||
|
||||
def produces?(target, source)
|
||||
target.has_suffix?(@env['OBJSUFFIX']) and source.has_suffix?(@env['CSUFFIX'])
|
||||
def run(target, sources, cache)
|
||||
# convert sources to object file names
|
||||
sources = sources.map do |source|
|
||||
if source.has_suffix?([@env['OBJSUFFIX'], @env['LIBSUFFIX']])
|
||||
source
|
||||
else
|
||||
o_file = source.set_suffix(@env['OBJSUFFIX', :string])
|
||||
builder = @env.builders.values.find { |b| b.produces?(o_file, source) }
|
||||
builder or raise "No builder found to convert input source #{source.inspect} to an object file."
|
||||
builder.run(o_file, [source], cache)
|
||||
end
|
||||
end
|
||||
unless cache.up_to_date?(target, sources)
|
||||
vars = {
|
||||
'TARGET' => target,
|
||||
'SOURCES' => sources,
|
||||
'LD' => @env['LD'] || @env['CC'], # TODO: figure out whether to use CC or CXX
|
||||
}
|
||||
@env.execute("LD #{target}", @env['LDCOM'], vars)
|
||||
end
|
||||
target
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -25,6 +25,7 @@ module Rscons
|
||||
|
||||
def up_to_date?(file, deps = nil)
|
||||
# TODO
|
||||
false
|
||||
end
|
||||
|
||||
def register_build(target, deps)
|
||||
|
@ -1,5 +1,9 @@
|
||||
require 'set'
|
||||
|
||||
module Rscons
|
||||
class Environment
|
||||
attr_reader :builders
|
||||
|
||||
class << self
|
||||
alias_method :orig_new, :new
|
||||
end
|
||||
@ -39,6 +43,12 @@ module Rscons
|
||||
|
||||
def add_builder(builder)
|
||||
@builders[builder.class.short_name] = builder
|
||||
var_defs = builder.default_variables(self)
|
||||
if var_defs
|
||||
var_defs.each_pair do |var, val|
|
||||
@variables[var] ||= val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def [](key, type = nil)
|
||||
@ -58,15 +68,70 @@ module Rscons
|
||||
|
||||
def process
|
||||
cache = Cache.new
|
||||
targets_processed = Set.new
|
||||
process_target = proc do |target|
|
||||
sources_built = @targets[target][:source].map do |src|
|
||||
targets_processed.include?(src) or not @targets.include?(src) or process_target.call(src)
|
||||
end.all?
|
||||
if sources_built
|
||||
@targets[target][:builder].run(target,
|
||||
@targets[target][:source],
|
||||
cache,
|
||||
*@targets[target][:args])
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
@targets.each do |target, info|
|
||||
next if targets_processed.include?(target)
|
||||
break unless process_target.call(target)
|
||||
end
|
||||
cache.write
|
||||
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 =~ /^\$(.*)$/
|
||||
# expand a single variable reference
|
||||
varname = $1
|
||||
varval = merged_variables[varname]
|
||||
varval or raise "Could not find variable #{varname.inspect}"
|
||||
expand_varref.call(varval)
|
||||
else
|
||||
varref
|
||||
end
|
||||
end
|
||||
end
|
||||
command = expand_varref.call(command.flatten).flatten
|
||||
if @echo == :command
|
||||
puts command.map { |c| c =~ /\s/ ? "'#{c}'" : c }.join(' ')
|
||||
elsif @echo == :short
|
||||
puts short_desc
|
||||
end
|
||||
system(*command)
|
||||
end
|
||||
|
||||
alias_method :orig_method_missing, :method_missing
|
||||
def method_missing(method, *args)
|
||||
if @builders.has_key?(method.to_s)
|
||||
target, source, *rest = args
|
||||
source = [source] unless source.is_a?(Array)
|
||||
@targets[target] = {
|
||||
builder: method.to_s,
|
||||
builder: @builders[method.to_s],
|
||||
source: source,
|
||||
args: rest,
|
||||
}
|
||||
@ -74,5 +139,24 @@ module Rscons
|
||||
orig_method_missing(method, *args)
|
||||
end
|
||||
end
|
||||
|
||||
def parse_makefile_deps(mf_fname, target)
|
||||
deps = []
|
||||
buildup = ''
|
||||
File.read(mf_fname).each_line do |line|
|
||||
if line =~ /^(.*)\\\s*$/
|
||||
buildup += ' ' + $1
|
||||
else
|
||||
if line =~ /^(.*): (.*)$/
|
||||
target, tdeps = $1.strip, $2
|
||||
if target == target
|
||||
deps += tdeps.split(' ').map(&:strip)
|
||||
end
|
||||
end
|
||||
buildup = ''
|
||||
end
|
||||
end
|
||||
deps
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user