Re-enable spec/library for full CI runs.
[rbx.git] / rakelib / rubinius.rb
blobb5c3911321cd4d3dd0a9f8f5318f8f9e07847270
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 current_dir = File.dirname File.expand_path(__FILE__)
46 RBX_BIN_PATH = File.join File.dirname(current_dir), 'bin', 'rbx'
48 def rbx(*args)
49   clear_compiler
51   sh(RBX_BIN_PATH, *args)
52 end
54 class Hash
55   include TSort
57   # This keeps things consistent across all platforms
58   def tsort_each_node(&block)
59     keys.sort.each(&block)
60   end
62   def tsort_each_child(node, &block)
63     fetch(node).each(&block)
64   end
65 end
67 def newer?(file, cmp)
68   File.exists?(cmp) and File.mtime(cmp) >= File.mtime(file)
69 end
71 def source_name(compiled)
72   File.basename(compiled, '.*') + '.rb'
73 end
75 def compiled_name(source, dir)
76   File.join(dir, File.basename(source, '.*') + '.rbc')
77 end
79 # Some files have load order dependencies. To specify a load order
80 # dependency, include a comment in the file that has the dependency.
81 # For example, assume files a.rb and b.rb, where a.rb requires that
82 # b.rb is loaded first. In a.rb, include a comment
83 #   # depends on: b.rb
85 # The 'depends on:' declaration takes a space separated list of file.
86 # When the '.load_order.txt' file is created, a topological sort
87 # (see name caveat in TSort) of the dependencies is performed
88 # so files that are depended on are loaded first.
90 # If there is a 'depends on:' declarations for a non-existent file,
91 # or if there are cyclic dependencies, this method will not create
92 # the '.load_order.txt' file.
94 def create_load_order(files, output=".load_order.txt")
95   d = Hash.new { |h,k| h[k] = [] }
97   # assume all the files are in the same directory
98   dir = File.dirname(files.first)
99   found = false
100   files.each do |fname|
101     name = source_name(fname)
102     # Force every entry to be in the hash
103     d[name]
104     File.open(File.join(dir, name), "r") do |f|
105       f.each do |line|
106         if m = /#\s*depends on:\s*(.*)/.match(line)
107           found = true
108           m[1].split.each { |dep| d[name] << dep }
109         end
110       end
111     end
112   end
114   puts "Generating #{output}..."
116   File.open(output, "w") do |f|
117     begin
118       if found
119         list = d.tsort
120       else
121         list = files.sort
122       end
124       f.puts list.collect { |n| compiled_name(n, dir) }.join("\n")
125     rescue IndexError => e
126       puts "Unable to generate '.load_order.txt'"
127       puts "Most likely, a file includes a 'depends on:' declaration for a non-existent file"
128       raise e
129     rescue TSort::Cyclic => e
130       puts "Unable to generate '.load_order.txt' due to a cyclic dependency\n  (#{e.message})"
131       raise e
132     end
133   end
136 def compile(name, output=nil, check_mtime=false)
137   if output
138     dir = File.dirname(output)
140     unless File.exists?(dir)
141       FileUtils.mkdir_p dir
142     end
144     if check_mtime and File.exists?(output) and File.mtime(output) > File.mtime(name)
145       return
146     end
147   end
148   
149   inc = "-Iruntime/stable/compiler.rba -rcompiler/init"
150   flags = "-frbx-safe-math -frbx-kernel"
152   if ENV['GDB']
153     sh "shotgun/rubinius --gdb #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
154   else
155     sh "shotgun/rubinius #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
156   end
159 def compile_dir(dir)
160   (Dir["#{dir}/*.rb"] + Dir["#{dir}/**/*.rb"]).each do |file|
161     compile file, "#{file}c", true
162   end
165 class CodeGroup
167   def initialize(files, compile_dir, rba_name, load_order=true)
168     if files.is_a?(FileList)
169       @files = files
170     else
171       @files = FileList[files]
172     end
174     @output = nil
175     @compile_dir = compile_dir
176     @build_dir = File.join 'runtime', rba_name
177     @rba_name = "#{rba_name}.rba"
179     if load_order
180       @load_order = File.join @compile_dir, '.load_order.txt'
181     else
182       @load_order = nil
183     end
185     @output = []
187     make_tasks
188   end
190   attr_reader :output
192   def clean
193     sh "find #{@compile_dir} -name '*.rbc' -delete"
194   end
196   def compile_task
197     @files.each do |source|
198       runtime = File.join(@compile_dir, source.ext("rbc"))
200       @output << runtime
202       deps = [source].compact
204       file runtime => deps do |t|
205         compile t.prerequisites.first, t.name
206       end
207     end
208   end
210   def load_order_task
211     return unless @load_order
213     file @load_order => @files do
214       create_load_order(@files, @load_order)
215     end
216     task "build:load_order" => @files do
217       create_load_order(@files, @load_order)
218     end
220     @output << @load_order
221   end
223   def make_tasks
224     Dir.mkdir @compile_dir unless File.exists? @compile_dir
226     compile_task
227     load_order_task
228     rba_task
230     @output
231   end
233   def rba_task
234     file File.join('runtime', 'stable', @rba_name) => @output do
235       files = @output.map do |path|
236         path.sub File.join(@build_dir, ''), ''
237       end
239       Dir.chdir @build_dir do
240         ar_name = File.join '..', 'stable', @rba_name
241         rm_f ar_name, :verbose => $verbose
243         File.readlines('.load_order.txt').each do |file|
244           ar_add ar_name, file.strip
245         end
246       end
247     end
248   end
252 def install_files(files, destination)
253   files.sort.each do |path|
254     next if File.directory? path
256     file = path.sub %r%^(runtime|lib)/%, ''
257     dest_file = File.join destination, file
258     dest_dir = File.dirname dest_file
259     mkdir_p dest_dir unless File.directory? dest_dir
261     install path, dest_file, :mode => 0644, :verbose => true
262   end