Added CROSS_COMPILING flag to rbconfig.
[rbx.git] / rakelib / rubinius.rb
blob9df75e8e54be5b19215cd90dd0dd158fb40946d1
1 require 'kernel/core/ar'
3 Ar.after_loaded # HACK
5 def ar_add(ar_name, file_name)
6   puts "ar_add #{ar_name} #{file_name}" if $verbose
8   ar = Ar.new ar_name
10   open file_name, 'rb' do |io|
11     stat  = io.stat
12     mtime = stat.mtime
13     uid   = stat.uid
14     gid   = stat.gid
15     mode  = stat.mode
17     ar.replace file_name, mtime, uid, gid, mode, io.read
18   end
19 end
21 def clear_compiler
22   ENV.delete 'RBX_BOOTSTRAP'
23   ENV.delete 'RBX_CORE'
24   ENV.delete 'RBX_LOADER'
25   ENV.delete 'RBX_PLATFORM'
26 end
28 def spec_target
29   target = ENV['SPEC_TARGET'] || 'rubinius'
30   if target == 'rubinius'
31     system %(shotgun/rubinius -e 'puts "rubinius build: \#{Rubinius::BUILDREV}"')
32   end
33   target
34 end
36 def make(args = nil)
37   if RUBY_PLATFORM =~ /bsd|solaris/
38     gmake = 'gmake'
39   else
40     gmake = 'make'
41   end
42   "#{ENV['MAKE'] || gmake} #{args}"
43 end
45 def rbx(*args)
46   clear_compiler
48   sh('shotgun/rubinius', *args)
49 end
51 class Hash
52   include TSort
54   # This keeps things consistent across all platforms
55   def tsort_each_node(&block)
56     keys.sort.each(&block)
57   end
59   def tsort_each_child(node, &block)
60     fetch(node).each(&block)
61   end
62 end
64 def newer?(file, cmp)
65   File.exists?(cmp) and File.mtime(cmp) >= File.mtime(file)
66 end
68 def source_name(compiled)
69   File.basename(compiled, '.*') + '.rb'
70 end
72 def compiled_name(source, dir)
73   File.join(dir, File.basename(source, '.*') + '.rbc')
74 end
76 # Some files have load order dependencies. To specify a load order
77 # dependency, include a comment in the file that has the dependency.
78 # For example, assume files a.rb and b.rb, where a.rb requires that
79 # b.rb is loaded first. In a.rb, include a comment
80 #   # depends on: b.rb
82 # The 'depends on:' declaration takes a space separated list of file.
83 # When the '.load_order.txt' file is created, a topological sort
84 # (see name caveat in TSort) of the dependencies is performed
85 # so files that are depended on are loaded first.
87 # If there is a 'depends on:' declarations for a non-existent file,
88 # or if there are cyclic dependencies, this method will not create
89 # the '.load_order.txt' file.
91 def create_load_order(files, output=".load_order.txt")
92   d = Hash.new { |h,k| h[k] = [] }
94   # assume all the files are in the same directory
95   dir = File.dirname(files.first)
96   found = false
97   files.each do |fname|
98     name = source_name(fname)
99     # Force every entry to be in the hash
100     d[name]
101     File.open(File.join(dir, name), "r") do |f|
102       f.each do |line|
103         if m = /#\s*depends on:\s*(.*)/.match(line)
104           found = true
105           m[1].split.each { |dep| d[name] << dep }
106         end
107       end
108     end
109   end
111   puts "Generating #{output}..."
113   File.open(output, "w") do |f|
114     begin
115       if found
116         list = d.tsort
117       else
118         list = files.sort
119       end
121       f.puts list.collect { |n| compiled_name(n, dir) }.join("\n")
122     rescue IndexError => e
123       puts "Unable to generate '.load_order.txt'"
124       puts "Most likely, a file includes a 'depends on:' declaration for a non-existent file"
125       raise e
126     rescue TSort::Cyclic => e
127       puts "Unable to generate '.load_order.txt' due to a cyclic dependency\n  (#{e.message})"
128       raise e
129     end
130   end
133 def compile(name, output=nil, check_mtime=false)
134   if output
135     dir = File.dirname(output)
137     unless File.exists?(dir)
138       FileUtils.mkdir_p dir
139     end
141     if check_mtime and File.exists?(output) and File.mtime(output) > File.mtime(name)
142       return
143     end
144   end
145   
146   inc = "-Iruntime/stable/compiler.rba -rcompiler/init"
147   flags = "-frbx-safe-math -frbx-kernel"
149   if ENV['GDB']
150     sh "shotgun/rubinius --gdb #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
151   else
152     sh "shotgun/rubinius #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
153   end
156 def compile_dir(dir)
157   (Dir["#{dir}/*.rb"] + Dir["#{dir}/**/*.rb"]).each do |file|
158     compile file, "#{file}c", true
159   end
162 class CodeGroup
164   def initialize(files, compile_dir, rba_name, load_order=true)
165     if files.is_a?(FileList)
166       @files = files
167     else
168       @files = FileList[files]
169     end
171     @output = nil
172     @compile_dir = compile_dir
173     @build_dir = File.join 'runtime', rba_name
174     @rba_name = "#{rba_name}.rba"
176     if load_order
177       @load_order = File.join @compile_dir, '.load_order.txt'
178     else
179       @load_order = nil
180     end
182     @output = []
184     make_tasks
185   end
187   attr_reader :output
189   def clean
190     sh "find #{@compile_dir} -name '*.rbc' -delete"
191   end
193   def compile_task
194     @files.each do |source|
195       runtime = File.join(@compile_dir, source.ext("rbc"))
197       @output << runtime
199       deps = [source].compact
201       file runtime => deps do |t|
202         compile t.prerequisites.first, t.name
203       end
204     end
205   end
207   def load_order_task
208     return unless @load_order
210     file @load_order => @files do
211       create_load_order(@files, @load_order)
212     end
213     task "build:load_order" => @files do
214       create_load_order(@files, @load_order)
215     end
217     @output << @load_order
218   end
220   def make_tasks
221     Dir.mkdir @compile_dir unless File.exists? @compile_dir
223     compile_task
224     load_order_task
225     rba_task
227     @output
228   end
230   def rba_task
231     file File.join('runtime', 'stable', @rba_name) => @output do
232       files = @output.map do |path|
233         path.sub File.join(@build_dir, ''), ''
234       end
236       Dir.chdir @build_dir do
237         ar_name = File.join '..', 'stable', @rba_name
238         rm_f ar_name, :verbose => $verbose
240         File.readlines('.load_order.txt').each do |file|
241           ar_add ar_name, file.strip
242         end
243       end
244     end
245   end
249 def install_files(files, destination)
250   files.sort.each do |path|
251     next if File.directory? path
253     file = path.sub %r%^(runtime|lib)/%, ''
254     dest_file = File.join destination, file
255     dest_dir = File.dirname dest_file
256     mkdir_p dest_dir unless File.directory? dest_dir
258     install path, dest_file, :mode => 0644, :verbose => true
259   end