Checkpoint commit.
--- 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
--- /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.
--- 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 <ged@FaerieMUD.org, mahlon@martini.nu>
+# * Michael Granger and Mahlon Smith <ged@FaerieMUD.org, mahlon@martini.nu>
#
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 )
--- 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 );
}
--- /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 <stdlib.h>
+#include <stdio.h>
+
+#include <ruby.h>
+#include <intern.h> /* For rb_dbl2big() */
+
+#include <link-grammar/link-includes.h>
+
+
+
+/* Debugging functions/macros */
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+extern void rbjail_debug(const char *fmt, ...);
+#else
+#include <varargs.h>
+#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 */
+
--- 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:
+ # * <tt>:loaded_libs</tt> -- libraries to load by default
+ # * <tt>:library_paths</tt> -- libraries paths to include by default
+ # * <tt>:headers</tt> -- headers to load by default
+ # * <tt>:compiler</tt> -- which compiler to use when determining availability
+ # * <tt>:includes</tt> -- 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 )
--- 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