[Pkg-ruby-extras-maintainers] r731 - in
packages/libinline-ruby/trunk: . debian lib
Patrick Ringl
smash-guest at costa.debian.org
Tue Aug 1 11:05:12 UTC 2006
Author: smash-guest
Date: 2006-08-01 11:05:10 +0000 (Tue, 01 Aug 2006)
New Revision: 731
Added:
packages/libinline-ruby/trunk/CHANGELOG
packages/libinline-ruby/trunk/README
packages/libinline-ruby/trunk/debian/
packages/libinline-ruby/trunk/debian/changelog
packages/libinline-ruby/trunk/debian/compat
packages/libinline-ruby/trunk/debian/control
packages/libinline-ruby/trunk/debian/control.in
packages/libinline-ruby/trunk/debian/copyright
packages/libinline-ruby/trunk/debian/example.rb
packages/libinline-ruby/trunk/debian/rules
packages/libinline-ruby/trunk/debian/watch
packages/libinline-ruby/trunk/lib/
packages/libinline-ruby/trunk/lib/inline.rb
packages/libinline-ruby/trunk/lib/inline_package
packages/libinline-ruby/trunk/setup.rb
Log:
Load newtrunk into packages/libinline-ruby/trunk.
Added: packages/libinline-ruby/trunk/CHANGELOG
===================================================================
--- packages/libinline-ruby/trunk/CHANGELOG 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/CHANGELOG 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,5 @@
+--------------------------------------------------------------------------------
+26/07/2006 version 3.5.0-1
+
+o Initial release.
+--------------------------------------------------------------------------------
\ No newline at end of file
Added: packages/libinline-ruby/trunk/README
===================================================================
--- packages/libinline-ruby/trunk/README 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/README 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,152 @@
+** Ruby Inline
+
+ http://www.zenspider.com/ZSS/Products/RubyInline/
+ http://rubyforge.org/projects/rubyinline/
+ support at zenspider.com
+
+** DESCRIPTION:
+
+Ruby Inline is an analog to Perl's Inline::C. Out of the box, it
+allows you to embed C/++ external module code in your ruby script
+directly. By writing simple builder classes, you can teach how to cope
+with new languages (fortran, perl, whatever). The code is compiled and
+run on the fly when needed.
+
+Using the package_inline tool Inline now allows you to package up
+your inlined object code for distribution to systems without a
+compiler (read: windows)!
+
+### HELLO WORLD EXAMPLE ###
+
+#!/usr/bin/ruby -w
+
+require 'inline'
+
+class Hello
+ inline do |builder|
+ builder.include "<stdio.h>"
+ builder.c 'void hello() { puts("hello world"); }'
+ end
+end
+
+Hello.new.hello
+
+##############################
+
+
+
+
+** FEATURES/PROBLEMS:
+
++ Quick and easy inlining of your C or C++ code embedded in your ruby script.
++ Extendable to work with other languages.
++ Automatic conversion between ruby and C basic types
+ + char, unsigned, unsigned int, char *, int, long, unsigned long
++ inline_c_raw exists for when the automatic conversion isn't sufficient.
++ Only recompiles if the inlined code has changed.
++ Pretends to be secure.
++ Only requires standard ruby libraries, nothing extra to download.
++ Can generate a basic Rakefile and package up built extensions for distribution.
+
+** SYNOPSYS:
+
+ require "inline"
+ class MyTest
+ inline do |builder|
+ builder.c "
+ long factorial(int max) {
+ int i=max, result=1;
+ while (i >= 2) { result *= i--; }
+ return result;
+ }"
+ end
+ t = MyTest.new()
+ factorial_5 = t.factorial(5)
+
+** SYNOPSYS (C++):
+
+ require 'inline'
+ class MyTest
+ inline(:C) do |builder|
+ builder.include '<iostream>'
+ builder.add_compile_flags '-x c++', '-lstdc++'
+ builder.c '
+ void hello(int i) {
+ while (i-- > 0) {
+ std::cout << "hello" << std::endl;
+ }
+ }'
+ end
+ end
+ t = MyTest.new()
+ t.hello(3)
+
+** SYNOPSYS (packaging):
+
+ rm -rf ~/.ruby_inline
+ make test
+ inline_package packagename 1.0.0
+ ls lib/inline
+
+** (PSEUDO)BENCHMARKS:
+
+ > make bench
+
+ Running native
+ Type = Native , Iter = 1000000, T = 28.70058100 sec, 0.00002870 sec / iter
+ Running primer - preloads the compiler and stuff
+ With full builds
+ Type = Inline C , Iter = 1000000, T = 7.55118600 sec, 0.00000755 sec / iter
+ Type = InlineRaw, Iter = 1000000, T = 7.54488300 sec, 0.00000754 sec / iter
+ Type = Alias , Iter = 1000000, T = 7.53243100 sec, 0.00000753 sec / iter
+ Without builds
+ Type = Inline C , Iter = 1000000, T = 7.59543300 sec, 0.00000760 sec / iter
+ Type = InlineRaw, Iter = 1000000, T = 7.54097200 sec, 0.00000754 sec / iter
+ Type = Alias , Iter = 1000000, T = 7.53654000 sec, 0.00000754 sec / iter
+
+** PROFILING STRATEGY:
+
+0) Always keep a log of your progress and changes.
+1) Run code with 'time' and large dataset.
+2) Run code with '-rprofile' and smaller dataset, large enough to get good #s.
+3) Examine profile output and translate 1 bottleneck to C.
+4) Run new code with 'time' and large dataset. Repeat 2-3 if unsatisfied.
+5) Run final code with 'time' and compare to the first run.
+
+** REQUIREMENTS:
+
++ Ruby - 1.8.2 has been used on FreeBSD 4.6+ and MacOSX.
++ POSIX compliant system (ie pretty much any UNIX, or Cygwin on MS platforms).
++ A C/C++ compiler (the same one that compiled your ruby interpreter).
++ test::unit for running tests ( http://testunit.talbott.ws/ ).
++ rubygems & rake if you'd like - these are used by inline_package.
+
+** INSTALL:
+
++ make test (optional)
++ make install
+
+** LICENSE:
+
+(The MIT License)
+
+Copyright (c) 2001-2005 Ryan Davis, Zen Spider Software
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Added: packages/libinline-ruby/trunk/debian/changelog
===================================================================
--- packages/libinline-ruby/trunk/debian/changelog 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/changelog 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,6 @@
+libinline-ruby (3.5.0-1) unstable; urgency=low
+
+ * Initial release
+
+ -- Patrick Ringl <patrick_ at freenet.de> Wed, 26 Jul 2006 04:38:15 +0200
+
Added: packages/libinline-ruby/trunk/debian/compat
===================================================================
--- packages/libinline-ruby/trunk/debian/compat 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/compat 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1 @@
+5
Added: packages/libinline-ruby/trunk/debian/control
===================================================================
--- packages/libinline-ruby/trunk/debian/control 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/control 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,35 @@
+Source: libinline-ruby
+Section: interpreters
+Priority: optional
+Maintainer: Patrick Ringl <patrick_ at freenet.de>
+Uploaders: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers at lists.alioth.debian.org>, Antonio S. de A. Terceiro <asaterceiro at inf.ufrgs.br>, David Moreno Garza <damog at debian.org>, David Nusinow <dnusinow at debian.org>, Paul van Tilburg <paulvt at debian.org>, Esteban Manchado Velázquez <zoso at debian.org>, Arnaud Cornet <arnaud.cornet at gmail.com>, Lucas Nussbaum <lucas at lucas-nussbaum.net>, Thierry Reding <thierry at doppeltgemoppelt.de>, Marc Dequènes (Duck) <Duck at DuckCorp.org>, Ari Pollak <ari at debian.org>, Daigo Moriwaki <daigo at debian.org>
+Build-Depends: ruby-pkg-tools (>= 0.8), cdbs, debhelper (>= 5.0.0), ruby1.8, ruby1.8-dev
+Build-Depends-Indep: ruby-pkg-tools (>= 0.8), cdbs, debhelper (>= 5.0.0), ruby1.8, ruby1.8-dev
+Standards-Version: 3.7.2
+
+Package: libinline-ruby
+Architecture: all
+Depends: libinline-ruby1.8
+Description: Ruby library for embedding C/++ external module code
+ Ruby Inline is an analog to Perl's Inline::C. Out of the box,
+ it allows you to embed C/++ external module code in your ruby script
+ directly. By writing simple builder classes, you can teach how to cope with
+ new languages (fortran, perl, whatever).
+ .
+ This package is part of the Ruby library extras, a supplement to Ruby's
+ standard library.
+ .
+ This is a dummy package depending on the library for the current default
+ version of Ruby.
+
+Package: libinline-ruby1.8
+Architecture: all
+Depends: ruby1.8, ruby1.8-dev
+Description: Ruby library for embedding C/++ external module code
+ Ruby Inline is an analog to Perl's Inline::C. Out of the box,
+ it allows you to embed C/++ external module code in your ruby script
+ directly. By writing simple builder classes, you can teach how to cope with
+ new languages (fortran, perl, whatever).
+ .
+ This package is part of the Ruby library extras, a supplement to Ruby's
+ standard library.
Added: packages/libinline-ruby/trunk/debian/control.in
===================================================================
--- packages/libinline-ruby/trunk/debian/control.in 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/control.in 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,35 @@
+Source: libinline-ruby
+Section: interpreters
+Priority: optional
+Maintainer: Patrick Ringl <patrick_ at freenet.de>
+Uploaders: @RUBY_EXTRAS_TEAM@
+Build-Depends: ruby-pkg-tools (>= 0.8), cdbs, debhelper (>= 5.0.0), ruby1.8, ruby1.8-dev
+Build-Depends-Indep: ruby-pkg-tools (>= 0.8), cdbs, debhelper (>= 5.0.0), ruby1.8, ruby1.8-dev
+Standards-Version: 3.7.2
+
+Package: libinline-ruby
+Architecture: all
+Depends: libinline-ruby1.8
+Description: Ruby library for embedding C/++ external module code
+ Ruby Inline is an analog to Perl's Inline::C. Out of the box,
+ it allows you to embed C/++ external module code in your ruby script
+ directly. By writing simple builder classes, you can teach how to cope with
+ new languages (fortran, perl, whatever).
+ .
+ This package is part of the Ruby library extras, a supplement to Ruby's
+ standard library.
+ .
+ This is a dummy package depending on the library for the current default
+ version of Ruby.
+
+Package: libinline-ruby1.8
+Architecture: all
+Depends: ruby1.8, ruby1.8-dev
+Description: Ruby library for embedding C/++ external module code
+ Ruby Inline is an analog to Perl's Inline::C. Out of the box,
+ it allows you to embed C/++ external module code in your ruby script
+ directly. By writing simple builder classes, you can teach how to cope with
+ new languages (fortran, perl, whatever).
+ .
+ This package is part of the Ruby library extras, a supplement to Ruby's
+ standard library.
Added: packages/libinline-ruby/trunk/debian/copyright
===================================================================
--- packages/libinline-ruby/trunk/debian/copyright 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/copyright 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,35 @@
+This package was debianized by Patrick Ringl <patrick_ at freenet.de> on
+Wed, 26 Jul 2006 04:38:15 +0200.
+
+It was downloaded from http://rubyforge.org/frs/download.php/6475/RubyInline-3.5.0.tar.gz
+
+Upstream Author: Ryan Davis <support at zenspider.com>
+
+Copyright: Copyright (c) 2001-2006 Ryan Davis, Zen Spider Software
+
+License: The MIT License
+
+Copyright (c) 2001-2005 Ryan Davis, Zen Spider Software
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+The Debian packaging is (C) 2006, Patrick Ringl <patrick_ at freenet.de> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
Added: packages/libinline-ruby/trunk/debian/example.rb
===================================================================
--- packages/libinline-ruby/trunk/debian/example.rb 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/example.rb 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,12 @@
+#!/usr/bin/ruby -w
+
+require 'inline'
+
+class Hello
+ inline do |builder|
+ builder.include "<stdio.h>"
+ builder.c 'void hello() { puts("hello world"); }'
+ end
+end
+
+Hello.new.hello
\ No newline at end of file
Added: packages/libinline-ruby/trunk/debian/rules
===================================================================
--- packages/libinline-ruby/trunk/debian/rules 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/rules 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,11 @@
+#!/usr/bin/make -f
+#
+# CDBS file to build the Daemonize package.
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/ruby-pkg-tools/1/class/ruby-setup-rb.mk
+
+include /usr/share/ruby-pkg-tools/1/rules/uploaders.mk
+
+# Include the upstream ChangeLog:
+DEB_INSTALL_CHANGELOGS_ALL = CHANGELOG
Property changes on: packages/libinline-ruby/trunk/debian/rules
___________________________________________________________________
Name: svn:executable
+ *
Added: packages/libinline-ruby/trunk/debian/watch
===================================================================
--- packages/libinline-ruby/trunk/debian/watch 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/debian/watch 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,2 @@
+version=2
+http://rubyforge.org/frs/download.php/6475/RubyInline-(.*)\.tar\.gz
\ No newline at end of file
Added: packages/libinline-ruby/trunk/lib/inline.rb
===================================================================
--- packages/libinline-ruby/trunk/lib/inline.rb 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/lib/inline.rb 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,651 @@
+#!/usr/bin/ruby -w
+
+##
+# Ruby Inline is a framework for writing ruby extensions in foreign
+# languages.
+#
+# = SYNOPSIS
+#
+# require 'inline'
+# class MyClass
+# inline do |builder|
+# builder.include "<math.h>"
+# builder.c %q{
+# long factorial(int max) {
+# int i=max, result=1;
+# while (i >= 2) { result *= i--; }
+# return result;
+# }
+# }
+# end
+# end
+#
+# = DESCRIPTION
+#
+# Inline allows you to write foreign code within your ruby code. It
+# automatically determines if the code in question has changed and
+# builds it only when necessary. The extensions are then automatically
+# loaded into the class/module that defines it.
+#
+# Using the package_inline tool Inline now allows you to package up
+# your inlined object code for distribution to systems without a
+# compiler (read: windows)!
+#
+# You can even write extra builders that will allow you to write
+# inlined code in any language. Use Inline::C as a template and look
+# at Module#inline for the required API.
+
+require "rbconfig"
+require "digest/md5"
+require 'ftools'
+require 'fileutils'
+
+$TESTING = false unless defined? $TESTING
+
+class CompilationError < RuntimeError; end
+
+##
+# The Inline module is the top-level module used. It is responsible
+# for instantiating the builder for the right language used,
+# compilation/linking when needed, and loading the inlined code into
+# the current namespace.
+
+module Inline
+ VERSION = '3.5.0'
+
+ $stderr.puts "RubyInline v #{VERSION}" if $DEBUG
+
+ protected
+
+ def self.rootdir
+ env = ENV['INLINEDIR'] || ENV['HOME']
+ unless defined? @@rootdir and env == @@rootdir and test ?d, @@rootdir then
+ rootdir = ENV['INLINEDIR'] || ENV['HOME']
+ Dir.mkdir rootdir, 0700 unless test ?d, rootdir
+ Dir.assert_secure rootdir
+ @@rootdir = rootdir
+ end
+
+ @@rootdir
+ end
+
+ def self.directory
+ directory = File.join(rootdir, ".ruby_inline")
+ unless defined? @@directory and directory == @@directory and test ?d, @@directory then
+ unless File.directory? directory then
+ $stderr.puts "NOTE: creating #{directory} for RubyInline" if $DEBUG
+ Dir.mkdir directory, 0700
+ end
+ Dir.assert_secure directory
+ @@directory = directory
+ end
+ @@directory
+ end
+
+ # Inline::C is the default builder used and the only one provided by
+ # Inline. It can be used as a template to write builders for other
+ # languages. It understands type-conversions for the basic types and
+ # can be extended as needed.
+
+ class C
+
+ protected unless $TESTING
+
+ MAGIC_ARITY_THRESHOLD = 2
+ MAGIC_ARITY = -1
+
+ @@type_map = {
+ 'char' => [ 'NUM2CHR', 'CHR2FIX' ],
+ 'char *' => [ 'STR2CSTR', 'rb_str_new2' ],
+ 'double' => [ 'NUM2DBL', 'rb_float_new' ],
+ 'int' => [ 'FIX2INT', 'INT2FIX' ],
+ 'long' => [ 'NUM2INT', 'INT2NUM' ],
+ 'unsigned int' => [ 'NUM2UINT', 'UINT2NUM' ],
+ 'unsigned long' => [ 'NUM2UINT', 'UINT2NUM' ],
+ 'unsigned' => [ 'NUM2UINT', 'UINT2NUM' ],
+ # Can't do these converters because they conflict with the above:
+ # ID2SYM(x), SYM2ID(x), NUM2DBL(x), FIX2UINT(x)
+ }
+
+ def ruby2c(type)
+ raise ArgumentError, "Unknown type #{type}" unless @@type_map.has_key? type
+ @@type_map[type].first
+ end
+
+ def c2ruby(type)
+ raise ArgumentError, "Unknown type #{type}" unless @@type_map.has_key? type
+ @@type_map[type].last
+ end
+
+ def strip_comments(src)
+ # strip c-comments
+ src = src.gsub(/\s*(?:(?:\/\*)(?:(?:(?!\*\/)[\s\S])*)(?:\*\/))/, '')
+ # strip cpp-comments
+ src.gsub!(/\s*(?:\/\*(?:(?!\*\/)[\s\S])*\*\/|\/\/[^\n]*\n)/, '')
+ src
+ end
+
+ def parse_signature(src, raw=false)
+
+ sig = self.strip_comments(src)
+ # strip preprocessor directives
+ sig.gsub!(/^\s*\#.*(\\\n.*)*/, '')
+ # strip {}s
+ sig.gsub!(/\{[^\}]*\}/, '{ }')
+ # clean and collapse whitespace
+ sig.gsub!(/\s+/, ' ')
+
+ types = 'void|VALUE|' + @@type_map.keys.map{|x| Regexp.escape(x)}.join('|')
+
+ if /(#{types})\s*(\w+)\s*\(([^)]*)\)/ =~ sig then
+ return_type, function_name, arg_string = $1, $2, $3
+ args = []
+ arg_string.split(',').each do |arg|
+
+ # helps normalize into 'char * varname' form
+ arg = arg.gsub(/\s*\*\s*/, ' * ').strip
+
+ # if /(#{types})\s+(\w+)\s*$/ =~ arg
+ if /(((#{types})\s*\*?)+)\s+(\w+)\s*$/ =~ arg then
+ args.push([$4, $1])
+ elsif arg != "void" then
+ $stderr.puts "WARNING: '#{arg}' not understood"
+ end
+ end
+
+ arity = args.size
+ arity = -1 if arity > MAGIC_ARITY_THRESHOLD or raw
+
+ return {
+ 'return' => return_type,
+ 'name' => function_name,
+ 'args' => args,
+ 'arity' => arity
+ }
+ end
+
+ raise SyntaxError, "Can't parse signature: #{sig}"
+ end # def parse_signature
+
+ def generate(src, options={})
+
+ if not Hash === options then
+ options = {:expand_types=>options}
+ end
+
+ expand_types = options[:expand_types]
+ singleton = options[:singleton]
+ result = self.strip_comments(src)
+
+ signature = parse_signature(src, !expand_types)
+ function_name = signature['name']
+ return_type = signature['return']
+ arity = signature['arity']
+
+ if expand_types then
+ prefix = "static VALUE #{function_name}("
+ if arity == MAGIC_ARITY then
+ prefix += "int argc, VALUE *argv, VALUE self"
+ else
+ prefix += "VALUE self"
+ signature['args'].each do |arg, type|
+ prefix += ", VALUE _#{arg}"
+ end
+ end
+ prefix += ") {\n"
+ if arity == MAGIC_ARITY then
+ count = 0
+ signature['args'].each do |arg, type|
+ prefix += " #{type} #{arg} = #{ruby2c(type)}(argv[#{count}]);\n"
+ count += 1
+ end
+ else
+ signature['args'].each do |arg, type|
+ prefix += " #{type} #{arg} = #{ruby2c(type)}(_#{arg});\n"
+ end
+ end
+ # replace the function signature (hopefully) with new sig (prefix)
+ result.sub!(/[^;\/\"\>]+#{function_name}\s*\([^\{]+\{/, "\n" + prefix)
+ result.sub!(/\A\n/, '') # strip off the \n in front in case we added it
+ unless return_type == "void" then
+ raise SyntaxError, "Couldn't find return statement for #{function_name}" unless
+ result =~ /return/
+ result.gsub!(/return\s+([^\;\}]+)/) do
+ "return #{c2ruby(return_type)}(#{$1})"
+ end
+ else
+ result.sub!(/\s*\}\s*\Z/, "\nreturn Qnil;\n}")
+ end
+ else
+ prefix = "static #{return_type} #{function_name}("
+ result.sub!(/[^;\/\"\>]+#{function_name}\s*\(/, prefix)
+ result.sub!(/\A\n/, '') # strip off the \n in front in case we added it
+ end
+
+ delta = if result =~ /\A(static.*?\{)/m then
+ $1.split(/\n/).size
+ else
+ warn "WARNING: Can't find signature in #{result.inspect}\n" unless $TESTING
+ 0
+ end
+
+ file, line = caller[1].split(/:/)
+ result = "# line #{line.to_i + delta} \"#{file}\"\n" + result unless $DEBUG
+
+ @src << result
+ @sig[function_name] = [arity,singleton]
+
+ return result if $TESTING
+ end # def generate
+
+ def module_name
+ unless defined? @module_name then
+ module_name = @mod.name.gsub('::','__')
+ md5 = Digest::MD5.new
+ @sig.keys.sort_by{|x| x.to_s}.each { |m| md5 << m.to_s }
+ @module_name = "Inline_#{module_name}_#{md5.to_s[0,4]}"
+ end
+ @module_name
+ end
+
+ def so_name
+ unless defined? @so_name then
+ @so_name = "#{Inline.directory}/#{module_name}.#{Config::CONFIG["DLEXT"]}"
+ end
+ @so_name
+ end
+
+ attr_reader :rb_file, :mod
+ attr_accessor :mod, :src, :sig, :flags, :libs if $TESTING
+
+ public
+
+ def initialize(mod)
+ raise ArgumentError, "Class/Module arg is required" unless Module === mod
+ # new (but not on some 1.8s) -> inline -> real_caller|eval
+ stack = caller
+ meth = stack.shift until meth =~ /in .(inline|test_)/ or stack.empty?
+ raise "Couldn't discover caller" if stack.empty?
+ real_caller = stack.first
+ real_caller = stack[3] if real_caller =~ /\(eval\)/
+ @real_caller = real_caller.split(/:/).first
+ @rb_file = File.expand_path(@real_caller)
+
+ @mod = mod
+ @src = []
+ @sig = {}
+ @flags = []
+ @libs = []
+ @init_extra = []
+ end
+
+ ##
+ # Attempts to load pre-generated code returning true if it succeeds.
+
+ def load_cache
+ begin
+ file = File.join("inline", File.basename(so_name))
+ if require file then
+ dir = Inline.directory
+ warn "WARNING: #{dir} exists but is not being used" if test ?d, dir
+ return true
+ end
+ rescue LoadError
+ end
+ return false
+ end
+
+ ##
+ # Loads the generated code back into ruby
+
+ def load
+ require "#{so_name}" or raise LoadError, "require on #{so_name} failed"
+ end
+
+ ##
+ # Builds the source file, if needed, and attempts to compile it.
+
+ def build
+ so_name = self.so_name
+ so_exists = File.file? so_name
+
+ unless so_exists and File.mtime(rb_file) < File.mtime(so_name)
+
+ src_name = "#{Inline.directory}/#{module_name}.c"
+ old_src_name = "#{src_name}.old"
+ should_compare = File.write_with_backup(src_name) do |io|
+ io.puts
+ io.puts "#include \"ruby.h\""
+ io.puts
+ io.puts @src.join("\n\n")
+ io.puts
+ io.puts
+ io.puts "#ifdef __cplusplus"
+ io.puts "extern \"C\" {"
+ io.puts "#endif"
+ io.puts " void Init_#{module_name}() {"
+ io.puts " VALUE c = rb_cObject;"
+ # TODO: use rb_class2path
+ @mod.name.split("::").each do |n|
+ io.puts " c = rb_const_get_at(c,rb_intern(\"#{n}\"));"
+ end
+ @sig.keys.sort.each do |name|
+ arity, singleton = @sig[name]
+ if singleton then
+ io.print " rb_define_singleton_method(c, \"#{name}\", "
+ else
+ io.print " rb_define_method(c, \"#{name}\", "
+ end
+ io.puts "(VALUE(*)(ANYARGS))#{name}, #{arity});"
+ end
+
+ io.puts @init_extra.join("\n") unless @init_extra.empty?
+
+ io.puts
+ io.puts " }"
+ io.puts "#ifdef __cplusplus"
+ io.puts "}"
+ io.puts "#endif"
+ io.puts
+ end
+
+ # recompile only if the files are different
+ recompile = true
+ if so_exists and should_compare and
+ File::compare(old_src_name, src_name, $DEBUG) then
+ recompile = false
+
+ # Updates the timestamps on all the generated/compiled files.
+ # Prevents us from entering this conditional unless the source
+ # file changes again.
+ t = Time.now
+ File.utime(t, t, src_name, old_src_name, so_name)
+ end
+
+ if recompile then
+
+ # extracted from mkmf.rb
+ srcdir = Config::CONFIG["srcdir"]
+ archdir = Config::CONFIG["archdir"]
+ if File.exist? archdir + "/ruby.h" then
+ hdrdir = archdir
+ elsif File.exist? srcdir + "/ruby.h" then
+ hdrdir = srcdir
+ else
+ $stderr.puts "ERROR: Can't find header files for ruby. Exiting..."
+ exit 1
+ end
+
+ flags = @flags.join(' ')
+ flags += " #{$INLINE_FLAGS}" if defined? $INLINE_FLAGS# DEPRECATE
+ libs = @libs.join(' ')
+ libs += " #{$INLINE_LIBS}" if defined? $INLINE_LIBS # DEPRECATE
+
+ cmd = "#{Config::CONFIG['LDSHARED']} #{flags} #{Config::CONFIG['CFLAGS']} -I #{hdrdir} -o #{so_name} #{src_name} #{libs}"
+
+ case RUBY_PLATFORM
+ when /mswin32/ then
+ cmd += " -link /INCREMENTAL:no /EXPORT:Init_#{module_name}"
+ when /i386-cygwin/ then
+ cmd += ' -L/usr/local/lib -lruby.dll'
+ end
+
+ cmd += " 2> /dev/null" if $TESTING and not $DEBUG
+
+ $stderr.puts "Building #{so_name} with '#{cmd}'" if $DEBUG
+ `#{cmd}`
+ if $? != 0 then
+ bad_src_name = src_name + ".bad"
+ File.rename src_name, bad_src_name
+ raise CompilationError, "error executing #{cmd}: #{$?}\nRenamed #{src_name} to #{bad_src_name}"
+ end
+ $stderr.puts "Built successfully" if $DEBUG
+ end
+
+ else
+ $stderr.puts "#{so_name} is up to date" if $DEBUG
+ end # unless (file is out of date)
+ end # def build
+
+ ##
+ # Adds compiler options to the compiler command line. No
+ # preprocessing is done, so you must have all your dashes and
+ # everything.
+
+ def add_compile_flags(*flags)
+ @flags.push(*flags)
+ end
+
+ ##
+ # Adds linker flags to the link command line. No preprocessing is
+ # done, so you must have all your dashes and everything.
+
+ def add_link_flags(*flags)
+ @libs.push(*flags)
+ end
+
+ ##
+ # Adds custom content to the end of the init function.
+
+ def add_to_init(*src)
+ @init_extra.push(*src)
+ end
+
+ ##
+ # Registers C type-casts +r2c+ and +c2r+ for +type+.
+
+ def add_type_converter(type, r2c, c2r)
+ $stderr.puts "WARNING: overridding #{type}" if @@type_map.has_key? type
+ @@type_map[type] = [r2c, c2r]
+ end
+
+ ##
+ # Adds an include to the top of the file. Don't forget to use
+ # quotes or angle brackets.
+
+ def include(header)
+ @src << "#include #{header}"
+ end
+
+ ##
+ # Adds any amount of text/code to the source
+
+ def prefix(code)
+ @src << code
+ end
+
+ ##
+ # Adds a C function to the source, including performing automatic
+ # type conversion to arguments and the return value. Unknown type
+ # conversions can be extended by using +add_type_converter+.
+
+ def c src
+ self.generate(src,:expand_types=>true)
+ end
+
+ ##
+ # Same as +c+, but adds a class function.
+
+ def c_singleton src
+ self.generate(src,:expand_types=>true,:singleton=>true)
+ end
+
+ ##
+ # Adds a raw C function to the source. This version does not
+ # perform any type conversion and must conform to the ruby/C
+ # coding conventions.
+
+ def c_raw src
+ self.generate(src)
+ end
+
+ ##
+ # Same as +c_raw+, but adds a class function.
+
+ def c_raw_singleton src
+ self.generate(src, :singleton=>true)
+ end
+
+ end # class Inline::C
+
+ class Packager
+ attr_accessor :name, :version, :summary, :libs_copied, :inline_dir
+
+ def initialize(name, version, summary = '')
+ @name = name
+ @version = version
+ @summary = summary
+ @libs_copied = false
+ @ext = Config::CONFIG['DLEXT']
+
+ # TODO (maybe) put libs in platform dir
+ @inline_dir = File.join "lib", "inline"
+ end
+
+ def package
+ copy_libs
+ generate_rakefile
+ build_gem
+ end
+
+ def copy_libs
+ unless @libs_copied then
+ FileUtils.mkdir_p @inline_dir
+ built_libs = Dir.glob File.join(Inline.directory, "*.#{@ext}")
+ FileUtils.cp built_libs, @inline_dir
+ @libs_copied = true
+ end
+ end
+
+ def generate_rakefile
+ if File.exists? 'Rakefile' then
+ unless $TESTING then
+ STDERR.puts "Hrm, you already have a Rakefile, so I didn't touch it."
+ STDERR.puts "You might have to add the following files to your gemspec's files list:"
+ STDERR.puts "\t#{gem_libs.join "\n\t"}"
+ end
+ return
+ end
+
+ rakefile = eval RAKEFILE_TEMPLATE
+
+ STDERR.puts "==> Generating Rakefile" unless $TESTING
+ File.open 'Rakefile', 'w' do |fp|
+ fp.puts rakefile
+ end
+ end
+
+ def build_gem
+ STDERR.puts "==> Running rake" unless $TESTING
+
+ cmd = "rake package"
+ cmd += "> /dev/null 2> /dev/null" if $TESTING
+ system cmd
+
+ STDERR.puts unless $TESTING
+ STDERR.puts "Ok, you now have a gem in ./pkg, enjoy!" unless $TESTING
+ end
+
+ def gem_libs
+ unless defined? @gem_libs then
+ @gem_libs = Dir.glob File.join(@inline_dir, "*.#{@ext}")
+ files = Dir.glob(File.join('lib', '*')).select { |f| test ?f, f }
+
+ @gem_libs.push(*files)
+ @gem_libs.sort!
+ end
+ @gem_libs
+ end
+
+ RAKEFILE_TEMPLATE = '%[require "rake"\nrequire "rake/gempackagetask"\n\nsummary = #{summary.inspect}\n\nif summary.empty? then\n STDERR.puts "*************************************"\n STDERR.puts "*** Summary not filled in, SHAME! ***"\n STDERR.puts "*************************************"\nend\n\nspec = Gem::Specification.new do |s|\n s.name = #{name.inspect}\n s.version = #{version.inspect}\n s.summary = summary\n\n s.has_rdoc = false\n s.files = #{gem_libs.inspect}\n s.add_dependency "RubyInline", ">= 3.3.0"\n s.require_path = "lib"\nend\n\ndesc "Builds a gem with #{name} in it"\nRake::GemPackageTask.new spec do |pkg|\n pkg.need_zip = false\n pkg.need_tar = false\nend\n]'
+ end # class Packager
+end # module Inline
+
+class Module
+
+ ##
+ # options is a hash that allows you to pass extra data to your
+ # builder. The only key that is guaranteed to exist is :testing.
+
+ attr_reader :options
+
+ ##
+ # Extends the Module class to have an inline method. The default
+ # language/builder used is C, but can be specified with the +lang+
+ # parameter.
+
+ def inline(lang = :C, options={})
+ case options
+ when TrueClass, FalseClass then
+ warn "WARNING: 2nd argument to inline is now a hash, changing to {:testing=>#{options}}" unless options
+ options = { :testing => options }
+ when Hash
+ options[:testing] ||= false
+ else
+ raise ArgumentError, "BLAH"
+ end
+
+ builder_class = begin
+ Inline.const_get(lang)
+ rescue NameError
+ require "inline/#{lang}"
+ Inline.const_get(lang)
+ end
+
+ @options = options
+ builder = builder_class.new self
+
+ yield builder
+
+ unless options[:testing] then
+ unless builder.load_cache then
+ builder.build
+ builder.load
+ end
+ end
+ end
+end
+
+class File
+
+ ##
+ # Equivalent to +File::open+ with an associated block, but moves
+ # any existing file with the same name to the side first.
+
+ def self.write_with_backup(path) # returns true if file already existed
+
+ # move previous version to the side if it exists
+ renamed = false
+ if test ?f, path then
+ renamed = true
+ File.rename path, path + ".old"
+ end
+
+ File.open(path, "w") do |io|
+ yield(io)
+ end
+
+ return renamed
+ end
+end # class File
+
+class Dir
+
+ ##
+ # +assert_secure+ checks to see that +path+ exists and has minimally
+ # writable permissions. If not, it prints an error and exits. It
+ # only works on +POSIX+ systems. Patches for other systems are
+ # welcome.
+
+ def self.assert_secure(path)
+ mode = File.stat(path).mode
+ unless ((mode % 01000) & 0022) == 0 then
+ if $TESTING then
+ raise SecurityError, "Directory #{path} is insecure"
+ else
+ $stderr.puts "#{path} is insecure (#{sprintf('%o', mode)}), needs 0700 for perms. Exiting."
+ exit 1
+ end
+ end
+ end
+end
Added: packages/libinline-ruby/trunk/lib/inline_package
===================================================================
--- packages/libinline-ruby/trunk/lib/inline_package 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/lib/inline_package 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,15 @@
+#!/usr/bin/ruby -w
+
+require 'inline'
+
+name = ARGV.shift
+version = ARGV.shift
+summary = ARGV.shift || ""
+
+if version.nil? then # TODO better usage
+ STDERR.puts "Usage: #{$0} NAME VERSION [SUMMARY]"
+ exit 1
+end
+
+packager = Inline::Packager.new name, version, summary
+packager.package
Added: packages/libinline-ruby/trunk/setup.rb
===================================================================
--- packages/libinline-ruby/trunk/setup.rb 2006-08-01 11:04:28 UTC (rev 730)
+++ packages/libinline-ruby/trunk/setup.rb 2006-08-01 11:05:10 UTC (rev 731)
@@ -0,0 +1,1360 @@
+#
+# setup.rb
+#
+# Copyright (c) 2000-2004 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU LGPL, Lesser General Public License version 2.1.
+#
+
+unless Enumerable.method_defined?(:map) # Ruby 1.4.6
+ module Enumerable
+ alias map collect
+ end
+end
+
+unless File.respond_to?(:read) # Ruby 1.6
+ def File.read(fname)
+ open(fname) {|f|
+ return f.read
+ }
+ end
+end
+
+def File.binread(fname)
+ open(fname, 'rb') {|f|
+ return f.read
+ }
+end
+
+# for corrupted windows stat(2)
+def File.dir?(path)
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
+end
+
+
+class SetupError < StandardError; end
+
+def setup_rb_error(msg)
+ raise SetupError, msg
+end
+
+#
+# Config
+#
+
+if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
+ ARGV.delete(arg)
+ require arg.split(/=/, 2)[1]
+ $".push 'rbconfig.rb'
+else
+ require 'rbconfig'
+end
+
+def multipackage_install?
+ FileTest.directory?(File.dirname($0) + '/packages')
+end
+
+
+class ConfigItem
+ def initialize(name, template, default, desc)
+ @name = name.freeze
+ @template = template
+ @value = default
+ @default = default.dup.freeze
+ @description = desc
+ end
+
+ attr_reader :name
+ attr_reader :description
+
+ attr_accessor :default
+ alias help_default default
+
+ def help_opt
+ "--#{@name}=#{@template}"
+ end
+
+ def value
+ @value
+ end
+
+ def eval(table)
+ @value.gsub(%r<\$([^/]+)>) { table[$1] }
+ end
+
+ def set(val)
+ @value = check(val)
+ end
+
+ private
+
+ def check(val)
+ setup_rb_error "config: --#{name} requires argument" unless val
+ val
+ end
+end
+
+class BoolItem < ConfigItem
+ def config_type
+ 'bool'
+ end
+
+ def help_opt
+ "--#{@name}"
+ end
+
+ private
+
+ def check(val)
+ return 'yes' unless val
+ unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
+ setup_rb_error "config: --#{@name} accepts only yes/no for argument"
+ end
+ (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
+ end
+end
+
+class PathItem < ConfigItem
+ def config_type
+ 'path'
+ end
+
+ private
+
+ def check(path)
+ setup_rb_error "config: --#{@name} requires argument" unless path
+ path[0,1] == '$' ? path : File.expand_path(path)
+ end
+end
+
+class ProgramItem < ConfigItem
+ def config_type
+ 'program'
+ end
+end
+
+class SelectItem < ConfigItem
+ def initialize(name, template, default, desc)
+ super
+ @ok = template.split('/')
+ end
+
+ def config_type
+ 'select'
+ end
+
+ private
+
+ def check(val)
+ unless @ok.include?(val.strip)
+ setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
+ end
+ val.strip
+ end
+end
+
+class PackageSelectionItem < ConfigItem
+ def initialize(name, template, default, help_default, desc)
+ super name, template, default, desc
+ @help_default = help_default
+ end
+
+ attr_reader :help_default
+
+ def config_type
+ 'package'
+ end
+
+ private
+
+ def check(val)
+ unless File.dir?("packages/#{val}")
+ setup_rb_error "config: no such package: #{val}"
+ end
+ val
+ end
+end
+
+class ConfigTable_class
+
+ def initialize(items)
+ @items = items
+ @table = {}
+ items.each do |i|
+ @table[i.name] = i
+ end
+ ALIASES.each do |ali, name|
+ @table[ali] = @table[name]
+ end
+ end
+
+ include Enumerable
+
+ def each(&block)
+ @items.each(&block)
+ end
+
+ def key?(name)
+ @table.key?(name)
+ end
+
+ def lookup(name)
+ @table[name] or raise ArgumentError, "no such config item: #{name}"
+ end
+
+ def add(item)
+ @items.push item
+ @table[item.name] = item
+ end
+
+ def remove(name)
+ item = lookup(name)
+ @items.delete_if {|i| i.name == name }
+ @table.delete_if {|name, i| i.name == name }
+ item
+ end
+
+ def new
+ dup()
+ end
+
+ def savefile
+ '.config'
+ end
+
+ def load
+ begin
+ t = dup()
+ File.foreach(savefile()) do |line|
+ k, v = *line.split(/=/, 2)
+ t[k] = v.strip
+ end
+ t
+ rescue Errno::ENOENT
+ setup_rb_error $!.message + "#{File.basename($0)} config first"
+ end
+ end
+
+ def save
+ @items.each {|i| i.value }
+ File.open(savefile(), 'w') {|f|
+ @items.each do |i|
+ f.printf "%s=%s\n", i.name, i.value if i.value
+ end
+ }
+ end
+
+ def [](key)
+ lookup(key).eval(self)
+ end
+
+ def []=(key, val)
+ lookup(key).set val
+ end
+
+end
+
+c = ::Config::CONFIG
+
+rubypath = c['bindir'] + '/' + c['ruby_install_name']
+
+major = c['MAJOR'].to_i
+minor = c['MINOR'].to_i
+teeny = c['TEENY'].to_i
+version = "#{major}.#{minor}"
+
+# ruby ver. >= 1.4.4?
+newpath_p = ((major >= 2) or
+ ((major == 1) and
+ ((minor >= 5) or
+ ((minor == 4) and (teeny >= 4)))))
+
+if c['rubylibdir']
+ # V < 1.6.3
+ _stdruby = c['rubylibdir']
+ _siteruby = c['sitedir']
+ _siterubyver = c['sitelibdir']
+ _siterubyverarch = c['sitearchdir']
+elsif newpath_p
+ # 1.4.4 <= V <= 1.6.3
+ _stdruby = "$prefix/lib/ruby/#{version}"
+ _siteruby = c['sitedir']
+ _siterubyver = "$siteruby/#{version}"
+ _siterubyverarch = "$siterubyver/#{c['arch']}"
+else
+ # V < 1.4.4
+ _stdruby = "$prefix/lib/ruby/#{version}"
+ _siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
+ _siterubyver = _siteruby
+ _siterubyverarch = "$siterubyver/#{c['arch']}"
+end
+libdir = '-* dummy libdir *-'
+stdruby = '-* dummy rubylibdir *-'
+siteruby = '-* dummy site_ruby *-'
+siterubyver = '-* dummy site_ruby version *-'
+parameterize = lambda {|path|
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\
+ .sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\
+ .sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\
+ .sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\
+ .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver')
+}
+libdir = parameterize.call(c['libdir'])
+stdruby = parameterize.call(_stdruby)
+siteruby = parameterize.call(_siteruby)
+siterubyver = parameterize.call(_siterubyver)
+siterubyverarch = parameterize.call(_siterubyverarch)
+
+if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
+else
+ makeprog = 'make'
+end
+
+common_conf = [
+ PathItem.new('prefix', 'path', c['prefix'],
+ 'path prefix of target environment'),
+ PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
+ 'the directory for commands'),
+ PathItem.new('libdir', 'path', libdir,
+ 'the directory for libraries'),
+ PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
+ 'the directory for shared data'),
+ PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
+ 'the directory for man pages'),
+ PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
+ 'the directory for man pages'),
+ PathItem.new('stdruby', 'path', stdruby,
+ 'the directory for standard ruby libraries'),
+ PathItem.new('siteruby', 'path', siteruby,
+ 'the directory for version-independent aux ruby libraries'),
+ PathItem.new('siterubyver', 'path', siterubyver,
+ 'the directory for aux ruby libraries'),
+ PathItem.new('siterubyverarch', 'path', siterubyverarch,
+ 'the directory for aux ruby binaries'),
+ PathItem.new('rbdir', 'path', '$siterubyver',
+ 'the directory for ruby scripts'),
+ PathItem.new('sodir', 'path', '$siterubyverarch',
+ 'the directory for ruby extentions'),
+ PathItem.new('rubypath', 'path', rubypath,
+ 'the path to set to #! line'),
+ ProgramItem.new('rubyprog', 'name', rubypath,
+ 'the ruby program using for installation'),
+ ProgramItem.new('makeprog', 'name', makeprog,
+ 'the make program to compile ruby extentions'),
+ SelectItem.new('shebang', 'all/ruby/never', 'ruby',
+ 'shebang line (#!) editing mode'),
+ BoolItem.new('without-ext', 'yes/no', 'no',
+ 'does not compile/install ruby extentions')
+]
+class ConfigTable_class # open again
+ ALIASES = {
+ 'std-ruby' => 'stdruby',
+ 'site-ruby-common' => 'siteruby', # For backward compatibility
+ 'site-ruby' => 'siterubyver', # For backward compatibility
+ 'bin-dir' => 'bindir',
+ 'bin-dir' => 'bindir',
+ 'rb-dir' => 'rbdir',
+ 'so-dir' => 'sodir',
+ 'data-dir' => 'datadir',
+ 'ruby-path' => 'rubypath',
+ 'ruby-prog' => 'rubyprog',
+ 'ruby' => 'rubyprog',
+ 'make-prog' => 'makeprog',
+ 'make' => 'makeprog'
+ }
+end
+multipackage_conf = [
+ PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
+ 'package names that you want to install'),
+ PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
+ 'package names that you do not want to install')
+]
+if multipackage_install?
+ ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf)
+else
+ ConfigTable = ConfigTable_class.new(common_conf)
+end
+
+
+module MetaConfigAPI
+
+ def eval_file_ifexist(fname)
+ instance_eval File.read(fname), fname, 1 if File.file?(fname)
+ end
+
+ def config_names
+ ConfigTable.map {|i| i.name }
+ end
+
+ def config?(name)
+ ConfigTable.key?(name)
+ end
+
+ def bool_config?(name)
+ ConfigTable.lookup(name).config_type == 'bool'
+ end
+
+ def path_config?(name)
+ ConfigTable.lookup(name).config_type == 'path'
+ end
+
+ def value_config?(name)
+ case ConfigTable.lookup(name).config_type
+ when 'bool', 'path'
+ true
+ else
+ false
+ end
+ end
+
+ def add_config(item)
+ ConfigTable.add item
+ end
+
+ def add_bool_config(name, default, desc)
+ ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
+ end
+
+ def add_path_config(name, default, desc)
+ ConfigTable.add PathItem.new(name, 'path', default, desc)
+ end
+
+ def set_config_default(name, default)
+ ConfigTable.lookup(name).default = default
+ end
+
+ def remove_config(name)
+ ConfigTable.remove(name)
+ end
+
+end
+
+
+#
+# File Operations
+#
+
+module FileOperations
+
+ def mkdir_p(dirname, prefix = nil)
+ dirname = prefix + File.expand_path(dirname) if prefix
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
+ return if no_harm?
+
+ # does not check '/'... it's too abnormal case
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
+ if /\A[a-z]:\z/i =~ dirs[0]
+ disk = dirs.shift
+ dirs[0] = disk + dirs[0]
+ end
+ dirs.each_index do |idx|
+ path = dirs[0..idx].join('')
+ Dir.mkdir path unless File.dir?(path)
+ end
+ end
+
+ def rm_f(fname)
+ $stderr.puts "rm -f #{fname}" if verbose?
+ return if no_harm?
+
+ if File.exist?(fname) or File.symlink?(fname)
+ File.chmod 0777, fname
+ File.unlink fname
+ end
+ end
+
+ def rm_rf(dn)
+ $stderr.puts "rm -rf #{dn}" if verbose?
+ return if no_harm?
+
+ Dir.chdir dn
+ Dir.foreach('.') do |fn|
+ next if fn == '.'
+ next if fn == '..'
+ if File.dir?(fn)
+ verbose_off {
+ rm_rf fn
+ }
+ else
+ verbose_off {
+ rm_f fn
+ }
+ end
+ end
+ Dir.chdir '..'
+ Dir.rmdir dn
+ end
+
+ def move_file(src, dest)
+ File.unlink dest if File.exist?(dest)
+ begin
+ File.rename src, dest
+ rescue
+ File.open(dest, 'wb') {|f| f.write File.binread(src) }
+ File.chmod File.stat(src).mode, dest
+ File.unlink src
+ end
+ end
+
+ def install(from, dest, mode, prefix = nil)
+ $stderr.puts "install #{from} #{dest}" if verbose?
+ return if no_harm?
+
+ realdest = prefix ? prefix + File.expand_path(dest) : dest
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
+ str = File.binread(from)
+ if diff?(str, realdest)
+ verbose_off {
+ rm_f realdest if File.exist?(realdest)
+ }
+ File.open(realdest, 'wb') {|f|
+ f.write str
+ }
+ File.chmod mode, realdest
+
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
+ if prefix
+ f.puts realdest.sub(prefix, '')
+ else
+ f.puts realdest
+ end
+ }
+ end
+ end
+
+ def diff?(new_content, path)
+ return true unless File.exist?(path)
+ new_content != File.binread(path)
+ end
+
+ def command(str)
+ $stderr.puts str if verbose?
+ system str or raise RuntimeError, "'system #{str}' failed"
+ end
+
+ def ruby(str)
+ command config('rubyprog') + ' ' + str
+ end
+
+ def make(task = '')
+ command config('makeprog') + ' ' + task
+ end
+
+ def extdir?(dir)
+ File.exist?(dir + '/MANIFEST')
+ end
+
+ def all_files_in(dirname)
+ Dir.open(dirname) {|d|
+ return d.select {|ent| File.file?("#{dirname}/#{ent}") }
+ }
+ end
+
+ REJECT_DIRS = %w(
+ CVS SCCS RCS CVS.adm .svn
+ )
+
+ def all_dirs_in(dirname)
+ Dir.open(dirname) {|d|
+ return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
+ }
+ end
+
+end
+
+
+#
+# Main Installer
+#
+
+module HookUtils
+
+ def run_hook(name)
+ try_run_hook "#{curr_srcdir()}/#{name}" or
+ try_run_hook "#{curr_srcdir()}/#{name}.rb"
+ end
+
+ def try_run_hook(fname)
+ return false unless File.file?(fname)
+ begin
+ instance_eval File.read(fname), fname, 1
+ rescue
+ setup_rb_error "hook #{fname} failed:\n" + $!.message
+ end
+ true
+ end
+
+end
+
+
+module HookScriptAPI
+
+ def get_config(key)
+ @config[key]
+ end
+
+ alias config get_config
+
+ def set_config(key, val)
+ @config[key] = val
+ end
+
+ #
+ # srcdir/objdir (works only in the package directory)
+ #
+
+ #abstract srcdir_root
+ #abstract objdir_root
+ #abstract relpath
+
+ def curr_srcdir
+ "#{srcdir_root()}/#{relpath()}"
+ end
+
+ def curr_objdir
+ "#{objdir_root()}/#{relpath()}"
+ end
+
+ def srcfile(path)
+ "#{curr_srcdir()}/#{path}"
+ end
+
+ def srcexist?(path)
+ File.exist?(srcfile(path))
+ end
+
+ def srcdirectory?(path)
+ File.dir?(srcfile(path))
+ end
+
+ def srcfile?(path)
+ File.file? srcfile(path)
+ end
+
+ def srcentries(path = '.')
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
+ return d.to_a - %w(. ..)
+ }
+ end
+
+ def srcfiles(path = '.')
+ srcentries(path).select {|fname|
+ File.file?(File.join(curr_srcdir(), path, fname))
+ }
+ end
+
+ def srcdirectories(path = '.')
+ srcentries(path).select {|fname|
+ File.dir?(File.join(curr_srcdir(), path, fname))
+ }
+ end
+
+end
+
+
+class ToplevelInstaller
+
+ Version = '3.3.1'
+ Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
+
+ TASKS = [
+ [ 'all', 'do config, setup, then install' ],
+ [ 'config', 'saves your configurations' ],
+ [ 'show', 'shows current configuration' ],
+ [ 'setup', 'compiles ruby extentions and others' ],
+ [ 'install', 'installs files' ],
+ [ 'clean', "does `make clean' for each extention" ],
+ [ 'distclean',"does `make distclean' for each extention" ]
+ ]
+
+ def ToplevelInstaller.invoke
+ instance().invoke
+ end
+
+ @singleton = nil
+
+ def ToplevelInstaller.instance
+ @singleton ||= new(File.dirname($0))
+ @singleton
+ end
+
+ include MetaConfigAPI
+
+ def initialize(ardir_root)
+ @config = nil
+ @options = { 'verbose' => true }
+ @ardir = File.expand_path(ardir_root)
+ end
+
+ def inspect
+ "#<#{self.class} #{__id__()}>"
+ end
+
+ def invoke
+ run_metaconfigs
+ case task = parsearg_global()
+ when nil, 'all'
+ @config = load_config('config')
+ parsearg_config
+ init_installers
+ exec_config
+ exec_setup
+ exec_install
+ else
+ @config = load_config(task)
+ __send__ "parsearg_#{task}"
+ init_installers
+ __send__ "exec_#{task}"
+ end
+ end
+
+ def run_metaconfigs
+ eval_file_ifexist "#{@ardir}/metaconfig"
+ end
+
+ def load_config(task)
+ case task
+ when 'config'
+ ConfigTable.new
+ when 'clean', 'distclean'
+ if File.exist?(ConfigTable.savefile)
+ then ConfigTable.load
+ else ConfigTable.new
+ end
+ else
+ ConfigTable.load
+ end
+ end
+
+ def init_installers
+ @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
+ end
+
+ #
+ # Hook Script API bases
+ #
+
+ def srcdir_root
+ @ardir
+ end
+
+ def objdir_root
+ '.'
+ end
+
+ def relpath
+ '.'
+ end
+
+ #
+ # Option Parsing
+ #
+
+ def parsearg_global
+ valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
+
+ while arg = ARGV.shift
+ case arg
+ when /\A\w+\z/
+ setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg
+ return arg
+
+ when '-q', '--quiet'
+ @options['verbose'] = false
+
+ when '--verbose'
+ @options['verbose'] = true
+
+ when '-h', '--help'
+ print_usage $stdout
+ exit 0
+
+ when '-v', '--version'
+ puts "#{File.basename($0)} version #{Version}"
+ exit 0
+
+ when '--copyright'
+ puts Copyright
+ exit 0
+
+ else
+ setup_rb_error "unknown global option '#{arg}'"
+ end
+ end
+
+ nil
+ end
+
+
+ def parsearg_no_options
+ unless ARGV.empty?
+ setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}"
+ end
+ end
+
+ alias parsearg_show parsearg_no_options
+ alias parsearg_setup parsearg_no_options
+ alias parsearg_clean parsearg_no_options
+ alias parsearg_distclean parsearg_no_options
+
+ def parsearg_config
+ re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/
+ @options['config-opt'] = []
+
+ while i = ARGV.shift
+ if /\A--?\z/ =~ i
+ @options['config-opt'] = ARGV.dup
+ break
+ end
+ m = re.match(i) or setup_rb_error "config: unknown option #{i}"
+ name, value = *m.to_a[1,2]
+ @config[name] = value
+ end
+ end
+
+ def parsearg_install
+ @options['no-harm'] = false
+ @options['install-prefix'] = ''
+ while a = ARGV.shift
+ case a
+ when /\A--no-harm\z/
+ @options['no-harm'] = true
+ when /\A--prefix=(.*)\z/
+ path = $1
+ path = File.expand_path(path) unless path[0,1] == '/'
+ @options['install-prefix'] = path
+ else
+ setup_rb_error "install: unknown option #{a}"
+ end
+ end
+ end
+
+ def print_usage(out)
+ out.puts 'Typical Installation Procedure:'
+ out.puts " $ ruby #{File.basename $0} config"
+ out.puts " $ ruby #{File.basename $0} setup"
+ out.puts " # ruby #{File.basename $0} install (may require root privilege)"
+ out.puts
+ out.puts 'Detailed Usage:'
+ out.puts " ruby #{File.basename $0} <global option>"
+ out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
+
+ fmt = " %-24s %s\n"
+ out.puts
+ out.puts 'Global options:'
+ out.printf fmt, '-q,--quiet', 'suppress message outputs'
+ out.printf fmt, ' --verbose', 'output messages verbosely'
+ out.printf fmt, '-h,--help', 'print this message'
+ out.printf fmt, '-v,--version', 'print version and quit'
+ out.printf fmt, ' --copyright', 'print copyright and quit'
+ out.puts
+ out.puts 'Tasks:'
+ TASKS.each do |name, desc|
+ out.printf fmt, name, desc
+ end
+
+ fmt = " %-24s %s [%s]\n"
+ out.puts
+ out.puts 'Options for CONFIG or ALL:'
+ ConfigTable.each do |item|
+ out.printf fmt, item.help_opt, item.description, item.help_default
+ end
+ out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
+ out.puts
+ out.puts 'Options for INSTALL:'
+ out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
+ out.printf fmt, '--prefix=path', 'install path prefix', '$prefix'
+ out.puts
+ end
+
+ #
+ # Task Handlers
+ #
+
+ def exec_config
+ @installer.exec_config
+ @config.save # must be final
+ end
+
+ def exec_setup
+ @installer.exec_setup
+ end
+
+ def exec_install
+ @installer.exec_install
+ end
+
+ def exec_show
+ ConfigTable.each do |i|
+ printf "%-20s %s\n", i.name, i.value
+ end
+ end
+
+ def exec_clean
+ @installer.exec_clean
+ end
+
+ def exec_distclean
+ @installer.exec_distclean
+ end
+
+end
+
+
+class ToplevelInstallerMulti < ToplevelInstaller
+
+ include HookUtils
+ include HookScriptAPI
+ include FileOperations
+
+ def initialize(ardir)
+ super
+ @packages = all_dirs_in("#{@ardir}/packages")
+ raise 'no package exists' if @packages.empty?
+ end
+
+ def run_metaconfigs
+ eval_file_ifexist "#{@ardir}/metaconfig"
+ @packages.each do |name|
+ eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
+ end
+ end
+
+ def init_installers
+ @installers = {}
+ @packages.each do |pack|
+ @installers[pack] = Installer.new(@config, @options,
+ "#{@ardir}/packages/#{pack}",
+ "packages/#{pack}")
+ end
+
+ with = extract_selection(config('with'))
+ without = extract_selection(config('without'))
+ @selected = @installers.keys.select {|name|
+ (with.empty? or with.include?(name)) \
+ and not without.include?(name)
+ }
+ end
+
+ def extract_selection(list)
+ a = list.split(/,/)
+ a.each do |name|
+ setup_rb_error "no such package: #{name}" unless @installers.key?(name)
+ end
+ a
+ end
+
+ def print_usage(f)
+ super
+ f.puts 'Inluded packages:'
+ f.puts ' ' + @packages.sort.join(' ')
+ f.puts
+ end
+
+ #
+ # multi-package metaconfig API
+ #
+
+ attr_reader :packages
+
+ def declare_packages(list)
+ raise 'package list is empty' if list.empty?
+ list.each do |name|
+ raise "directory packages/#{name} does not exist"\
+ unless File.dir?("#{@ardir}/packages/#{name}")
+ end
+ @packages = list
+ end
+
+ #
+ # Task Handlers
+ #
+
+ def exec_config
+ run_hook 'pre-config'
+ each_selected_installers {|inst| inst.exec_config }
+ run_hook 'post-config'
+ @config.save # must be final
+ end
+
+ def exec_setup
+ run_hook 'pre-setup'
+ each_selected_installers {|inst| inst.exec_setup }
+ run_hook 'post-setup'
+ end
+
+ def exec_install
+ run_hook 'pre-install'
+ each_selected_installers {|inst| inst.exec_install }
+ run_hook 'post-install'
+ end
+
+ def exec_clean
+ rm_f ConfigTable.savefile
+ run_hook 'pre-clean'
+ each_selected_installers {|inst| inst.exec_clean }
+ run_hook 'post-clean'
+ end
+
+ def exec_distclean
+ rm_f ConfigTable.savefile
+ run_hook 'pre-distclean'
+ each_selected_installers {|inst| inst.exec_distclean }
+ run_hook 'post-distclean'
+ end
+
+ #
+ # lib
+ #
+
+ def each_selected_installers
+ Dir.mkdir 'packages' unless File.dir?('packages')
+ @selected.each do |pack|
+ $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
+ Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
+ Dir.chdir "packages/#{pack}"
+ yield @installers[pack]
+ Dir.chdir '../..'
+ end
+ end
+
+ def verbose?
+ @options['verbose']
+ end
+
+ def no_harm?
+ @options['no-harm']
+ end
+
+end
+
+
+class Installer
+
+ FILETYPES = %w( bin lib ext data )
+
+ include HookScriptAPI
+ include HookUtils
+ include FileOperations
+
+ def initialize(config, opt, srcroot, objroot)
+ @config = config
+ @options = opt
+ @srcdir = File.expand_path(srcroot)
+ @objdir = File.expand_path(objroot)
+ @currdir = '.'
+ end
+
+ def inspect
+ "#<#{self.class} #{File.basename(@srcdir)}>"
+ end
+
+ #
+ # Hook Script API base methods
+ #
+
+ def srcdir_root
+ @srcdir
+ end
+
+ def objdir_root
+ @objdir
+ end
+
+ def relpath
+ @currdir
+ end
+
+ #
+ # configs/options
+ #
+
+ def no_harm?
+ @options['no-harm']
+ end
+
+ def verbose?
+ @options['verbose']
+ end
+
+ def verbose_off
+ begin
+ save, @options['verbose'] = @options['verbose'], false
+ yield
+ ensure
+ @options['verbose'] = save
+ end
+ end
+
+ #
+ # TASK config
+ #
+
+ def exec_config
+ exec_task_traverse 'config'
+ end
+
+ def config_dir_bin(rel)
+ end
+
+ def config_dir_lib(rel)
+ end
+
+ def config_dir_ext(rel)
+ extconf if extdir?(curr_srcdir())
+ end
+
+ def extconf
+ opt = @options['config-opt'].join(' ')
+ command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}"
+ end
+
+ def config_dir_data(rel)
+ end
+
+ #
+ # TASK setup
+ #
+
+ def exec_setup
+ exec_task_traverse 'setup'
+ end
+
+ def setup_dir_bin(rel)
+ all_files_in(curr_srcdir()).each do |fname|
+ adjust_shebang "#{curr_srcdir()}/#{fname}"
+ end
+ end
+
+ def adjust_shebang(path)
+ return if no_harm?
+ tmpfile = File.basename(path) + '.tmp'
+ begin
+ File.open(path, 'rb') {|r|
+ first = r.gets
+ return unless File.basename(config('rubypath')) == 'ruby'
+ return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby'
+ $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
+ File.open(tmpfile, 'wb') {|w|
+ w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
+ w.write r.read
+ }
+ move_file tmpfile, File.basename(path)
+ }
+ ensure
+ File.unlink tmpfile if File.exist?(tmpfile)
+ end
+ end
+
+ def setup_dir_lib(rel)
+ end
+
+ def setup_dir_ext(rel)
+ make if extdir?(curr_srcdir())
+ end
+
+ def setup_dir_data(rel)
+ end
+
+ #
+ # TASK install
+ #
+
+ def exec_install
+ rm_f 'InstalledFiles'
+ exec_task_traverse 'install'
+ end
+
+ def install_dir_bin(rel)
+ install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755
+ end
+
+ def install_dir_lib(rel)
+ install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644
+ end
+
+ def install_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ install_files ruby_extentions('.'),
+ "#{config('sodir')}/#{File.dirname(rel)}",
+ 0555
+ end
+
+ def install_dir_data(rel)
+ install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644
+ end
+
+ def install_files(list, dest, mode)
+ mkdir_p dest, @options['install-prefix']
+ list.each do |fname|
+ install fname, dest, mode, @options['install-prefix']
+ end
+ end
+
+ def ruby_scripts
+ collect_filenames_auto().select {|n| /\.rb\z/ =~ n }
+ end
+
+ # picked up many entries from cvs-1.11.1/src/ignore.c
+ reject_patterns = %w(
+ core RCSLOG tags TAGS .make.state
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
+
+ *.org *.in .*
+ )
+ mapping = {
+ '.' => '\.',
+ '$' => '\$',
+ '#' => '\#',
+ '*' => '.*'
+ }
+ REJECT_PATTERNS = Regexp.new('\A(?:' +
+ reject_patterns.map {|pat|
+ pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
+ }.join('|') +
+ ')\z')
+
+ def collect_filenames_auto
+ mapdir((existfiles() - hookfiles()).reject {|fname|
+ REJECT_PATTERNS =~ fname
+ })
+ end
+
+ def existfiles
+ all_files_in(curr_srcdir()) | all_files_in('.')
+ end
+
+ def hookfiles
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
+ }.flatten
+ end
+
+ def mapdir(filelist)
+ filelist.map {|fname|
+ if File.exist?(fname) # objdir
+ fname
+ else # srcdir
+ File.join(curr_srcdir(), fname)
+ end
+ }
+ end
+
+ def ruby_extentions(dir)
+ Dir.open(dir) {|d|
+ ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname }
+ if ents.empty?
+ setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
+ end
+ return ents
+ }
+ end
+
+ #
+ # TASK clean
+ #
+
+ def exec_clean
+ exec_task_traverse 'clean'
+ rm_f ConfigTable.savefile
+ rm_f 'InstalledFiles'
+ end
+
+ def clean_dir_bin(rel)
+ end
+
+ def clean_dir_lib(rel)
+ end
+
+ def clean_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ make 'clean' if File.file?('Makefile')
+ end
+
+ def clean_dir_data(rel)
+ end
+
+ #
+ # TASK distclean
+ #
+
+ def exec_distclean
+ exec_task_traverse 'distclean'
+ rm_f ConfigTable.savefile
+ rm_f 'InstalledFiles'
+ end
+
+ def distclean_dir_bin(rel)
+ end
+
+ def distclean_dir_lib(rel)
+ end
+
+ def distclean_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ make 'distclean' if File.file?('Makefile')
+ end
+
+ #
+ # lib
+ #
+
+ def exec_task_traverse(task)
+ run_hook "pre-#{task}"
+ FILETYPES.each do |type|
+ if config('without-ext') == 'yes' and type == 'ext'
+ $stderr.puts 'skipping ext/* by user option' if verbose?
+ next
+ end
+ traverse task, type, "#{task}_dir_#{type}"
+ end
+ run_hook "post-#{task}"
+ end
+
+ def traverse(task, rel, mid)
+ dive_into(rel) {
+ run_hook "pre-#{task}"
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
+ all_dirs_in(curr_srcdir()).each do |d|
+ traverse task, "#{rel}/#{d}", mid
+ end
+ run_hook "post-#{task}"
+ }
+ end
+
+ def dive_into(rel)
+ return unless File.dir?("#{@srcdir}/#{rel}")
+
+ dir = File.basename(rel)
+ Dir.mkdir dir unless File.dir?(dir)
+ prevdir = Dir.pwd
+ Dir.chdir dir
+ $stderr.puts '---> ' + rel if verbose?
+ @currdir = rel
+ yield
+ Dir.chdir prevdir
+ $stderr.puts '<--- ' + rel if verbose?
+ @currdir = File.dirname(rel)
+ end
+
+end
+
+
+if $0 == __FILE__
+ begin
+ if multipackage_install?
+ ToplevelInstallerMulti.invoke
+ else
+ ToplevelInstaller.invoke
+ end
+ rescue SetupError
+ raise if $DEBUG
+ $stderr.puts $!.message
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
+ exit 1
+ end
+end
More information about the pkg-ruby-extras-maintainers
mailing list