diff -Nru orig/rubycocoa-0.4.1/README.embed new/rubycocoa-0.4.1-embed/README.embed --- orig/rubycocoa-0.4.1/README.embed Wed Dec 31 16:00:00 1969 +++ new/rubycocoa-0.4.1-embed/README.embed Thu Apr 7 19:51:23 2005 @@ -0,0 +1,27 @@ +If you want to build an embedded RubyCocoa.framework (one that has +an completely bundled libruby with it so it has no external +dependencies on ruby), you only need to do one step differently in +the build process: + +ruby install.rb --embed + +When you build in embedded mode, we force a static libruby.a to be +linked in. RBRuntime gets a special bootstrap call at runtime that +determines where your app is installed and updates $: to refer to +your bundled libruby instead of the libruby it was built with +originally. + +Extensions that depend on dynamic libs aren't supported yet, but the +basics are added. You can create a Resources/lib under your built +RubyCocoa.framework and copy dylibs into there. If you set +DYLD_LIBRARY_PATH to the internal Resources/lib and +Resources/ruby-core/lib, then all dynamic libs can be loaded without +any app-external dependencies. + +I've done some investigating on how to make the dyld manipulations +programmatic inside RBRuntime, but it doesn't quite work yet. +Currently, RBRuntime does a setenv(3) on DYLD_LIBRARY_PATH, but it +doesn't load the libraries from their proper paths. You can't +use libtool because it's a buildtime tool, and you can't use +prebinding because you can't depend on all the dependent libs being +built with prebinding. diff -Nru orig/rubycocoa-0.4.1/framework/src/objc/RBRuntime.h new/rubycocoa-0.4.1-embed/framework/src/objc/RBRuntime.h --- orig/rubycocoa-0.4.1/framework/src/objc/RBRuntime.h Sun Dec 15 21:04:43 2002 +++ new/rubycocoa-0.4.1-embed/framework/src/objc/RBRuntime.h Thu Apr 7 19:16:35 2005 @@ -10,6 +10,10 @@ * **/ +#define RUBY_COCOA_EMBEDDED 1 +#define EMBEDDED_RUBY_SUBDIR "ruby-core" + int RBApplicationMain(const char* rb_main_name, int argc, const char* argv[]); int RBRubyCocoaInit(); + diff -Nru orig/rubycocoa-0.4.1/framework/src/objc/RBRuntime.h.in new/rubycocoa-0.4.1-embed/framework/src/objc/RBRuntime.h.in --- orig/rubycocoa-0.4.1/framework/src/objc/RBRuntime.h.in Wed Dec 31 16:00:00 1969 +++ new/rubycocoa-0.4.1-embed/framework/src/objc/RBRuntime.h.in Thu Apr 7 19:40:38 2005 @@ -0,0 +1,19 @@ +/** -*-objc-*- + * + * $Id: RBRuntime.h,v 1.3 2002/12/16 05:04:43 hisa Exp $ + * + * Copyright (c) 2001 FUJIMOTO Hisakuni + * + * This program is free software. + * You can distribute/modify this program under the terms of + * the GNU Lesser General Public License version 2. + * + **/ + +#define RUBY_COCOA_EMBEDDED %%%embed_rubycocoa%%% +#define EMBEDDED_RUBY_SUBDIR "ruby-core" + +int RBApplicationMain(const char* rb_main_name, int argc, const char* argv[]); + +int RBRubyCocoaInit(); + diff -Nru orig/rubycocoa-0.4.1/framework/src/objc/RBRuntime.m new/rubycocoa-0.4.1-embed/framework/src/objc/RBRuntime.m --- orig/rubycocoa-0.4.1/framework/src/objc/RBRuntime.m Fri Mar 18 07:22:58 2005 +++ new/rubycocoa-0.4.1-embed/framework/src/objc/RBRuntime.m Thu Apr 7 19:17:23 2005 @@ -13,6 +13,7 @@ #import "RBRuntime.h" #import "RBObject.h" #import +#import #import #import #import @@ -21,6 +22,8 @@ #define RUBY_MAIN_NAME "rb_main.rb" +extern VALUE rb_load_path; + static char* rb_main_path(const char* rb_main_name) { char* result; @@ -67,6 +70,92 @@ rb_ary_unshift(rb_load_path, rb_str_new2(path)); } +// If we're in embedded mode (a complete ruby install is bundled inside +// RubyCocoa.framework), then we need to adjust the ruby load paths, +// which is controlled by the rb_load_path global in ruby. +// +// We call resource_path() to get the absolute path to our Resources +// folder inside our app bundle, and then adjust it to point to the +// embedded ruby inside RubyCocoa.framework. We expect that the same +// ruby that was used to build RC has been copied: +// +// cp -rp $ruby_base/lib RC.framework/Resources/EMBEDDED_RUBY_SUBDIR +// +// EMBEDDED_RUBY_SUBDIR is usually defined as ruby-core, but you can +// change it if you want. +// +// the load paths for the ruby we embedded are wrong, so we iterate +// through the array, stripping off everything before the last lib/ruby +// and replacing it with the pointers to the ruby-core path. after this, +// rb_load_path has been dynamically updated to contain the load paths +// for the bundled ruby, not the one used to build RC (i.e. everything +// is self-contained). +// +// this load method works for static extensions, but dynamic ones still +// have references back to the dynamic libs they had runtime depenencies +// on when they were orignally built. +// +// we attempt to support proper dyld behavior, adding support for a +// Resources/lib under RubyCocoa.framework that lets you bundle any +// third-party shared libs that are required by your site_ruby extensions +// under ruby-core. DYLD_LIBRARY_PATH is assigned to, but the only way +// to get this to work so far is to assign to the env in your shell +// before opening the app. there are more drastic approaches we can +// take. prebinding doesn't work because the dependent libs might not +// have been built with prebinding, and libtool requires that you have +// the intermediate .o files in order to build a new shared lib with +// fixed path references. + +static void +setEmbeddedPaths() +{ + id pool = [[NSAutoreleasePool alloc] init]; + + char *basePath = resource_path(); + int i; + + NSMutableString *fullpath = [NSMutableString stringWithCString:basePath]; + NSMutableString *embedDir = [NSMutableString string]; + + [fullpath appendString:@"/../Frameworks/RubyCocoa.framework/Resources/"]; + [fullpath appendString:@EMBEDDED_RUBY_SUBDIR]; + + for (i=0; i < RARRAY(rb_load_path)->len; i++) { + VALUE pathString = RARRAY(rb_load_path)->ptr[i]; + if (RSTRING(pathString)->len == 0) + continue; + + char *oldpath = RSTRING(pathString)->ptr; + NSMutableString *newpath = [NSMutableString stringWithCString:oldpath]; + NSRange range = [newpath rangeOfString:@"/lib/ruby" + options:NSBackwardsSearch]; + + if (range.location != NSNotFound) { + int origLocation = range.location; + range.location = 0; + range.length = origLocation; + [newpath deleteCharactersInRange:range]; + [newpath insertString:fullpath atIndex:0]; + } + + RARRAY(rb_load_path)->ptr[i] = rb_str_new2([newpath cString]); + } + + NSMutableString *libPath = [NSMutableString stringWithCString:resource_path()]; + [libPath appendString:@"/../Frameworks/RubyCocoa.framework/Resources/lib"]; + + char *oldLibPath = getenv("DYLD_LIBRARY_PATH"); + + if (oldLibPath && strchr(oldLibPath, ':')) { + [libPath appendString:@":"]; + [libPath appendString:[NSString stringWithCString:oldLibPath]]; + } + + setenv("DYLD_FRAMEWORK_PATH", [libPath cString], 1); + [pool release]; +} + + static int prepare_argv(int argc, const char* argv[], const char* rb_main_name, const char*** ruby_argv_ptr) { @@ -117,9 +206,13 @@ if (init_p) return 0; ruby_init(); + + if (RUBY_COCOA_EMBEDDED) + setEmbeddedPaths(); + initialize_mdl_osxobjc(); // initialize an objc part of rubycocoa load_path_unshift(framework_ruby_path()); // add a ruby part of rubycocoa to $LOAD_PATH init_p = 1; - + return 1; } diff -Nru orig/rubycocoa-0.4.1/metaconfig new/rubycocoa-0.4.1-embed/metaconfig --- orig/rubycocoa-0.4.1/metaconfig Sun Jan 9 22:33:37 2005 +++ new/rubycocoa-0.4.1-embed/metaconfig Thu Apr 7 19:39:36 2005 @@ -4,13 +4,14 @@ eval File.open('VERSION'){|f|f.read} end -libruby_path = File.join(Config::CONFIG['libdir'], Config::CONFIG['LIBRUBY']) -unless File.exist?( libruby_path ) then - libruby_path = File.join(Config::CONFIG['archdir'], Config::CONFIG['LIBRUBY_A']) -end +add_bool_config 'embed', false, "Build an embedded RubyCocoa" + +dynamic_libruby_path = File.join(Config::CONFIG['libdir'], Config::CONFIG['LIBRUBY']) +static_libruby_path = File.join(Config::CONFIG['libdir'], Config::CONFIG['LIBRUBY_A']) + # On Panther, /usr/lib/ruby reports wrong CONFIG -unless File.exist?( libruby_path ) then - libruby_path = File.join(Config::CONFIG['libdir'], 'libruby.dylib') +unless File.exist?( dynamic_libruby_path ) then + dynamic_libruby_path = File.join(Config::CONFIG['libdir'], 'libruby.dylib') end add_path_config 'install-root', '', @@ -42,8 +43,11 @@ add_path_config 'ruby-header-dir', Config::CONFIG['archdir'], 'path to the ruby header directory' -add_path_config 'libruby-path', libruby_path, - 'path to the libruby file' +add_path_config 'libruby-path', dynamic_libruby_path, + 'path to the libruby.dylib file' + +add_path_config 'static-libruby-path', static_libruby_path, + 'path to the static libruby.a file' add_config 'rubycocoa-version', 'name', RubyCocoaConfig::VERSION + RubyCocoaConfig::STAGE, diff -Nru orig/rubycocoa-0.4.1/post-setup.rb new/rubycocoa-0.4.1-embed/post-setup.rb --- orig/rubycocoa-0.4.1/post-setup.rb Wed Dec 31 16:00:00 1969 +++ new/rubycocoa-0.4.1-embed/post-setup.rb Thu Apr 7 19:15:55 2005 @@ -0,0 +1,35 @@ +require 'fileutils' + +# if we're in embed mode, copy in the build ruby's lib dir. + +if @config['embed'] + libdir = Config::CONFIG['libdir'] + destbase = "framework/build/RubyCocoa.framework" + destdir = "#{destbase}/Resources/ruby-core" + + if ! FileTest.exists?("#{destdir}/lib") + puts "Bundling #{libdir} into #{destdir}" + FileUtils.cp_r(libdir, destdir) + end + + if ! FileTest.exists?("./RubyCocoa.framework") + puts "Symlinking built RubyCocoa.framework into ." + FileUtils.ln_s(destbase, ".") + end + + puts <