[MacRuby-devel] experimental branch: status update

Laurent Sansonetti lsansonetti at apple.com
Sat Jul 11 22:25:01 PDT 2009


Another update on the experimental branch!

Highlights are:

- A much better AOT (ahead-of-time) compiler, now available as a  
separate command line executable, macrubyc. It can compile some  
MacRuby sample code. Details at the very end of this message.

- IB support is back! Once you install experimental IB can show the  
classes and their outlets/actions that you defined in your Ruby code,  
inside Xcode, as previously. It still uses the same command line tool  
based on Ripper.

- More Ruby and Cocoa compatibility.

Detailed changes:

- AOT compiler: added support for compilation of NSObject, IDs,  
blocks, dynamic variables, instance variables, cleanup exception  
handler, global variables, literal symbols & immediates,

- RubySpec was updated from upstream.

- Fixed a bug in the way we compile literal strings, before the same  
instance was reused which was bad since strings are mutable.

- Implemented END{} blocks.

- Fixed a bug in IO.copy_stream, IO#print, implemented  
IO#initialize_copy.

- Fixed lexical constant lookup inside classes defined within a  
builtin class.

- The Ripper C extension is now supported again. It is built and  
installed as part of the normal build process. First C extension on  
experimental!

- Fixed a bug in the instance variable slot logic where it was only  
called for T_OBJECT types.

- Added a workaround for missing 64-bit informal protocol annotations  
in BridgeSupport.

- Installed a cleanup exception handler in macruby_main().

- Optimized dummy calls to <=>: inside the code base.

- Mark thread block locals as used. This fixes a bug where a thread's  
block was using a local variable right after the method exited.

- Implemented the internal rb_rescue() and rb_ensure() APIs.

- Implemented ThreadGroup.

- Re-implemented return-from-block to use a specialized C++ exception  
instead of SjLj. This is to make sure ensure blocks are honored, to  
conform to the Ruby specs.

- Force the installation of the static .a library within  
MacRuby.framework (for AOT compiler).

- Fixed the setting of $? post a popen-based expression.

- Removed the --compile command line argument from the macruby  
executable, added the --emit-llvm argument which dumps the LLVM  
bitcode. This is only for internal use, users should use the new  
macrubyc executable instead.

- Introducing macrubyc, a command line tool interface to the AOT  
compiler.

macrubyc allows you to compile a given Ruby file into a Mach-O object  
file and/or produce a final executable.

Produced Mach-O objects are true object files. They can be used to  
form a MacRuby executable or you can also use them into your Objective- 
C project that uses the MacRuby Objective-C API.

Produced executables embed all the compiled Ruby code as well as  
MacRuby, statically. It can be distributed as is and does not depend  
on anything MacRuby or LLVM at runtime. The Ruby source code is  
compiled into native machine code (same process as we do at runtime  
with the JIT compiler), so it's also a good way to obfuscate the  
source code. The final binary looks like an Objective-C binary (except  
that it's larger).

macrubyc behaves like gcc.

An example:

$ echo 'p 123' > t1.rb
$ echo 'p 456' > t2.rb
$ macrubyc -c t1.rb -o t1.o
$ macrubyc -c t2.rb -o t2.o
$ macrubyc t1.o t2.o -o t
$ ./t
123
456

Which can be rewritten in a shorter form:

$ macrubyc t1.rb t2.rb -o t
$ ./t
123
456

Ruby files are loaded using the link order.

You can also provide any .o file during link time. Example:

$ cat t.m
#import <Foundation/Foundation.h>
@interface Foo : NSObject
@end
@implementation Foo
+ (void)foo { NSLog(@"foo"); }
@end
$ gcc -c t.m -o t.o -fobjc-gc
$ cat t2.rb
Foo.foo
$ macrubyc t.o t2.rb -o t
$ ./t
2009-07-11 22:04:37.229 t[12964:903] foo

Here, we link a Ruby source file with a pure Objective-C source file  
and it works.

macrubyc is still very preliminary but it can compile a few samples  
that we ship, like DotView or PathDemo (I did not try all of them yet).

We will provide an Xcode target to automatize the compilation of a  
MacRuby Xcode project, but in the meantime you can try the command  
line. An example for PathDemo:

$ cd build/Release/PathDemo.app/Contents/Resources/
$ cat prelude.rb
framework 'Cocoa'
$ cat main.rb
NSApplicationMain(0, nil)
$ macrubyc prelude.rb DemoView.rb PathDemoController.rb main.rb -o ../ 
MacOS/PathDemo
$ rm *.o *.rb

As you can see, here we created 2 additional files, prelude.rb and  
main.rb. prelude.rb loads the Cocoa framework and is passed as the 1st  
object, which means it will be executed at the very first time. This  
is needed since you want the framework to be loaded before executing  
code that would use it. main.rb just calls the Cocoa run loop, we pass  
it at the very end since this is a blocking call.

Current issues:

- It is very preliminary. Lots of bugs and only a portion of the Ruby  
AST is supported. The goal is to provide 2 modes: normal and full.  
Only the normal mode is being implemented right now.

The normal mode will support the entire Ruby specification, compile  
input source files into machine code, and still use LLVM at runtime to  
generate stubs. This will be the preferred way to compile desktop  
applications. Startup time will be very good (almost like Objective-C)  
and the entire source code will be compiled.

The full mode will compile everything statically and will not generate  
any code at runtime. Only a subset of the Ruby specification will be  
supported, and the final binary will not contain LLVM. This can be  
used when you want a very light application and/or if the environment  
does not support runtime code generation.

- It can only produce 64-bit binaries for now. Universal binary  
support will come in the future.

- It heavily depends on the linker ordering in order to initialize  
things. macrubyc might expose a way to call a "main" method that you  
would define in Ruby, after doing all the initializations.

If you have any comment, criticism or suggestion please do not  
hesitate. This is all shiny and we have the time to iterate on it :-)

Laurent


More information about the MacRuby-devel mailing list