1 require 'kernel/core/ar'
5 def ar_add(ar_name, file_name)
6 puts "ar_add #{ar_name} #{file_name}" if $verbose
10 open file_name, 'rb' do |io|
17 ar.replace file_name, mtime, uid, gid, mode, io.read
22 ENV.delete 'RBX_BOOTSTRAP'
24 ENV.delete 'RBX_LOADER'
25 ENV.delete 'RBX_PLATFORM'
29 target = ENV['SPEC_TARGET'] || 'rubinius'
30 if target == 'rubinius'
31 system %(shotgun/rubinius -e 'puts "rubinius build: \#{Rubinius::BUILDREV}"')
37 if RUBY_PLATFORM =~ /bsd|solaris/
42 "#{ENV['MAKE'] || gmake} #{args}"
48 sh('shotgun/rubinius', *args)
54 # This keeps things consistent across all platforms
55 def tsort_each_node(&block)
56 keys.sort.each(&block)
59 def tsort_each_child(node, &block)
60 fetch(node).each(&block)
65 File.exists?(cmp) and File.mtime(cmp) >= File.mtime(file)
68 def source_name(compiled)
69 File.basename(compiled, '.*') + '.rb'
72 def compiled_name(source, dir)
73 File.join(dir, File.basename(source, '.*') + '.rbc')
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
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)
98 name = source_name(fname)
99 # Force every entry to be in the hash
101 File.open(File.join(dir, name), "r") do |f|
103 if m = /#\s*depends on:\s*(.*)/.match(line)
105 m[1].split.each { |dep| d[name] << dep }
111 puts "Generating #{output}..."
113 File.open(output, "w") do |f|
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"
126 rescue TSort::Cyclic => e
127 puts "Unable to generate '.load_order.txt' due to a cyclic dependency\n (#{e.message})"
133 def compile(name, output=nil, check_mtime=false)
135 dir = File.dirname(output)
137 unless File.exists?(dir)
138 FileUtils.mkdir_p dir
141 if check_mtime and File.exists?(output) and File.mtime(output) > File.mtime(name)
146 inc = "-Iruntime/stable/compiler.rba -rcompiler/init"
147 flags = "-frbx-safe-math -frbx-kernel"
150 sh "shotgun/rubinius --gdb #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
152 sh "shotgun/rubinius #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
157 (Dir["#{dir}/*.rb"] + Dir["#{dir}/**/*.rb"]).each do |file|
158 compile file, "#{file}c", true
164 def initialize(files, compile_dir, rba_name, load_order=true)
165 if files.is_a?(FileList)
168 @files = FileList[files]
172 @compile_dir = compile_dir
173 @build_dir = File.join 'runtime', rba_name
174 @rba_name = "#{rba_name}.rba"
177 @load_order = File.join @compile_dir, '.load_order.txt'
190 sh "find #{@compile_dir} -name '*.rbc' -delete"
194 @files.each do |source|
195 runtime = File.join(@compile_dir, source.ext("rbc"))
199 deps = [source].compact
201 file runtime => deps do |t|
202 compile t.prerequisites.first, t.name
208 return unless @load_order
210 file @load_order => @files do
211 create_load_order(@files, @load_order)
213 task "build:load_order" => @files do
214 create_load_order(@files, @load_order)
217 @output << @load_order
221 Dir.mkdir @compile_dir unless File.exists? @compile_dir
231 file File.join('runtime', 'stable', @rba_name) => @output do
232 files = @output.map do |path|
233 path.sub File.join(@build_dir, ''), ''
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
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