Permalink
Browse files

Compile the kernel, and load it in

Add loading of the kernel to driver/cli.cpp. Add tasks to compile the
kernel, use 'rake kernel:build'
  • Loading branch information...
1 parent 9901699 commit d19313c43f71c7da02c0b2a9db3313ce1411ebdb Evan Phoenix committed Aug 1, 2008
View
@@ -0,0 +1,122 @@
+# All the tasks to manage the kernel
+
+# Some files have load order dependencies. To specify a load order
+# dependency, include a comment in the file that has the dependency.
+# For example, assume files a.rb and b.rb, where a.rb requires that
+# b.rb is loaded first. In a.rb, include a comment
+# # depends on: b.rb
+#
+# The 'depends on:' declaration takes a space separated list of file.
+# When the '.load_order.txt' file is created, a topological sort
+# (see name caveat in TSort) of the dependencies is performed
+# so files that are depended on are loaded first.
+#
+# If there is a 'depends on:' declarations for a non-existent file,
+# or if there are cyclic dependencies, this method will not create
+# the '.load_order.txt' file.
+
+require 'tsort'
+
+class Hash
+ include TSort
+
+ # This keeps things consistent across all platforms
+ def tsort_each_node(&block)
+ keys.sort.each(&block)
+ end
+
+ def tsort_each_child(node, &block)
+ fetch(node).each(&block)
+ end
+end
+
+def create_load_order(files, output=".load_order.txt")
+ d = Hash.new { |h,k| h[k] = [] }
+
+ # assume all the files are in the same directory
+ dir = File.dirname(files.first)
+ found = false
+ files.each do |fname|
+ name = File.basename(fname)
+ # Force every entry to be in the hash
+ d[name]
+ File.open(File.join(dir, name), "r") do |f|
+ f.each do |line|
+ if m = /#\s*depends on:\s*(.*)/.match(line)
+ found = true
+ m[1].split.each { |dep| d[name] << dep }
+ end
+ end
+ end
+ end
+
+ puts "Generating #{output}..."
+
+ File.open(output, "w") do |f|
+ begin
+ if found
+ list = d.tsort
+ else
+ list = files.sort
+ end
+
+ list.each do |n|
+ f.puts File.basename(n, ".*") + ".rbc"
+ end
+ rescue IndexError => e
+ puts "Unable to generate '.load_order.txt'"
+ puts "Most likely, a file includes a 'depends on:' declaration for a non-existent file"
+ raise e
+ rescue TSort::Cyclic => e
+ puts "Unable to generate '.load_order.txt' due to a cyclic dependency\n (#{e.message})"
+ raise e
+ end
+ end
+end
+
+loose = []
+modules = Hash.new { |h,k| h[k] = [] }
+
+Dir["kernel/**/*.rb"].each do |path|
+ _, mod, file = path.split("/")
+
+ if file
+ modules[mod] << path
+ else
+ loose << mod
+ end
+end
+
+@all_kernel = []
+
+modules.each do |name, files|
+ files.each do |file|
+ compiled = "runtime/#{name}/#{File.basename(file)}c"
+ @all_kernel << compiled
+
+ file compiled => file
+ end
+end
+
+rule ".rbc" do |t|
+ rbc = t.name
+ src = t.prerequisites.first
+
+ dir = File.dirname(rbc)
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
+
+ ruby "lib/compiler/mri_compile.rb -frbx-kernel #{src} #{rbc}"
+end
+
+namespace :kernel do
+ task :show do
+ p modules
+ p loose
+ end
+
+ task :build => @all_kernel do
+ modules.each do |name, files|
+ create_load_order files, "runtime/#{name}/.load_order.txt"
+ end
+ end
+end
View
@@ -40,19 +40,6 @@ def rbx(*args)
sh('shotgun/rubinius', *args)
end
-class Hash
- include TSort
-
- # This keeps things consistent across all platforms
- def tsort_each_node(&block)
- keys.sort.each(&block)
- end
-
- def tsort_each_child(node, &block)
- fetch(node).each(&block)
- end
-end
-
def newer?(file, cmp)
File.exists?(cmp) and File.mtime(cmp) >= File.mtime(file)
end
@@ -65,62 +52,6 @@ def compiled_name(source, dir)
File.join(dir, File.basename(source, '.*') + '.rbc')
end
-# Some files have load order dependencies. To specify a load order
-# dependency, include a comment in the file that has the dependency.
-# For example, assume files a.rb and b.rb, where a.rb requires that
-# b.rb is loaded first. In a.rb, include a comment
-# # depends on: b.rb
-#
-# The 'depends on:' declaration takes a space separated list of file.
-# When the '.load_order.txt' file is created, a topological sort
-# (see name caveat in TSort) of the dependencies is performed
-# so files that are depended on are loaded first.
-#
-# If there is a 'depends on:' declarations for a non-existent file,
-# or if there are cyclic dependencies, this method will not create
-# the '.load_order.txt' file.
-
-def create_load_order(files, output=".load_order.txt")
- d = Hash.new { |h,k| h[k] = [] }
-
- # assume all the files are in the same directory
- dir = File.dirname(files.first)
- found = false
- files.each do |fname|
- name = source_name(fname)
- # Force every entry to be in the hash
- d[name]
- File.open(File.join(dir, name), "r") do |f|
- f.each do |line|
- if m = /#\s*depends on:\s*(.*)/.match(line)
- found = true
- m[1].split.each { |dep| d[name] << dep }
- end
- end
- end
- end
-
- puts "Generating #{output}..."
-
- File.open(output, "w") do |f|
- begin
- if found
- list = d.tsort
- else
- list = files.sort
- end
-
- f.puts list.collect { |n| compiled_name(n, dir) }.join("\n")
- rescue IndexError => e
- puts "Unable to generate '.load_order.txt'"
- puts "Most likely, a file includes a 'depends on:' declaration for a non-existent file"
- raise e
- rescue TSort::Cyclic => e
- puts "Unable to generate '.load_order.txt' due to a cyclic dependency\n (#{e.message})"
- raise e
- end
- end
-end
def compile(name, output=nil, check_mtime=false)
if output
View
@@ -24,8 +24,8 @@ TYPE_GEN = %w[ vm/gen/simple_field.rb
vm/gen/typechecks.gen.cpp
vm/gen/primitives_declare.hpp
vm/gen/primitives_glue.gen.cpp ]
-OTHER_GEN = %w[ vm/instructions.cpp ]
+BC = "vm/instructions.bc"
LLVM_A = "vm/external_libs/llvm/Release/lib/libLLVMSystem.a"
EXTERNALS = %W[ #{LLVM_A}
vm/external_libs/libtommath/libtommath.a
@@ -39,10 +39,11 @@ OPTIONS = {
INCLUDES = (EX_INC + %w[vm/test/cxxtest vm .]).map { |f| "-I#{f}" }
FLAGS = %w(-Wall -ggdb -gdwarf-2)
+CC = ENV['CC'] || "gcc"
+
FLAGS << "-O2" if ENV['FAST']
-CC = ENV['CC'] || "gcc"
def compile(obj, src)
unless defined? $llvm_c then
@@ -52,9 +53,30 @@ def compile(obj, src)
flags = (INCLUDES + FLAGS + $llvm_c).join(' ')
- sh "#{CC} #{flags} -c -o #{obj} #{src} 2>&1"
+ if ENV['TERSE']
+ puts "CC #{src}"
+ sh "#{CC} #{flags} -c -o #{obj} #{src} 2>&1", :verbose => false
+ else
+ sh "#{CC} #{flags} -c -o #{obj} #{src} 2>&1"
+ end
end
+def link t
+ $link_opts ||= `#{LLVM_CONFIG} --ldflags`.split(/\s+/).join(' ')
+
+ ld = ENV['LD'] || 'g++'
+ o = t.prerequisites.find_all { |f| f =~ /o$/ }.join(' ')
+ l = ex_libs.join(' ')
+
+ if ENV['TERSE']
+ puts "LD #{t.name}"
+ sh "#{ld} #{$link_opts} -o #{t.name} #{o} #{l}", :verbose => false
+ else
+ sh "#{ld} #{$link_opts} -o #{t.name} #{o} #{l}"
+ end
+end
+
+
############################################################
# Other Tasks
@@ -85,7 +107,7 @@ objs.zip(srcs).each do |obj, src|
file obj => src
end
-objs += ["vm/instructions.o"]
+objs += ["vm/instructions.o", BC]
files EXTERNALS do |t|
path = File.join(*split_all(t.name)[0..2])
@@ -98,6 +120,7 @@ files EXTERNALS do |t|
end
end
+file "vm/primitives.o" => "vm/field_extract.rb"
file 'vm/instructions_gen.rb' => 'kernel/core/iseq.rb'
file 'vm/instructions.rb' => %w[vm/gen vm/instructions_gen.rb]
@@ -129,16 +152,28 @@ file 'vm/test/runner' => EXTERNALS + objs + %w[vm/test/runner.o] do |t|
link t
end
-file 'vm/instructions.cpp' => %w[vm/llvm/instructions.cpp vm/rubypp.rb] do
- ruby 'vm/rubypp.rb vm/llvm/instructions.cpp vm/instructions.cpp'
+require 'tmpdir'
+
+def tmpname(suffix="cpp")
+ @which ||= 0
+
+ path = File.join(Dir.tmpdir, "rake.#{$$}.#{@which += 1}.#{suffix}")
+
+ at_exit { FileUtils.rm_rf(path) }
+
+ return path
end
-file 'vm/instructions.o' => 'vm/instructions.cpp' do
- compile 'vm/instructions.o', 'vm/instructions.cpp'
+file 'vm/instructions.o' => 'vm/llvm/instructions.cpp' do
+ path = tmpname()
+ ruby "vm/rubypp.rb vm/llvm/instructions.cpp #{path}"
+ compile 'vm/instructions.o', path
end
-file 'vm/instructions.bc' => 'vm/instructions.cpp' do
- sh 'llvm-g++ -emit-llvm -Ivm -Ivm/external_libs/libffi/include -c -o vm/instructions.bc vm/instructions.cpp', :verbose => true
+file 'vm/instructions.bc' => 'vm/llvm/instructions.cpp' do
+ path = tmpname()
+ ruby "vm/rubypp.rb vm/llvm/instructions.cpp #{path}"
+ sh "llvm-g++ -emit-llvm -Ivm -Ivm/external_libs/libffi/include -c -o vm/instructions.bc #{path}"
end
namespace :vm do
@@ -151,7 +186,7 @@ namespace :vm do
desc "Clean up vm build files"
task :clean do
files = [
- objs, dep_file, TYPE_GEN, INSN_GEN, OTHER_GEN,
+ objs, dep_file, TYPE_GEN, INSN_GEN,
'vm/gen',
'vm/test/runner',
'vm/test/runner.cpp',
@@ -192,7 +227,7 @@ end
require 'rake/loaders/makefile'
-generated = (TYPE_GEN + INSN_GEN + OTHER_GEN).select { |f| f =~ /pp$/ }
+generated = (TYPE_GEN + INSN_GEN).select { |f| f =~ /pp$/ }
file dep_file => srcs + hdrs + vm_srcs + generated do |t|
includes = INCLUDES.join ' '
@@ -202,7 +237,6 @@ file dep_file => srcs + hdrs + vm_srcs + generated do |t|
cmd = "makedepend -f- #{includes} -- #{flags} -- #{t.prerequisites}"
cmd << ' 2>/dev/null' unless $verbose
- puts cmd
dep = `#{cmd}`
dep.gsub!(%r% /usr/include\S+%, '') # speeds up rake a lot
@@ -239,14 +273,3 @@ def field_extract
ruby('vm/field_extract.rb', *order)
end
-
-def link t
- $link_opts ||= `#{LLVM_CONFIG} --ldflags`.split(/\s+/).join(' ')
-
- ld = ENV['LD'] || 'g++'
- o = t.prerequisites.find_all { |f| f =~ /o$/ }.join(' ')
- l = ex_libs.join(' ')
-
- sh "#{ld} #{$link_opts} -o #{t.name} #{o} #{l}"
-end
-
View
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+ruby lib/compiler/mri_compile.rb -frbx-kernel $1 $1c
Oops, something went wrong.

0 comments on commit d19313c

Please sign in to comment.