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}"
45 current_dir = File.dirname File.expand_path(__FILE__)
46 RBX_BIN_PATH = File.join File.dirname(current_dir), 'bin', 'rbx'
51 sh(RBX_BIN_PATH, *args)
57 # This keeps things consistent across all platforms
58 def tsort_each_node(&block)
59 keys.sort.each(&block)
62 def tsort_each_child(node, &block)
63 fetch(node).each(&block)
68 File.exists?(cmp) and File.mtime(cmp) >= File.mtime(file)
71 def source_name(compiled)
72 File.basename(compiled, '.*') + '.rb'
75 def compiled_name(source, dir)
76 File.join(dir, File.basename(source, '.*') + '.rbc')
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
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)
100 files.each do |fname|
101 name = source_name(fname)
102 # Force every entry to be in the hash
104 File.open(File.join(dir, name), "r") do |f|
106 if m = /#\s*depends on:\s*(.*)/.match(line)
108 m[1].split.each { |dep| d[name] << dep }
114 puts "Generating #{output}..."
116 File.open(output, "w") do |f|
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"
129 rescue TSort::Cyclic => e
130 puts "Unable to generate '.load_order.txt' due to a cyclic dependency\n (#{e.message})"
136 def compile(name, output=nil, check_mtime=false)
138 dir = File.dirname(output)
140 unless File.exists?(dir)
141 FileUtils.mkdir_p dir
144 if check_mtime and File.exists?(output) and File.mtime(output) > File.mtime(name)
149 inc = "-Iruntime/stable/compiler.rba -rcompiler/init"
150 flags = "-frbx-safe-math -frbx-kernel"
153 sh "shotgun/rubinius --gdb #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
155 sh "shotgun/rubinius #{inc} compile #{flags} #{name} #{output}", :verbose => $verbose
160 (Dir["#{dir}/*.rb"] + Dir["#{dir}/**/*.rb"]).each do |file|
161 compile file, "#{file}c", true
167 def initialize(files, compile_dir, rba_name, load_order=true)
168 if files.is_a?(FileList)
171 @files = FileList[files]
175 @compile_dir = compile_dir
176 @build_dir = File.join 'runtime', rba_name
177 @rba_name = "#{rba_name}.rba"
180 @load_order = File.join @compile_dir, '.load_order.txt'
193 sh "find #{@compile_dir} -name '*.rbc' -delete"
197 @files.each do |source|
198 runtime = File.join(@compile_dir, source.ext("rbc"))
202 deps = [source].compact
204 file runtime => deps do |t|
205 compile t.prerequisites.first, t.name
211 return unless @load_order
213 file @load_order => @files do
214 create_load_order(@files, @load_order)
216 task "build:load_order" => @files do
217 create_load_order(@files, @load_order)
220 @output << @load_order
224 Dir.mkdir @compile_dir unless File.exists? @compile_dir
234 file File.join('runtime', 'stable', @rba_name) => @output do
235 files = @output.map do |path|
236 path.sub File.join(@build_dir, ''), ''
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
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