diff --git a/build_tests/c-simple/spec.rb b/build_tests/c-simple/spec.rb index 512f4d1..a3877b2 100644 --- a/build_tests/c-simple/spec.rb +++ b/build_tests/c-simple/spec.rb @@ -1,5 +1,6 @@ it 'builds a C program with one source file' do env = Rscons::Environment.new env.Program('simple', 'simple.c') + File.exist?('simple.o').should be_true `./simple`.should =~ /This is a simple C program/ end diff --git a/lib/rscons/builder.rb b/lib/rscons/builder.rb index 38c3ba7..fe54565 100644 --- a/lib/rscons/builder.rb +++ b/lib/rscons/builder.rb @@ -1,4 +1,7 @@ module Rscons class Builder + def self.makes_object_file?(env, fname) + false + end end end diff --git a/lib/rscons/builders/cc.rb b/lib/rscons/builders/cc.rb index 98f48a2..aba0805 100644 --- a/lib/rscons/builders/cc.rb +++ b/lib/rscons/builders/cc.rb @@ -2,12 +2,30 @@ module Rscons class CC < Builder VARIABLE_DEFAULTS = { 'CC' => 'gcc', - 'CFLAGS' => [], + 'CFLAGS' => ['-c'], 'CPPFLAGS' => [], 'OBJSUFFIX' => '.o', + 'CEXTS' => ['.c'], } - def run(env, target, sources) + def self.makes_object_file?(env, fname) + env['CEXTS'].find do |cext| + fname =~ /#{cext}$/ + end + end + + def run(env, target, source) + raise "String expected, not #{source.inspect}" unless source.is_a?(String) + o_file = "#{env.stem(source)}#{env['OBJSUFFIX']}" + command = [ + env['CC'], + *env['CPPFLAGS'], + *env['CFLAGS'], + '-o', o_file, + source + ] + env.execute("CC #{o_file}", command) + o_file end end end diff --git a/lib/rscons/builders/program.rb b/lib/rscons/builders/program.rb index 45b978d..0ecbc10 100644 --- a/lib/rscons/builders/program.rb +++ b/lib/rscons/builders/program.rb @@ -10,6 +10,20 @@ module Rscons } def run(env, target, sources) + sources = [sources] if sources.is_a?(String) + sources = sources.map do |source| + if source =~ /#{env['OBJSUFFIX']}$/ or source =~ /#{env['LIBSUFFIX']}$/ + source + else + builder_class = env.builders.values.find { |klass| klass.makes_object_file?(env, source) } + if builder_class + builder = builder_class.new + builder.run(env, env.stem(source) + env['OBJSUFFIX'], source) + else + raise "No builder found to convert input source #{source.inspect} to an object file." + end + end + end command = [ env['LD'] || env['CC'], '-o', target, @@ -19,6 +33,7 @@ module Rscons *env['LIBS'].map {|lib| "-l#{lib}"} ] env.execute("LINK #{target}", command) + target end end end diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index 50cb671..65b3f89 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -7,6 +7,9 @@ module Rscons # :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]/ } @@ -53,6 +56,10 @@ module Rscons system(*command) end + def stem(fname) + fname.sub(/\.[^.]*$/, '') + end + def method_missing(method, *args) if @builders.has_key?(method.to_s) # TODO: build sources if necessary