From 05458921fbda9cef2a61b85648e7baf9dd84ffcf Mon Sep 17 00:00:00 2001 From: Laurent Sansonetti Date: Thu, 14 Jul 2011 17:01:45 -0700 Subject: [PATCH] integrate library --- Rakefile | 23 +++++++ data/Rakefile | 33 +++++++++ doc/Rakefile | 11 +++ lib/rubixir/rake.rb | 42 ++++++++++++ lib/rubixir/rake/builder.rb | 133 ++++++++++++++++++++++++++++++++++++ lib/rubixir/rake/config.rb | 25 +++++++ sample/hello/Rakefile | 4 ++ sample/hello/app/main.rb | 40 +++++++++++ 8 files changed, 311 insertions(+) create mode 100644 Rakefile create mode 100644 data/Rakefile create mode 100644 doc/Rakefile create mode 100644 lib/rubixir/rake.rb create mode 100644 lib/rubixir/rake/builder.rb create mode 100644 lib/rubixir/rake/config.rb create mode 100644 sample/hello/Rakefile create mode 100644 sample/hello/app/main.rb diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..f79e5959 --- /dev/null +++ b/Rakefile @@ -0,0 +1,23 @@ +PLATFORMS_DIR = '/Developer/Platforms' +SDK_VERSION = '4.3' + +def rake(dir, cmd='all') + Dir.chdir(dir) do + sh "rake platforms_dir=#{PLATFORMS_DIR} sdk_version=#{SDK_VERSION} #{cmd}" + end +end + +targets = %w{vm data doc} + +task :default => :all +task :all => targets + +targets.each do |target| + task target do + rake(target) + end +end + +task :clean do + targets.each { |target| rake(target, 'clean') } +end diff --git a/data/Rakefile b/data/Rakefile new file mode 100644 index 00000000..89ec1b8f --- /dev/null +++ b/data/Rakefile @@ -0,0 +1,33 @@ +platforms_dir = ENV['platforms_dir'] +sdk_version = ENV['sdk_version'] + +task :default => :all +task :all => [:vm_files, :bridgesupport] + +task :vm_files do + install '../vm/miniruby', 'ruby' + install '/usr/local/bin/llc', 'llc' + mkdir_p 'iPhoneOS' + install '../vm/.ios-objs/kernel-armv6.bc', 'iPhoneOS' + install '../vm/.ios-objs/kernel-armv7.bc', 'iPhoneOS' + install '../vm/.ios-objs/libmacruby-static.a', 'iPhoneOS' + mkdir_p 'iPhoneSimulator' + install '../vm/.simulator-objs/kernel-i386.bc', 'iPhoneSimulator' + install '../vm/.simulator-objs/libmacruby-static.a', 'iPhoneSimulator' +end + +task :bridgesupport do + frameworks = %w{UIKit Foundation CoreGraphics} + platform_dev_path = "#{platforms_dir}/iPhoneSimulator.platform/Developer" + sdk_path = "#{platform_dev_path}/SDKs/iPhoneSimulator#{sdk_version}.sdk" + sdk_frameworks = "#{sdk_path}/System/Library/Frameworks" + mkdir_p 'BridgeSupport' + frameworks.each do |framework| + dest = "BridgeSupport/#{framework}.bridgesupport" + sh "gen_bridge_metadata --format complete --no-64-bit --cflags \"--sysroot=#{sdk_path} -miphoneos-version-min=#{sdk_version}\" --framework #{sdk_frameworks}/#{framework}.framework > #{dest}" unless File.exist?(dest) + end +end + +task :clean do + %w{ruby llc iPhoneOS iPhoneSimulator BridgeSupport}.each { |path| rm_rf(path) } +end diff --git a/doc/Rakefile b/doc/Rakefile new file mode 100644 index 00000000..ccfcb252 --- /dev/null +++ b/doc/Rakefile @@ -0,0 +1,11 @@ +platforms_dir = ENV['platforms_dir'] +sdk_version = ENV['sdk_version'] + +task :default => :all +task :all do + # TODO +end + +task :clean do + # TODO +end diff --git a/lib/rubixir/rake.rb b/lib/rubixir/rake.rb new file mode 100644 index 00000000..05070c93 --- /dev/null +++ b/lib/rubixir/rake.rb @@ -0,0 +1,42 @@ +require 'rubixir/rake/config' +require 'rubixir/rake/builder' + +module Rubixir + CONFIG = Config.new('.') + BUILDER = Builder.new +end + +desc "Build the project, then run the simulator" +task :default => :simulator + +namespace :build do + desc "Build the simulator version" + task :simulator do + Rubixir::BUILDER.compile(Rubixir::CONFIG, 'iPhoneSimulator') + end + + desc "Build the iOS version" + task :ios do + Rubixir::BUILDER.compile(Rubixir::CONFIG, 'iPhoneOS') + end + + desc "Build everything" + task :all => [:simulator, :ios] +end + +desc "Run the simulator" +task :simulator => ['build:simulator'] do + sim = File.join(Rubixir::CONFIG.platform_dir('iPhoneSimulator'), '/Developer/Applications/iPhone Simulator.app/Contents/MacOS/iPhone Simulator') + app = File.join(Rubixir::CONFIG.build_dir, 'iPhoneSimulator/main') + sh "\"#{sim}\" -SimulateApplication \"#{app}\"" +end + +desc "Deploy on the device" +task :deploy do + # TODO +end + +desc "Clear build objects" +task :clean do + rm_rf(Rubixir::CONFIG.build_dir) +end diff --git a/lib/rubixir/rake/builder.rb b/lib/rubixir/rake/builder.rb new file mode 100644 index 00000000..9cf9459c --- /dev/null +++ b/lib/rubixir/rake/builder.rb @@ -0,0 +1,133 @@ +module Rubixir + class Builder + def compile(config, platform) + datadir = File.join(File.dirname(__FILE__), '../../../data') + libstatic = File.join(datadir, 'libmacruby-static.a') + archs = Dir.glob(File.join(datadir, platform, '*.bc')).map do |path| + path.scan(/kernel-(.+).bc$/)[0][0] + end + ruby = File.join(datadir, 'ruby') + llc = File.join(datadir, 'llc') + + # Locate SDK. + sdk = config.sdk(platform) + + # Locate compilers. + cc = File.join(config.platform_dir(platform), 'Developer/usr/bin/gcc') + cxx = File.join(config.platform_dir(platform), 'Developer/usr/bin/g++') + + build_dir = File.join(config.build_dir, platform) + + bs_flags = '' + config.frameworks.each do |framework| + bs_path = File.join(datadir, 'BridgeSupport', framework + '.bridgesupport') + if File.exist?(bs_path) + bs_flags << "--uses-bs \"" + bs_path + "\" " + end + end + + objs = [] + config.files.each do |path| + # Generate init function. + init_func = "MREP_#{`uuidgen`.strip.gsub('-', '')}" + + arch_objs = [] + archs.each do |arch| + # Locate arch kernel. + kernel = File.join(datadir, platform, "kernel-#{arch}.bc") + raise "Can't locate kernel file" unless File.exist?(kernel) + + # Prepare build_dir. + bc = File.join(build_dir, "#{path}.#{arch}.bc") + FileUtils.mkdir_p(File.dirname(bc)) + + # LLVM bitcode. + sh "/usr/bin/env VM_KERNEL_PATH=\"#{kernel}\" #{ruby} #{bs_flags} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\"" + + # Assembly. + asm = File.join(build_dir, "#{path}.#{arch}.s") + llc_arch = case arch + when 'i386'; 'x86' + when 'x86_64'; 'x86-64' + when /^arm/; 'arm' + else; arch + end + sh "#{llc} \"#{bc}\" -o=\"#{asm}\" -march=#{llc_arch} -relocation-model=pic -disable-fp-elim -jit-enable-eh" + + # Object. + obj = File.join(build_dir, "#{path}.#{arch}.o") + sh "#{cc} -fexceptions -c -arch #{arch} \"#{asm}\" -o \"#{obj}\"" + + arch_objs << obj + end + + # Assemble fat binary. + arch_objs_list = arch_objs.map { |x| "\"#{x}\"" }.join(' ') + obj = File.join(build_dir, "#{path}.o") + sh "lipo -create #{arch_objs_list} -output \"#{obj}\"" + + objs << [obj, init_func] + end + + # Generate main file. + main_txt = < +extern "C" { + void ruby_sysinit(int *, char ***); + void ruby_init(void); + void ruby_init_loadpath(void); + void ruby_script(const char *); + void ruby_set_argv(int, char **); + void rb_vm_init_compiler(void); + void rb_vm_init_jit(void); + void rb_vm_aot_feature_provide(const char *, void *); + void *rb_vm_top_self(void); + void rb_vm_print_current_exception(void); + void rb_exit(int); +EOS + objs.each do |_, init_func| + main_txt << "void #{init_func}(void *, void *);\n" + end + main_txt << <