[macruby-changes] [3528] MacRuby/trunk/bin/ruby_deploy

source_changes at macosforge.org source_changes at macosforge.org
Mon Feb 15 08:14:11 PST 2010


Revision: 3528
          http://trac.macosforge.org/projects/ruby/changeset/3528
Author:   eloy.de.enige at gmail.com
Date:     2010-02-15 08:14:10 -0800 (Mon, 15 Feb 2010)
Log Message:
-----------
ruby_deploy: Add --verbose and --stdlib. The latter option allows you to specify the name of a stdlib lib to keep. Also compile *all* .rb files in the app bundle, including those in the embeded framework and fix the binaries if the framework is embeded.

For instance, using `--stdlib digest' would keep:
* usr/lib/ruby/site_ruby/1.9.0/digest.rb
* usr/lib/ruby/site_ruby/1.9.0/digest/hmac.rb
* usr/lib/ruby/site_ruby/1.9.0/digest/sha2.rb
* usr/lib/ruby/site_ruby/1.9.0/universal-darwin10.0/digest.bundle
* usr/lib/ruby/site_ruby/1.9.0/universal-darwin10.0/digest/bubblebabble.bundle
* usr/lib/ruby/site_ruby/1.9.0/universal-darwin10.0/digest/md5.bundle
* usr/lib/ruby/site_ruby/1.9.0/universal-darwin10.0/digest/rmd160.bundle
* usr/lib/ruby/site_ruby/1.9.0/universal-darwin10.0/digest/sha1.bundle
* usr/lib/ruby/site_ruby/1.9.0/universal-darwin10.0/digest/sha2.bundle

Note that this is done purely based on the name of the lib.

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

Modified: MacRuby/trunk/bin/ruby_deploy
===================================================================
--- MacRuby/trunk/bin/ruby_deploy	2010-02-15 15:43:22 UTC (rev 3527)
+++ MacRuby/trunk/bin/ruby_deploy	2010-02-15 16:14:10 UTC (rev 3528)
@@ -7,19 +7,20 @@
 
 require 'optparse'
 require 'rbconfig'
-require 'fileutils'
 
 class Deployer
-  include FileUtils
-
   NAME = File.basename(__FILE__)
 
   def initialize(argv)
+    @stdlib = []
+
     OptionParser.new do |opts|
       opts.banner = "Usage: #{NAME} [options] application-bundle"
-      opts.on('--compile', 'Compile the bundle source code') { @compile = true }
-      opts.on('--embed', 'Embed MacRuby inside the bundle') { @embed = true }
-      opts.on('--no-stdlib', "Do not embed the standard library") { @no_stdlib = true }
+      opts.on('--compile',       'Compile the bundle source code') { @compile = true }
+      opts.on('--embed',         'Embed MacRuby inside the bundle') { @embed = true }
+      opts.on('--no-stdlib',     'Do not embed the standard library') { @no_stdlib = true }
+      opts.on('--stdlib [LIB]',  'Embed only LIB from the standard library') { |lib| @stdlib << lib }
+      opts.on('--verbose',       'Log actions to standard out') { @verbose = true }
       opts.on('-v', '--version', 'Display the version') do
         puts RUBY_DESCRIPTION
         exit 1
@@ -33,63 +34,95 @@
       @app_bundle = argv[0]
     end
 
-    if !File.exist?(@app_bundle)
-      die "Given path `#{@app_bundle}' doesn't exist"
-    end
-    if !File.directory?(@app_bundle) or !File.exist?(File.join(@app_bundle, 'Contents'))
-      die "Given path `#{@app_bundle}' doesn't seem to be a valid application bundle"
-    end
+    ensure_path @app_bundle
+    ensure_path File.join(@app_bundle, 'Contents'), "Path `%s' doesn't seem to be a valid application bundle"
 
     # Locate necessary programs.
     @install_name_tool = locate('install_name_tool')
 
     # Locate the MacRuby framework.
     @macruby_framework_path = Config::CONFIG['libdir'].scan(/^.+MacRuby\.framework/)[0]
-    if !File.exist?(@macruby_framework_path)
-      die "Cannot locate MacRuby.framework from rbconfig.rb"
-    end
+    ensure_path @macruby_framework_path, "Cannot locate MacRuby.framework from rbconfig.rb"
   end
 
   def run
     die "Nothing to do, please specify --compile or --embed" if !@compile and !@embed
     die "--no-stdlib can only be used with --embed" if @no_stdlib and !@embed
+    die "--stdlib can only be used with --embed" if !@stdlib.empty? and !@embed
+    embed if @embed
     compile if @compile
-    embed if @embed
   end
 
   private
 
+  # FileUtils::Verbose doesn't work with MacRuby yet. However, it doesn't print
+  # out failures anyways, just the command. Use the command-line tools directly
+  # to circumvent this.
+  { :cp_r => 'cp -R', :mkdir_p => 'mkdir -p', :rm_rf => 'rm -rf' }.each do |name, cmd|
+    module_eval <<-END, __FILE__, __LINE__ + 1
+      def #{name}(*args)
+        execute "#{cmd} \#{args.map { |a| "'\#{a}'" }.join(' ')}"
+      end
+    END
+  end
+
+  def app_frameworks
+    File.join(@app_bundle, 'Contents/Frameworks')
+  end
+
+  def app_macruby
+    File.join(app_frameworks, 'MacRuby.framework')
+  end
+
+  def app_macruby_usr
+    File.join(app_macruby, 'Versions', MACRUBY_VERSION, 'usr')
+  end
+
+  def macruby_usr
+    @macruby_usr ||= ensure_path(File.join(@macruby_framework_path, 'Versions', MACRUBY_VERSION, 'usr'))
+  end
+
+  def compile_files
+    Dir.glob(File.join(@app_bundle, 'Contents/Resources/*.rb')) +
+      Dir.glob(File.join(app_macruby_usr, '**/*.rb'))
+  end
+
   def compile
-    Dir.glob(File.join(@app_bundle, 'Contents/Resources/*.rb')).each do |source|
+    compile_files.each do |source|
       base = File.basename(source, '.rb')
       next if base == 'rb_main'
       obj = File.join(File.dirname(source), base + '.rbo')
       if !File.exist?(obj) or File.mtime(source) > File.mtime(obj)
-        die "Can't compile \"#{source}\"" unless system("macrubyc -C \"#{source}\" -o \"#{obj}\"")
-        FileUtils.rm_f(source)
+        execute("macrubyc -C \"#{source}\" -o \"#{obj}\"", "Can't compile \"#{source}\"")
       end
+      rm_rf(source)
     end
+    fix_install_name if File.exist?(app_macruby)
   end
 
+  STDLIB_PATTERN = "lib/ruby/{,site_ruby/}1.9.*{,/universal-darwin*}"
+  KEEP_STDLIB_PATTERN = "{%s}{,{.,/**/*.}{rb,rbo,bundle}}"
+
   def embed
     # Copy MacRuby.framework inside MyApp.app/Contents/Frameworks.
-    app_frameworks = File.join(@app_bundle, 'Contents/Frameworks')
     mkdir_p(app_frameworks)
-    app_macruby = File.join(app_frameworks, 'MacRuby.framework')
     rm_rf(app_macruby)
     cp_r(@macruby_framework_path, app_frameworks)
 
     # Delete unnecessary things in the MacRuby.framework copy.
-    app_macruby_usr = File.join(app_macruby, 'Versions', MACRUBY_VERSION, 'usr')
-    macruby_usr = File.join(@macruby_framework_path, 'Versions', MACRUBY_VERSION, 'usr')
-    die "oops" if !File.exist?(app_macruby_usr) or !File.exist?(macruby_usr)
     dirs = ['bin', 'include', 'lib/libmacruby-static.a', 'share']
-    if @no_stdlib
-      dirs << 'lib/ruby'
-    end
+    dirs << 'lib/ruby' if @no_stdlib
     dirs << 'lib/ruby/Gems' # TODO add gems support
     dirs.each { |x| rm_rf(File.join(app_macruby_usr, x)) }
 
+    # Only keep specific libs from stdlib.
+    unless @stdlib.empty?
+      lib = File.join(app_macruby_usr, STDLIB_PATTERN)
+      all, keep = ["**/*", KEEP_STDLIB_PATTERN % @stdlib.join(',')].map { |p| Dir.glob(File.join(lib, p)) }
+      keep.reject! { |f| File.extname(f) == '.rb' && keep.include?("#{f}o") } # only keep .rbo for duplicates
+      all.select { |f| keep.grep(/^#{f}/).empty? }.each { |x| rm_rf(x) }
+    end
+
     # Only keep the Current version of the MacRuby.framework copy.
     Dir.glob(File.join(app_macruby, 'Versions/*')).select { |x|
       base = File.basename(x)
@@ -98,9 +131,14 @@
       rm_rf(x)
     }
 
-    # Hack the application binaries to link against the MacRuby.framework copy.
-    patterns = [File.join(@app_bundle, 'Contents/MacOS/*'), 
-                File.join(app_macruby_usr, 'lib/ruby/**/*.{bundle,rbo}'), 
+    # Wait with fixing install name until all binaries are available.
+    fix_install_name unless @compile
+  end
+
+  # Hack the application binaries to link against the MacRuby.framework copy.
+  def fix_install_name
+    patterns = [File.join(@app_bundle, 'Contents/MacOS/*'),
+                File.join(app_macruby_usr, 'lib/ruby/**/*.{bundle,rbo}'),
                 File.join(@app_bundle, 'Contents/Resources/*.rbo')]
     patterns.each do |pat|
       Dir.glob(pat).each do |bin|
@@ -109,9 +147,10 @@
     end
   end
 
-  def execute(line)
+  def execute(line, error_message = nil)
+    $stdout.puts(line) if @verbose
     ret = `#{line}`
-    die "Error when executing `#{line}'" unless $?.success?
+    die(error_message || "Error when executing `#{line}'") unless $?.success?
     ret
   end
 
@@ -121,6 +160,11 @@
     path
   end
 
+  def ensure_path(path, message = "Path does not exist `%s'")
+    die(message % path) unless File.exist?(path)
+    path
+  end
+
   def die(*args)
     $stderr.puts args
     exit 1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100215/158ac902/attachment-0001.html>


More information about the macruby-changes mailing list