1 class ExtensionCompiler
3 def initialize(extra=[], flags=[])
6 @compile_flags = ["-g"]
11 elsif e.prefix?("-C,")
12 @compile_flags << e[3..-1]
19 @preserve_objects = false
24 if m = /output=(.*)/.match(i)
29 @preserve_objects = true
34 @preserve_objects = true
37 if File.exists?("shotgun/lib/subtend/ruby.h")
38 @includes << "-I#{Dir.pwd}/shotgun/lib/subtend"
45 @output_name = file unless @output_name
48 def set_output(output)
52 def add_flag(flags, link=true)
56 @compile_flags << flags
61 @includes << "-I#{inc}"
67 m = /(.*)\.[^\.]+/.match(@output_name)
69 @output = "#{m[1]}.#{Rubinius::LIBSUFFIX}"
71 @output = "#{@output_name}.#{Rubinius::LIBSUFFIX}"
76 Rubinius::OS == :win32
80 Rubinius::COMPILER == :gcc
84 Rubinius::OS == :win32 and Rubinius::COMPILER == :microsoft
88 Rubinius::OS == :win32 and Rubinius::COMPILER == :gcc
92 Rubinius::OS == :cygwin
96 Rubinius::OS == :darwin
100 str = (@includes + @compile_flags).join(" ")
102 if Rubinius::PLATFORM == :amd64 || ( Rubinius::PLATFORM == :x86 && gcc? )
114 Rubinius::COMPILER_PATH
117 # Adapted from RubyInline
118 def system_link_options
120 "-link /LIBPATH:\"#{@libdir}\" /DEFAULTLIB:\"#{@lib}\" /INCREMENTAL:no /EXPORT:#{@init}"
122 "-Wl,--enable-auto-import -L#{@libdir}"
126 "-dynamic -bundle -undefined suppress -flat_namespace"
133 opts = @link_flags.dup
134 opts << system_link_options
136 return opts.join(" ")
141 @files.each do |file|
142 cmd = "#{compiler} #{compile_options} -c -o #{file}.o #{file}"
145 @objects << "#{file}.o"
149 def compile(report=true)
152 cmd = "#{compiler} #{link_options} #{@objects.join(' ')} -o #{@output}"
158 if File.exists?(@output)
159 unless @preserve_objects
160 puts "Cleaning up objects..."
161 @objects.each { |o| system "rm #{o}" }
164 puts "Created #{@output}" if report
167 puts "Unable to compile extension into #{@output}. Check compiler log."
184 Dir[glob].each { |f| @ec.add_file f }
188 args.each { |a| @ec.add_flag a }
192 args.each { |a| @ec.add_flag "-l#{a}", true }
196 args.each { |a| @ec.add_include a }
207 yield $ec_dsl if block_given?
216 while ARGV[0] and ARGV[0].prefix? "-f"
217 body = ARGV.shift[2..-1]
223 if body.prefix? 'rbx'
230 while ARGV[0] and ARGV[0].prefix? "-"
236 if File.directory?(file)
237 rec = File.join(file, "build.rb")
238 unless File.exists?(rec)
239 puts "No build instructions found in #{file}"
242 puts "Building from instructions at #{rec}" if $VERBOSE
243 ext = ExtensionCompiler.new(ext_flags, ARGV)
244 dsl = ExtensionCompiler::DSL.new(ext)
250 elsif file.suffix?(".c")
251 puts "Compiling extension #{file}..."
252 ext = ExtensionCompiler.new(ext_flags, ARGV)
256 if File.exists?(file)
258 out = ARGV.shift || "#{file}c"
260 unless flags.include? '-f'
261 if File.exists?(out) and File.mtime(out) > File.mtime(file)
262 puts "Output '#{out}' is newer, no compile needed."
267 if flags.include? "-e"
268 puts "Compiling (external) #{file}..."
269 require 'compiler/compiler'
270 cm = Compiler.compile_file file, rbx_flags
271 puts "Unable to compile '#{file}'" unless cm
272 Marshal.dump_to_file cm, out, Compile.version_number
274 puts "Compiling #{file}..."
275 compile(file, out, rbx_flags)
278 puts "Unable to compile '#{file}'"