# HG changeset patch # User Michael Granger # Date 1224124988 0 # Node ID 0c24586f579a68cc03c7eaa05cc4fd684214fac8 # Parent 09d0d209d06dd4a14740e3b765a3e6b034335a06 Checkpoint commit. diff -r 09d0d209d06d -r 0c24586f579a LICENSE --- a/LICENSE Fri Aug 15 16:23:03 2008 +0000 +++ b/LICENSE Thu Oct 16 02:43:08 2008 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2008, Michae Granger and Mahlon Smith +Copyright (c) 2008, Michael Granger and Mahlon Smith All rights reserved. Redistribution and use in source and binary forms, with or without diff -r 09d0d209d06d -r 0c24586f579a README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Thu Oct 16 02:43:08 2008 +0000 @@ -0,0 +1,19 @@ += jparallel + +jparallel is a "parallel jail shell" written in Ruby. + +This is shell that can be used to interact with multiple FreeBSD jail instances +simultaneously. It includes a Ruby binding to the FreeBSD jail(2) functions. + +In the meantime, you can check out the current development source with Subversion from the +following URL: + + svn://deveiate.org/jparallel/trunk + +The project page is also likely to have more details: + + http://deveiate.org/projects/Jparallel/ + +== License + +See the LICENSE file in the same directory for licensing details. diff -r 09d0d209d06d -r 0c24586f579a Rakefile --- a/Rakefile Fri Aug 15 16:23:03 2008 +0000 +++ b/Rakefile Thu Oct 16 02:43:08 2008 +0000 @@ -7,7 +7,7 @@ # Copyright (c) 2008 The FaerieMUD Consortium # # Authors: -# * Michae Granger and Mahlon Smith +# * Michael Granger and Mahlon Smith # BEGIN { @@ -21,9 +21,10 @@ $LOAD_PATH.unshift( extdir.to_s ) unless $LOAD_PATH.include?( extdir.to_s ) } +require 'rubygems' +gem 'rake', '>= 0.8.3' require 'rbconfig' -require 'rubygems' require 'rake' require 'rake/rdoctask' require 'rake/testtask' @@ -34,26 +35,33 @@ ### Config constants BASEDIR = Pathname.new( __FILE__ ).dirname.relative_path_from( Pathname.getwd ) +BINDIR = BASEDIR + 'bin' LIBDIR = BASEDIR + 'lib' EXTDIR = BASEDIR + 'ext' DOCSDIR = BASEDIR + 'docs' PKGDIR = BASEDIR + 'pkg' +DATADIR = BASEDIR + 'data' -PKG_NAME = 'jparallel' +PROJECT_NAME = 'jparallel' +PKG_NAME = PROJECT_NAME.downcase PKG_SUMMARY = 'A "parallel jail shell" written in Ruby' VERSION_FILE = LIBDIR + 'jparallel.rb' -PKG_VERSION = VERSION_FILE.read[ /VERSION = '(\d+\.\d+\.\d+)'/, 1 ] +PKG_VERSION = VERSION_FILE.read[ /VERSION\s*=\s*'(\d+\.\d+\.\d+)'/, 1 ] PKG_FILE_NAME = "#{PKG_NAME.downcase}-#{PKG_VERSION}" GEM_FILE_NAME = "#{PKG_FILE_NAME}.gem" ARTIFACTS_DIR = Pathname.new( ENV['CC_BUILD_ARTIFACTS'] || 'artifacts' ) TEXT_FILES = %w( Rakefile ChangeLog README LICENSE ).collect {|filename| BASEDIR + filename } +BIN_FILES = Pathname.glob( BINDIR + '*' ).delete_if {|item| item =~ /\.svn/ } LIB_FILES = Pathname.glob( LIBDIR + '**/*.rb' ).delete_if {|item| item =~ /\.svn/ } EXT_FILES = Pathname.glob( EXTDIR + '**/*.{c,h,rb}' ).delete_if {|item| item =~ /\.svn/ } +DATA_FILES = Pathname.glob( DATADIR + '**/*' ).delete_if {|item| item =~ /\.svn/ } SPECDIR = BASEDIR + 'spec' -SPEC_FILES = Pathname.glob( SPECDIR + '**/*_spec.rb' ).delete_if {|item| item =~ /\.svn/ } +SPECLIBDIR = SPECDIR + 'lib' +SPEC_FILES = Pathname.glob( SPECDIR + '**/*_spec.rb' ).delete_if {|item| item =~ /\.svn/ } + + Pathname.glob( SPECLIBDIR + '**/*.rb' ).delete_if {|item| item =~ /\.svn/ } TESTDIR = BASEDIR + 'tests' TEST_FILES = Pathname.glob( TESTDIR + '**/*.tests.rb' ).delete_if {|item| item =~ /\.svn/ } @@ -64,13 +72,15 @@ LOCAL_RAKEFILE = BASEDIR + 'Rakefile.local' EXTRA_PKGFILES = [] -EXTRA_PKGFILES += Pathname.glob( BASEDIR + 'examples/*.{c,rb}' ).delete_if {|item| item =~ /\.svn/ } +EXTRA_PKGFILES.concat Pathname.glob( BASEDIR + 'examples/*.{c,rb}' ).delete_if {|item| item =~ /\.svn/ } RELEASE_FILES = TEXT_FILES + SPEC_FILES + TEST_FILES + + BIN_FILES + LIB_FILES + EXT_FILES + + DATA_FILES + RAKE_TASKLIBS + EXTRA_PKGFILES @@ -108,6 +118,7 @@ SNAPSHOT_GEM_NAME = "#{SNAPSHOT_PKG_NAME}.gem" # Documentation constants +RDOCDIR = DOCSDIR + 'api' RDOC_OPTIONS = [ '-w', '4', '-SHN', @@ -124,7 +135,8 @@ PROJECT_HOST = 'deveiate.org' PROJECT_PUBDIR = "/usr/local/www/public/code" PROJECT_DOCDIR = "#{PROJECT_PUBDIR}/#{PKG_NAME}" -PROJECT_SCPURL = "#{PROJECT_HOST}:#{PROJECT_DOCDIR}" +PROJECT_SCPPUBURL = "#{PROJECT_HOST}:#{PROJECT_PUBDIR}" +PROJECT_SCPDOCURL = "#{PROJECT_HOST}:#{PROJECT_DOCDIR}" # Rubyforge stuff RUBYFORGE_GROUP = 'deveiate' @@ -134,9 +146,25 @@ DEPENDENCIES = { } +# Developer Gem dependencies: gemname => version +DEVELOPMENT_DEPENDENCIES = { + 'amatch' => '>= 0.2.3', + 'rake' => '>= 0.8.1', + 'rcodetools' => '>= 0.7.0.0', + 'rcov' => '>= 0', + 'RedCloth' => '>= 4.0.3', + 'rspec' => '>= 0', + 'rubyforge' => '>= 0', + 'termios' => '>= 0', + 'text-format' => '>= 1.0.0', + 'tmail' => '>= 1.2.3.1', + 'ultraviolet' => '>= 0.10.2', + 'libxml-ruby' => '>= 0.8.3', +} + # Non-gem requirements: packagename => version REQUIREMENTS = { - 'FreeBSD' => '>= 7.0', + 'FreeBSD' => '>= 5.0', } # RubyGem specification @@ -147,11 +175,10 @@ gem.summary = PKG_SUMMARY gem.description = <<-EOD This is shell that can be used to interact with multiple FreeBSD jail instances - simultaneously. It includes a Ruby binding to the FreeBSD jail(2) functions. EOD - gem.authors = 'Michae Granger and Mahlon Smith' + gem.authors = 'Michael Granger and Mahlon Smith' gem.email = 'ged@FaerieMUD.org, mahlon@martini.nu' gem.homepage = 'http://deveiate.org/projects/Jparallel/' gem.rubyforge_project = RUBYFORGE_PROJECT @@ -159,6 +186,9 @@ gem.has_rdoc = true gem.rdoc_options = RDOC_OPTIONS + gem.bindir = BINDIR.relative_path_from(BASEDIR).to_s + + gem.files = RELEASE_FILES. collect {|f| f.relative_path_from(BASEDIR).to_s } gem.test_files = SPEC_FILES. @@ -166,7 +196,15 @@ DEPENDENCIES.each do |name, version| version = '>= 0' if version.length.zero? - gem.add_dependency( name, version ) + gem.add_runtime_dependency( name, version ) + end + + # Developmental dependencies don't work as of RubyGems 1.2.0 + unless Gem::Version.new( Gem::RubyGemsVersion ) <= Gem::Version.new( "1.2.0" ) + DEVELOPMENT_DEPENDENCIES.each do |name, version| + version = '>= 0' if version.length.zero? + gem.add_development_dependency( name, version ) + end end REQUIREMENTS.each do |name, version| @@ -174,6 +212,9 @@ end end +# Manual-generation config +MANUALDIR = DOCSDIR + 'manual' + $trace = Rake.application.options.trace ? true : false $dryrun = Rake.application.options.dryrun ? true : false @@ -203,7 +244,10 @@ ##################################################################### ### Default task -task :default => [:clean, :spec, :rdoc, :package] +task :default => [:clean, :local, :spec, :rdoc, :package] + +### Task the local Rakefile can append to -- no-op by default +task :local ### Task: clean @@ -226,13 +270,16 @@ ### Task: cruise (Cruisecontrol task) desc "Cruisecontrol build" -task :cruise => [:clean, :spec, :package] do |task| +task :cruise => [:clean, 'spec:quiet', :package] do |task| raise "Artifacts dir not set." if ARTIFACTS_DIR.to_s.empty? artifact_dir = ARTIFACTS_DIR.cleanpath artifact_dir.mkpath - $stderr.puts "Copying coverage stats..." - FileUtils.cp_r( 'coverage', artifact_dir ) + coverage = BASEDIR + 'coverage' + if coverage.exist? && coverage.directory? + $stderr.puts "Copying coverage stats..." + FileUtils.cp_r( 'coverage', artifact_dir ) + end $stderr.puts "Copying packages..." FileUtils.cp_r( FileList['pkg/*'].to_a, artifact_dir ) diff -r 09d0d209d06d -r 0c24586f579a examples/startjail.rb diff -r 09d0d209d06d -r 0c24586f579a ext/bsdjail.c --- a/ext/bsdjail.c Fri Aug 15 16:23:03 2008 +0000 +++ b/ext/bsdjail.c Thu Oct 16 02:43:08 2008 +0000 @@ -29,6 +29,32 @@ /* + * Debug logging function + */ +void +#ifdef HAVE_STDARG_PROTOTYPES +rlink_debug(const char *fmt, ...) +#else +rlink_debug( const char *fmt, va_dcl ) +#endif +{ + char buf[BUFSIZ], buf2[BUFSIZ]; + va_list args; + + if ( !RTEST(ruby_debug) ) return; + + snprintf( buf, BUFSIZ, "Jail Debug>>> %s", fmt ); + + va_init_list( args, fmt ); + vsnprintf( buf2, BUFSIZ, buf, args ); + fputs( buf2, stderr ); + fputs( "\n", stderr ); + fflush( stderr ); + va_end( args ); +} + + +/* struct jail { u_int32_t version; char *path; @@ -41,8 +67,7 @@ * Allocation function */ static jail * -rbjail_jail_alloc() -{ +rbjail_jail_alloc() { jail *ptr = ALLOC( jail ); ptr->version = 0; @@ -59,17 +84,19 @@ * GC Free function */ static void -rbjail_jail_gc_free( ptr ) - jail *ptr; -{ +rbjail_gc_free( jail *ptr ) { if ( ptr ) { + if ( ptr->path ) xfree( ptr->path ); + if ( ptr->hostname ) xfree( ptr->hostname ); + ptr->path = NULL; ptr->hostname = NULL; + xfree( ptr ); } else { - debugMsg(( "Not freeing an uninitialized rlink_SENTENCE" )); + debugMsg(( "Not freeing an uninitialized jail" )); } } @@ -77,15 +104,13 @@ /* * Object validity checker. Returns the data pointer. */ -static rlink_SENTENCE * -check_sentence( self ) - VALUE self; -{ - debugMsg(( "Checking a LinkParser::Sentence object (%d).", self )); +static jail * +rbjail_check_jail( VALUE self ) { + debugMsg(( "Checking a BSD::Jail object (%d).", self )); Check_Type( self, T_DATA ); - if ( !IsSentence(self) ) { - rb_raise( rb_eTypeError, "wrong argument type %s (expected LinkParser::Sentence)", + if ( !rb_obj_is_kind_of(self, rbjail_cBSDJail) ) { + rb_raise( rb_eTypeError, "wrong argument type %s (expected BSD::Jail)", rb_class2name(CLASS_OF( self )) ); } @@ -96,13 +121,11 @@ /* * Fetch the data pointer and check it for sanity. */ -static rlink_SENTENCE * -get_sentence( self ) - VALUE self; -{ - rlink_SENTENCE *ptr = check_sentence( self ); +static jail * +rbjail_get_jail( VALUE self ) { + jail *ptr = check_sentence( self ); - debugMsg(( "Fetching a Sentence (%p).", ptr )); + debugMsg(( "Fetching a Jail (%p).", ptr )); if ( !ptr ) rb_raise( rb_eRuntimeError, "uninitialized Sentence" ); @@ -110,21 +133,13 @@ } +/* -------------------------------------------------------------- + * Jail utility functions + * -------------------------------------------------------------- */ + /* - * Publicly-usable sentence-fetcher + * Try to jail_attach() to the specified +jid+, raising an exception if it fails. */ -rlink_SENTENCE * -rlink_get_sentence( self ) - VALUE self; -{ - return get_sentence( self ); -} - - - - - - static void rbjail_do_jail_attach( int jid ) { @@ -132,7 +147,10 @@ rb_sys_fail( "jail_attach" ); } -/* Mostly ripped off from Ruby's process.c */ + +/* + * Fork + Block function for rbjail_attach(). Mostly stolen from Ruby's process.c. + */ static VALUE rbjail_attach_block( int jid ) { @@ -140,8 +158,8 @@ rb_secure(2); - fflush(stdout); - fflush(stderr); + fflush( stdout ); + fflush( stderr ); switch ( pid = fork() ) { case 0: @@ -164,9 +182,132 @@ } } + +/* -------------------------------------------------------------- + * Class methods + * -------------------------------------------------------------- */ + +/* + * call-seq: + * BSD::Jail.allocate -> bsdjail + * + * Allocate a new BSD::Jail object. + * + */ static VALUE -rbjail_attach( int argc, VALUE *argv, VALUE self ) -{ +rbjail_jail_s_allocate( VALUE klass ) { + return Data_Wrap_Struct( klass, 0, rbjail_gc_free, 0 ); +} + + +/* + * call-seq: + * BSD::Jail.list -> array + * + * Return an Array of all the running jails on the host. + * + */ +static VALUE +rbjail_jail_s_list( VALUE klass ) { + VALUE rval = rb_ary_new(); + struct xprison *xp; + struct in_addr in; + size_t i, len; + + if ( sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1 ) + rb_sys_fail( "sysctlbyname(): jail.list" ); + + xp = ALLOCA_N( xprison, 1 ); + + if ( sysctlbyname("jail.list", xp, &len, NULL, 0) == -1 ) { + rb_sys_fail( "sysctlbyname(): jail.list" ); + } + + if ( len < sizeof(*xp) || len % sizeof(*xp) || + xp->pr_version != KINFO_PRISON_VERSION ) + rb_fatal( "Kernel and userland out of sync" ); + + len /= sizeof( *xp ); + for ( i = 0; i < len; i++ ) { + VALUE jail, args[3]; + + /* Hostname */ + args[0] = rb_str_new2( xp->pr_host ); + + /* IP */ + in.s_addr = ntohl( xp->pr_ip ); + args[1] = rb_str_new2( inet_ntoa(in) ); + + /* Path */ + args[2] = rb_str_new2( xp->pr_path ); + + jail = rb_class_new_instance( 3, args, klass ); + rb_ary_push( rval, jail ); + + xp++; + } + + return rval; +} + + + + +/* -------------------------------------------------------------- + * Instance methods + * -------------------------------------------------------------- */ + +/* + * call-seq: + * BSD::Jail.new( hostname, ip, path ) -> new_jail + * + * Create a new jail for the given +hostname+, +ip+, and +path+. + */ +static VALUE +rbjail_jail_initialize( VALUE self, VALUE hostname, VALUE ip, VALUE path ) { + if ( !rbjail_check_jail(self) ) { + struct jail *ptr = rbjail_jail_alloc(); + char *pathstr = NULL, *hostnamestr = NULL; + + Check_Type( hostname, T_STRING ); + Check_Type( ip, T_STRING ); + + pathstr = ALLOC_N( char, RSTRING(path)->len ); + strncpy( pathstr, RSTRING(path)->ptr, RSTRING(path)->len ); + + hostnamestr = ALLOC_N( char, RSTRING(hostname)->len ); + strncpy( hostnamestr, RSTRING(hostname)->ptr, RSTRING(hostname)->len ); + + /* + struct jail { + u_int32_t version; + char *path; + char *hostname; + u_int32_t ip_number; + }; + */ + ptr->version = 0; /* Per the manpage's recommendation */ + ptr->ip_number = inet_addr( StringValuePtr(ip) ); + ptr->path = path; + ptr->hostname = hostname; + } +} + + +/* + * call-seq: + * jail.attach -> true or false + * jail.attach { block } -> pid + * + * Attach to the given jail. In the non-block form, attach the current process to the + * jail and return +true+ if it succeeds. This is a one-way operation, and requires root + * privileges. + * + * In the block form, the process will be forked, and the block will be attached to the jail and + * run by the child. The parent process will receive the process ID of the child. + */ +static VALUE +rbjail_attach( int argc, VALUE *argv, VALUE self ) { VALUE jidnum, rval; int jid; @@ -185,49 +326,27 @@ return rval; } -static VALUE - rbjail_list( VALUE self ) -{ - struct kinfo_prison *sxp, *xp; - struct in_addr in; - size_t i, len; - if (sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1) - rb_sys_fail("sysctlbyname(): jail.list"); - - xp = ALLOCA_N( kinfo_prison, 1 ); - - if (sysctlbyname("jail.list", xp, &len, NULL, 0) == -1) { - rb_sys_fail("sysctlbyname(): jail.list"); - } - - if (len < sizeof(*xp) || len % sizeof(*xp) || - xp->pr_version != KINFO_PRISON_VERSION) - rb_fatal("Kernel and userland out of sync"); - - len /= sizeof(*xp); - printf(" JID IP Address Hostname Path\n"); - for (i = 0; i < len; i++) { - in.s_addr = ntohl(xp->pr_ip); - printf("%6d %-15.15s %-29.29s %.74s\n", - xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path); - xp++; - } - free(sxp); - exit(0); - -} - +/* + * I can't remember how the hell you document a class, but that will go here. + */ void -Init_bsdjail( void ) -{ +Init_bsdjail( void ) { rbjail_mBSD = rb_define_module( "BSD" ); rbjail_cBSDJail = rb_define_class_under( rbjail_mBSD, "Jail" ); - rb_define_singleton_method( rbjail_cBSDJail, "list", rbjail_list, 0 ); - rb_define_alloc_function( rbjail_cBSDJail, ) + /* Class methods */ + rb_define_alloc_function( rbjail_cBSDJail, rbjail_jail_s_allocate ); + rb_define_singleton_method( rbjail_cBSDJail, "jail", rbjail_jail_s_jail, 0 ); + rb_define_singleton_method( rbjail_cBSDJail, "list", rbjail_jail_s_list, 0 ); - rb_define_method( rbjail_cBSDJail, "attach", rbjail_attach, -1 ); + /* Instance methods */ + rb_define_method( rbjail_cBSDJail, "initialize", rbjail_jail_initialize, 3 ); + rb_define_method( rbjail_cBSDJail, "attach", rbjail_jail_attach, -1 ); + rb_define_method( rbjail_cBSDJail, "hostname", rbjail_jail_hostname, 0 ); + rb_define_method( rbjail_cBSDJail, "path", rbjail_jail_path, 0 ); + rb_define_method( rbjail_cBSDJail, "ip", rbjail_jail_ip, 0 ); + rb_define_method( rbjail_cBSDJail, "jid", rbjail_jail_jid, 0 ); } diff -r 09d0d209d06d -r 0c24586f579a ext/bsdjail.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/bsdjail.h Thu Oct 16 02:43:08 2008 +0000 @@ -0,0 +1,31 @@ + + +#include +#include + +#include +#include /* For rb_dbl2big() */ + +#include + + + +/* Debugging functions/macros */ +#ifdef HAVE_STDARG_PROTOTYPES +#include +#define va_init_list(a,b) va_start(a,b) +extern void rbjail_debug(const char *fmt, ...); +#else +#include +#define va_init_list(a,b) va_start(a) +extern void rbjail_debug(fmt, va_alist); +#endif + + +/* Debugging macro */ +#if DEBUG +# define debugMsg(f) rbjail_debug f +#else /* ! DEBUG */ +# define debugMsg(f) +#endif /* DEBUG */ + diff -r 09d0d209d06d -r 0c24586f579a misc/monkeypatches.rb --- a/misc/monkeypatches.rb Fri Aug 15 16:23:03 2008 +0000 +++ b/misc/monkeypatches.rb Thu Oct 16 02:43:08 2008 +0000 @@ -42,12 +42,14 @@ task :default => EXT rule '.#{objext}' => '.#{@source_extension}' do |t| - sh "\#{CC} \#{CFLAGS} \#{INCLUDES} -c \#{t.source}" + $stderr.puts " building \#{t.name} from \#{t.source}" + sh "\#{CC} \#{CFLAGS} \#{INCLUDES} -c \#{t.source}" end desc "Build this extension" file EXT => OBJ do - sh "\#{LDSHARED} \#{LIBPATH} #{@available.ld_outfile(@extension_name)} \#{OBJ} \#{ADDITIONAL_OBJECTS} \#{LIBS} \#{LIBRUBYARG_SHARED}" + $stderr.puts " linking \#{OBJ.join(', ')} into \#{EXT}" + sh "\#{LDSHARED} \#{LIBPATH} #{@available.ld_outfile(@extension_name)} \#{OBJ} \#{ADDITIONAL_OBJECTS} \#{LIBS} \#{LIBRUBYARG_SHARED}" end @@ -55,7 +57,7 @@ desc "Install this extension" task :install => [EXT, RUBYARCHDIR] do - install EXT, RUBYARCHDIR, :verbose => true + install EXT, RUBYARCHDIR, :verbose => true end #{additional_code} @@ -66,7 +68,83 @@ module Mkrf class Availability - # No-op the stupid squashing of output + + # Create a new Availability instance. + # + # Valid keys for the options hash include: + # * :loaded_libs -- libraries to load by default + # * :library_paths -- libraries paths to include by default + # * :headers -- headers to load by default + # * :compiler -- which compiler to use when determining availability + # * :includes -- directories that should be searched for include files + def initialize(options = {}) + @loaded_libs = options[:loaded_libs] || [] + @loaded_libs.flatten! + + @library_paths = [(options[:library_paths] || [])].flatten + # Not sure what COMMON_HEADERS looks like when populated + @headers = options[:headers] || [] # Config::CONFIG["COMMON_HEADERS"] + @compiler = options[:compiler] || Config::CONFIG["CC"] + @includes = [(options[:includes] || DEFAULT_INCLUDES)].flatten + @logger = Logger.new('mkrf.log') + @defines = [] + end + + + def can_link?( function_body ) + silence_command_line do + create_source(function_body) + cmd = link_command() + @logger.debug "Running link command: #{cmd}" + system( cmd ) + end + ensure + FileUtils.rm_f TEMP_SOURCE_FILE + FileUtils.rm_f TEMP_EXECUTABLE + end + + + # Add the LIBRUBYARG_SHARED setting to the library paths for non-windows boxen. This is + # necessary if Ruby is installed in a directory that isn't in the default library + # search path (e.g., on FreeBSD where Ruby is /usr/local/bin/ruby). + def library_paths_compile_string + if RUBY_PLATFORM =~ /mswin/ + @library_paths.collect {|l| "/libpath:#{l}"}.join(' ') + else + Config::CONFIG['LIBRUBYARG_SHARED'] + @library_paths.collect {|l| "-L#{l}"}.join(' ') + end + end + + + # Separate includes with a newline instead of a literal '\n' + def header_include_string + @headers.collect {|header| "#include <#{header}>"}.join( "\n" ) + end + + + # Log the created source to the logfile + def create_source( src ) + @logger.debug "Creating source file:\n#{src}" + File.open( TEMP_SOURCE_FILE, "w+" ) do |f| + f.write( src ) + end + end + + # Prepend the LIBS string directly to the @loaded_libs, as not all arguments in + # it + def library_compile_string + added_libs = nil + if RUBY_PLATFORM =~ /mswin/ + added_libs = @loaded_libs.join(' ') + else + added_libs = @loaded_libs.collect {|l| "-l#{l}"}.join(' ') + end + + return Config::CONFIG["LIBS"] + ' ' + added_libs + end + + + # Redirect to the mkrf log instead of /dev/null def silence_stream( stream ) old_stream = stream.dup stream.reopen( @logger.instance_variable_get(:@logdev).dev ) diff -r 09d0d209d06d -r 0c24586f579a project.yml --- a/project.yml Fri Aug 15 16:23:03 2008 +0000 +++ b/project.yml Thu Oct 16 02:43:08 2008 +0000 @@ -12,6 +12,9 @@ project_summary: A "parallel jail shell" written in Ruby project_name: jparallel +version_file: "jparallel.rb" additional_pkgfiles: - examples/*.{c,rb} +dev_dependencies: {} + author_email: ged@FaerieMUD.org, mahlon@martini.nu