[macruby-changes] [2439] MacRuby/trunk/bin/rubyc

source_changes at macosforge.org source_changes at macosforge.org
Sun Aug 30 16:09:37 PDT 2009


Revision: 2439
          http://trac.macosforge.org/projects/ruby/changeset/2439
Author:   lsansonetti at apple.com
Date:     2009-08-30 16:09:33 -0700 (Sun, 30 Aug 2009)
Log Message:
-----------
introduce -C flag to compile loadable ruby objects (.rbo)

Modified Paths:
--------------
    MacRuby/trunk/bin/rubyc

Modified: MacRuby/trunk/bin/rubyc
===================================================================
--- MacRuby/trunk/bin/rubyc	2009-08-30 23:08:21 UTC (rev 2438)
+++ MacRuby/trunk/bin/rubyc	2009-08-30 23:09:33 UTC (rev 2439)
@@ -14,19 +14,6 @@
   def initialize(argv)
     @mode = :normal
     @frameworks = []
-=begin
-    # OptionParser is not smart enough to handle some typical command line style arguments.
-    new_argv = argv.dup
-    argv.each_with_index do |a, i|
-      if a == '-framework'
-        die 'missing argument: -framework' if argv.size == i + 1
-        @frameworks << argv[i + 1]
-	new_argv.delete_at(i)
-	new_argv.delete_at(i)
-      end
-    end
-    argv = new_argv
-=end
 
     # Parse arguments.
     OptionParser.new do |opts|
@@ -34,7 +21,8 @@
       opts.on('-c', 'Compile and assemble, but do not link') { @dont_link = true }
       opts.on('-o <file>', 'Place the output into <file>') { |output| @output = output }
       opts.on('--mode [MODE]', "Select compilation mode (normal or full)") { |mode| @mode = mode.intern }
-      #opts.on('-framework <framework>', 'Link against <framework>') { |path| @frameworks << path }
+      #opts.on('--framework <framework>', 'Link against <framework>') { |path| @frameworks << path }
+      opts.on('-C', 'Compile, assemble and link a loadable object file') { @bundle = true }
       opts.on('-v', '--version', 'Display the version') { puts RUBY_DESCRIPTION; exit 1 }
       opts.on('-V', '--verbose', 'Print every command line executed') { @verbose = true }
       opts.on('-h', '--help', 'Display this information') { die opts }
@@ -66,14 +54,18 @@
     if @mode == :full
       die "full compilation mode is not implemented yet!"
     end
-    if @dont_link
+    if @dont_link or @bundle
+      die "cannot specify -c and -C at the same time" if @bundle and @dont_link
       if @files.size > 1 and @output
-        die "cannot specify -o with -c and multiple input files"
+        die "cannot specify -o with -c or -C and multiple input files"
       end
-      @files.each do |file|
-        if File.extname(file) != '.rb'
-          die "given input file `#{file}' must be a Ruby source file (.rb)"
-        end
+      file = @files[0]
+      if File.extname(file) != '.rb'
+        die "given input file `#{file}' must be a Ruby source file (.rb)"
+      end
+      if @bundle
+        compile_bundle(file, @output)
+      else
         compile_object(file, @output)
       end
     else
@@ -116,16 +108,43 @@
     output
   end
 
+  def compile_bundle(file, output)
+    base = File.basename(file, '.rb')
+    obj = gen_tmpfile(base, 'o')
+    compile_object(file, obj)
+
+    output ||= File.join(File.dirname(file), base + '.rbo')
+
+    real_init_func = guess_init_function_name(obj)
+    unless real_init_func
+      die "can't guess the init function of Ruby object file `#{obj}'"
+    end
+
+    init_func = "Init_" + base
+    main_txt = <<EOS
+extern "C" {
+  void *#{real_init_func}(void *, void *);
+  void *rb_vm_top_self(void);
+  void
+  #{init_func}(void) {
+    #{real_init_func}(rb_vm_top_self(), 0);
+  }
+}
+EOS
+
+    main = gen_tmpfile('main', 'c')
+    File.open(main, 'w') { |io| io.write(main_txt) }
+    execute("#{@gcxx} #{main} -dynamic -bundle -undefined suppress -flat_namespace -arch x86_64 -framework MacRuby #{obj} -o #{output}")
+  end
+
   def compile_executable(objs, output)
     output ||= 'a.out'
 
     # Guess which objects were originally MacRuby source files and memorize their init function.
     init_funcs = []
     objs.each do |file|
-      ary = execute("#{@nm} #{file}").scan(/^\d+\sT\s(_MREP_.*)$/)
-      unless ary.empty?
-        init_funcs << ary[0][0][1..-1] # drop _ prefix
-      end
+      n = guess_init_function_name(file)
+      init_funcs << n if n
     end
 
     # Generate main file.
@@ -182,6 +201,11 @@
     execute(line)
   end
 
+  def guess_init_function_name(file)
+    ary = execute("#{@nm} -g #{file}").scan(/^\d+\sT\s(_MREP_.*)$/)
+    ary.empty? ? nil : ary[0][0][1..-1] # drop _ prefix
+  end
+
   def execute(line)
     $stderr.puts line if @verbose
     ret = `#{line}`
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090830/fdec0026/attachment-0001.html>


More information about the macruby-changes mailing list