[Jifty-commit] r5712 - in B-Utils: . inc lib/B t

Jifty commits jifty-commit at lists.jifty.org
Wed Aug 13 09:20:53 EDT 2008


Author: clkao
Date: Wed Aug 13 09:20:53 2008
New Revision: 5712

Added:
   B-Utils/BUtils.h
   B-Utils/Utils.xs
   B-Utils/inc/
   B-Utils/inc/ExtUtils/
   B-Utils/inc/ExtUtils/Depends.pm
Removed:
   B-Utils/t/03yaml.t
Modified:
   B-Utils/MANIFEST
   B-Utils/Makefile.PL
   B-Utils/lib/B/Utils.pm

Log:
* Bundle ExtUtils::Depends
* Use ExtUtils::Depends to export BUtils.h 
* META.yml can be dist-only


Added: B-Utils/BUtils.h
==============================================================================
--- (empty file)
+++ B-Utils/BUtils.h	Wed Aug 13 09:20:53 2008
@@ -0,0 +1,11 @@
+#ifndef _BUTILS_H_
+#define _BUTILS_H_
+
+extern char *BUtils_cc_opclassname(pTHX_ const OP *o);
+extern SV *BUtils_make_sv_object(pTHX_ SV *arg, SV *sv);
+
+extern I32 BUtils_op_name_to_num(SV * name);
+
+
+
+#endif

Modified: B-Utils/MANIFEST
==============================================================================
--- B-Utils/MANIFEST	(original)
+++ B-Utils/MANIFEST	Wed Aug 13 09:20:53 2008
@@ -27,4 +27,3 @@
 t/44optrep.t
 t/50carp.t
 t/51croak.t
-META.yml                                 Module meta-data (added by MakeMaker)

Modified: B-Utils/Makefile.PL
==============================================================================
--- B-Utils/Makefile.PL	(original)
+++ B-Utils/Makefile.PL	Wed Aug 13 09:20:53 2008
@@ -1,4 +1,13 @@
+use lib 'inc';
+require ExtUtils::Depends;
+
+my $butils = ExtUtils::Depends->new('B::Utils');
+
+$butils->install('BUtils.h');
+
+$butils->save_config('build/IFiles.pm');
 use ExtUtils::MakeMaker;
+
 WriteMakefile(
     NAME          => 'B::Utils',
     VERSION_FROM  => 'lib/B/Utils.pm',
@@ -6,4 +15,5 @@
     ABSTRACT_FROM => 'lib/B/Utils.pm',
     AUTHOR        => 'Joshua b. Jore <jjore at cpan.org>',
     LICENSE => 'perl',
+#    $butils->get_makefile_vars,
 );

Added: B-Utils/Utils.xs
==============================================================================
--- (empty file)
+++ B-Utils/Utils.xs	Wed Aug 13 09:20:53 2008
@@ -0,0 +1,326 @@
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "BUtils.h"
+
+/* After 5.10, the CxLVAL macro was added. */
+#ifndef CxLVAL
+#  define CxLVAL(cx) cx->blk_sub.lval
+#endif
+
+#define MY_CXT_KEY "B::Utils::_guts" XS_VERSION
+
+typedef struct {
+    int		x_walkoptree_debug;	/* Flag for walkoptree debug hook */
+    SV *	x_specialsv_list[7];
+} my_cxt_t;
+
+START_MY_CXT
+
+/* Stolen from B.xs */
+
+/* XXX: this really need to properly exported by the B module,
+  possibly with custom .h retrieved by some extutil module for
+  building, and we shall be able to simply reuse the public symbol
+  from loaded module in run time. */
+
+#ifdef PERL_OBJECT
+#undef PL_op_name
+#undef PL_opargs 
+#undef PL_op_desc
+#define PL_op_name (get_op_names())
+#define PL_opargs (get_opargs())
+#define PL_op_desc (get_op_descs())
+#endif
+
+/* duplicated from B.xs */
+static char *svclassnames[] = {
+    "B::NULL",
+    "B::IV",
+    "B::NV",
+    "B::RV",
+    "B::PV",
+    "B::PVIV",
+    "B::PVNV",
+    "B::PVMG",
+    "B::BM",
+#if PERL_VERSION >= 9
+    "B::GV",
+#endif
+    "B::PVLV",
+    "B::AV",
+    "B::HV",
+    "B::CV",
+#if PERL_VERSION <= 8
+    "B::GV",
+#endif
+    "B::FM",
+    "B::IO",
+};
+
+typedef enum {
+    OPc_NULL,	/* 0 */
+    OPc_BASEOP,	/* 1 */
+    OPc_UNOP,	/* 2 */
+    OPc_BINOP,	/* 3 */
+    OPc_LOGOP,	/* 4 */
+    OPc_LISTOP,	/* 5 */
+    OPc_PMOP,	/* 6 */
+    OPc_SVOP,	/* 7 */
+    OPc_PADOP,	/* 8 */
+    OPc_PVOP,	/* 9 */
+    OPc_LOOP,	/* 10 */
+    OPc_COP	/* 11 */
+} opclass;
+
+static char *opclassnames[] = {
+    "B::NULL",
+    "B::OP",
+    "B::UNOP",
+    "B::BINOP",
+    "B::LOGOP",
+    "B::LISTOP",
+    "B::PMOP",
+    "B::SVOP",
+    "B::PADOP",
+    "B::PVOP",
+    "B::LOOP",
+    "B::COP"	
+};
+
+static opclass
+cc_opclass(pTHX_ const OP *o)
+{
+    if (!o)
+	return OPc_NULL;
+
+    if (o->op_type == 0)
+	return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
+
+    if (o->op_type == OP_SASSIGN)
+	return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
+
+#ifdef USE_ITHREADS
+    if (o->op_type == OP_GV || o->op_type == OP_GVSV ||
+	o->op_type == OP_AELEMFAST || o->op_type == OP_RCATLINE)
+	return OPc_PADOP;
+#endif
+
+    switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {
+    case OA_BASEOP:
+	return OPc_BASEOP;
+
+    case OA_UNOP:
+	return OPc_UNOP;
+
+    case OA_BINOP:
+	return OPc_BINOP;
+
+    case OA_LOGOP:
+	return OPc_LOGOP;
+
+    case OA_LISTOP:
+	return OPc_LISTOP;
+
+    case OA_PMOP:
+	return OPc_PMOP;
+
+    case OA_SVOP:
+	return OPc_SVOP;
+
+    case OA_PADOP:
+	return OPc_PADOP;
+
+    case OA_PVOP_OR_SVOP:
+        /*
+         * Character translations (tr///) are usually a PVOP, keeping a 
+         * pointer to a table of shorts used to look up translations.
+         * Under utf8, however, a simple table isn't practical; instead,
+         * the OP is an SVOP, and the SV is a reference to a swash
+         * (i.e., an RV pointing to an HV).
+         */
+	return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))
+		? OPc_SVOP : OPc_PVOP;
+
+    case OA_LOOP:
+	return OPc_LOOP;
+
+    case OA_COP:
+	return OPc_COP;
+
+    case OA_BASEOP_OR_UNOP:
+	/*
+	 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
+	 * whether parens were seen. perly.y uses OPf_SPECIAL to
+	 * signal whether a BASEOP had empty parens or none.
+	 * Some other UNOPs are created later, though, so the best
+	 * test is OPf_KIDS, which is set in newUNOP.
+	 */
+	return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
+
+    case OA_FILESTATOP:
+	/*
+	 * The file stat OPs are created via UNI(OP_foo) in toke.c but use
+	 * the OPf_REF flag to distinguish between OP types instead of the
+	 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
+	 * return OPc_UNOP so that walkoptree can find our children. If
+	 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
+	 * (no argument to the operator) it's an OP; with OPf_REF set it's
+	 * an SVOP (and op_sv is the GV for the filehandle argument).
+	 */
+	return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
+#ifdef USE_ITHREADS
+		(o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);
+#else
+		(o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);
+#endif
+    case OA_LOOPEXOP:
+	/*
+	 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
+	 * label was omitted (in which case it's a BASEOP) or else a term was
+	 * seen. In this last case, all except goto are definitely PVOP but
+	 * goto is either a PVOP (with an ordinary constant label), an UNOP
+	 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
+	 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
+	 * get set.
+	 */
+	if (o->op_flags & OPf_STACKED)
+	    return OPc_UNOP;
+	else if (o->op_flags & OPf_SPECIAL)
+	    return OPc_BASEOP;
+	else
+	    return OPc_PVOP;
+    }
+    warn("can't determine class of operator %s, assuming BASEOP\n",
+	 PL_op_name[o->op_type]);
+    return OPc_BASEOP;
+}
+
+char *
+BUtils_cc_opclassname(pTHX_ const OP *o)
+{
+    return opclassnames[cc_opclass(aTHX_ o)];
+}
+
+I32
+BUtils_op_name_to_num(SV *name)
+{
+    dTHX;
+    char const *s;
+    char *wanted = SvPV_nolen(name);
+    int i =0;
+    int topop = OP_max;
+
+#ifdef PERL_CUSTOM_OPS
+    topop--;
+#endif
+
+    if (SvIOK(name) && SvIV(name) >= 0 && SvIV(name) < topop)
+        return SvIV(name);
+
+    for (s = PL_op_name[i]; s; s = PL_op_name[++i]) {
+        if (strEQ(s, wanted))
+            return i;
+    }
+#ifdef PERL_CUSTOM_OPS
+    if (PL_custom_op_names) {
+        HE* ent;
+        SV* value;
+        /* This is sort of a hv_exists, backwards */
+        (void)hv_iterinit(PL_custom_op_names);
+        while ((ent = hv_iternext(PL_custom_op_names))) {
+            if (strEQ(SvPV_nolen(hv_iterval(PL_custom_op_names,ent)),wanted))
+                return OP_CUSTOM;
+        }
+    }
+#endif
+
+    croak("No such op \"%s\"", SvPV_nolen(name));
+
+    return -1;
+}
+
+SV *
+BUtils_make_sv_object(pTHX_ SV *arg, SV *sv)
+{
+    char *type = 0;
+    IV iv;
+    dMY_CXT;
+
+    if (!type) {
+	type = svclassnames[SvTYPE(sv)];
+	iv = PTR2IV(sv);
+    }
+    sv_setiv(newSVrv(arg, type), iv);
+    return arg;
+}
+
+/* Stolen from pp_ctl.c (with modifications) */
+
+I32
+dopoptosub_at(pTHX_ PERL_CONTEXT *cxstk, I32 startingblock)
+{
+    dTHR;
+    I32 i;
+    PERL_CONTEXT *cx;
+    for (i = startingblock; i >= 0; i--) {
+        cx = &cxstk[i];
+        switch (CxTYPE(cx)) {
+        default:
+            continue;
+        /*case CXt_EVAL:*/
+        case CXt_SUB:
+        case CXt_FORMAT:
+            DEBUG_l( Perl_deb(aTHX_ "(Found sub #%ld)\n", (long)i));
+            return i;
+        }
+    }
+    return i;
+}
+
+I32
+dopoptosub(pTHX_ I32 startingblock)
+{
+    dTHR;
+    return dopoptosub_at(aTHX_ cxstack, startingblock);
+}
+
+PERL_CONTEXT*
+upcontext(pTHX_ I32 count)
+{
+    PERL_SI *top_si = PL_curstackinfo;
+    I32 cxix = dopoptosub(aTHX_ cxstack_ix);
+    PERL_CONTEXT *cx;
+    PERL_CONTEXT *ccstack = cxstack;
+    I32 dbcxix;
+
+    for (;;) {
+        /* we may be in a higher stacklevel, so dig down deeper */
+        while (cxix < 0 && top_si->si_type != PERLSI_MAIN) {
+            top_si = top_si->si_prev;
+            ccstack = top_si->si_cxstack;
+            cxix = dopoptosub_at(aTHX_ ccstack, top_si->si_cxix);
+        }
+        if (cxix < 0) {
+            return (PERL_CONTEXT *)0;
+        }
+        if (PL_DBsub && cxix >= 0 &&
+                ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))
+            count++;
+        if (!count--)
+            break;
+        cxix = dopoptosub_at(aTHX_ ccstack, cxix - 1);
+    }
+    cx = &ccstack[cxix];
+    if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
+        dbcxix = dopoptosub_at(aTHX_ ccstack, cxix - 1);
+        /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the
+           field below is defined for any cx. */
+        if (PL_DBsub && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) {
+            cx = &ccstack[dbcxix];
+        }
+    }
+    return cx;
+}
+
+MODULE = B::Utils           PACKAGE = B::Utils

Added: B-Utils/inc/ExtUtils/Depends.pm
==============================================================================
--- (empty file)
+++ B-Utils/inc/ExtUtils/Depends.pm	Wed Aug 13 09:20:53 2008
@@ -0,0 +1,549 @@
+#
+# $Header: /cvsroot/gtk2-perl/gtk2-perl-xs/ExtUtils-Depends/lib/ExtUtils/Depends.pm,v 1.18 2008/03/30 15:36:23 kaffeetisch Exp $
+#
+
+package ExtUtils::Depends;
+
+use strict;
+use warnings;
+use Carp;
+use File::Find;
+use File::Spec;
+use Data::Dumper;
+
+our $VERSION = '0.300';
+
+sub import {
+	my $class = shift;
+	return unless @_;
+        die "$class version $_[0] is required--this is only version $VERSION"
+		if $VERSION < $_[0];
+}
+
+sub new {
+	my ($class, $name, @deps) = @_;
+	my $self = bless {
+		name => $name,
+		deps => {},
+		inc => [],
+		libs => '',
+
+		pm => {},
+		typemaps => [],
+		xs => [],
+		c => [],
+	}, $class;
+
+	$self->add_deps (@deps);
+
+	# attempt to load these now, so we'll find out as soon as possible
+	# whether the dependencies are valid.  we'll load them again in
+	# get_makefile_vars to catch any added between now and then.
+	$self->load_deps;
+
+	return $self;
+}
+
+sub add_deps {
+	my $self = shift;
+	foreach my $d (@_) {
+		$self->{deps}{$d} = undef
+			unless $self->{deps}{$d};
+	}
+}
+
+sub get_deps {
+	my $self = shift;
+	$self->load_deps; # just in case
+
+	return %{$self->{deps}};
+}
+
+sub set_inc {
+	my $self = shift;
+	push @{ $self->{inc} }, @_;
+}
+
+sub set_libs {
+	my ($self, $newlibs) = @_;
+	$self->{libs} = $newlibs;
+}
+
+sub add_pm {
+	my ($self, %pm) = @_;
+	while (my ($key, $value) = each %pm) {
+		$self->{pm}{$key} = $value;
+	}
+}
+
+sub _listkey_add_list {
+	my ($self, $key, @list) = @_;
+	$self->{$key} = [] unless $self->{$key};
+	push @{ $self->{$key} }, @list;
+}
+
+sub add_xs       { shift->_listkey_add_list ('xs',       @_) }
+sub add_c        { shift->_listkey_add_list ('c',        @_) }
+sub add_typemaps {
+	my $self = shift;
+	$self->_listkey_add_list ('typemaps', @_);
+	$self->install (@_);
+}
+
+# no-op, only used for source back-compat
+sub add_headers { carp "add_headers() is a no-op" }
+
+####### PRIVATE
+sub basename { (File::Spec->splitdir ($_[0]))[-1] }
+# get the name in Makefile syntax.
+sub installed_filename {
+	my $self = shift;
+	return '$(INST_ARCHLIB)/$(FULLEXT)/Install/'.basename ($_[0]);
+}
+
+sub install {
+	# install things by adding them to the hash of pm files that gets
+	# passed through WriteMakefile's PM key.
+	my $self = shift;
+	foreach my $f (@_) {
+		$self->add_pm ($f, $self->installed_filename ($f));
+	}
+}
+
+sub save_config {
+	use Data::Dumper;
+	use IO::File;
+
+	my ($self, $filename) = @_;
+	my $file = IO::File->new (">".$filename)
+		or croak "can't open '$filename' for writing: $!\n";
+	print $file "package $self->{name}\::Install::Files;\n\n";
+	# for modern stuff
+	print $file "".Data::Dumper->Dump([{
+		inc => join (" ", @{ $self->{inc} }),
+		libs => $self->{libs},
+		typemaps => [ map { basename $_ } @{ $self->{typemaps} } ],
+		deps => [keys %{ $self->{deps} }],
+	}], ['self']);
+	# for ancient stuff
+	print $file "\n\n# this is for backwards compatiblity\n";
+	print $file "\@deps = \@{ \$self->{deps} };\n";
+	print $file "\@typemaps = \@{ \$self->{typemaps} };\n";
+	print $file "\$libs = \$self->{libs};\n";
+	print $file "\$inc = \$self->{inc};\n";
+	# this is riduculous, but old versions of ExtUtils::Depends take
+	# first $loadedmodule::CORE and then $INC{$file} --- the fallback
+	# includes the Filename.pm, which is not useful.  so we must add
+	# this crappy code.  we don't worry about portable pathnames,
+	# as the old code didn't either.
+	(my $mdir = $self->{name}) =~ s{::}{/}g;
+	print $file <<"EOT";
+
+	\$CORE = undef;
+	foreach (\@INC) {
+		if ( -f \$_ . "/$mdir/Install/Files.pm") {
+			\$CORE = \$_ . "/$mdir/Install/";
+			last;
+		}
+	}
+EOT
+
+	print $file "\n1;\n";
+
+	close $file;
+
+	# we need to ensure that the file we just created gets put into
+	# the install dir with everything else.
+	#$self->install ($filename);
+	$self->add_pm ($filename, $self->installed_filename ('Files.pm'));
+}
+
+sub load {
+	my $dep = shift;
+	my @pieces = split /::/, $dep;
+	my @suffix = qw/ Install Files /;
+	my $relpath = File::Spec->catfile (@pieces, @suffix) . '.pm';
+	my $depinstallfiles = join "::", @pieces, @suffix;
+	eval {
+		require $relpath 
+	} or die " *** Can't load dependency information for $dep:\n   $@\n";
+	#
+	#print Dumper(\%INC);
+
+	# effectively $instpath = dirname($INC{$relpath})
+	@pieces = File::Spec->splitdir ($INC{$relpath});
+	pop @pieces;
+	my $instpath = File::Spec->catdir (@pieces);
+	
+	no strict;
+
+	croak "No dependency information found for $dep"
+		unless $instpath;
+
+	if (not File::Spec->file_name_is_absolute ($instpath)) {
+		$instpath = File::Spec->rel2abs ($instpath);
+	}
+
+	my @typemaps = map {
+		File::Spec->rel2abs ($_, $instpath)
+	} @{"$depinstallfiles\::typemaps"};
+
+	{
+		instpath => $instpath,
+		typemaps => \@typemaps,
+		inc      => "-I$instpath ".${"$depinstallfiles\::inc"},
+		libs     => ${"$depinstallfiles\::libs"},
+		# this will not exist when loading files from old versions
+		# of ExtUtils::Depends.
+		(exists ${"$depinstallfiles\::"}{deps}
+		  ? (deps => \@{"$depinstallfiles\::deps"})
+		  : ()), 
+	}
+}
+
+sub load_deps {
+	my $self = shift;
+	my @load = grep { not $self->{deps}{$_} } keys %{ $self->{deps} };
+	foreach my $d (@load) {
+		my $dep = load ($d);
+		$self->{deps}{$d} = $dep;
+		if ($dep->{deps}) {
+			foreach my $childdep (@{ $dep->{deps} }) {
+				push @load, $childdep
+					unless
+						$self->{deps}{$childdep}
+					or
+						grep {$_ eq $childdep} @load;
+			}
+		}
+	}
+}
+
+sub uniquify {
+	my %seen;
+	# we use a seen hash, but also keep indices to preserve
+	# first-seen order.
+	my $i = 0;
+	foreach (@_) {
+		$seen{$_} = ++$i
+			unless exists $seen{$_};
+	}
+	#warn "stripped ".(@_ - (keys %seen))." redundant elements\n";
+	sort { $seen{$a} <=> $seen{$b} } keys %seen;
+}
+
+
+sub get_makefile_vars {
+	my $self = shift;
+
+	# collect and uniquify things from the dependencies.
+	# first, ensure they are completely loaded.
+	$self->load_deps;
+	
+	##my @defbits = map { split } @{ $self->{defines} };
+	my @incbits = map { split } @{ $self->{inc} };
+	my @libsbits = split /\s+/, $self->{libs};
+	my @typemaps = @{ $self->{typemaps} };
+	foreach my $d (keys %{ $self->{deps} }) {
+		my $dep = $self->{deps}{$d};
+		#push @defbits, @{ $dep->{defines} };
+		push @incbits, @{ $dep->{defines} } if $dep->{defines};
+		push @incbits, split /\s+/, $dep->{inc} if $dep->{inc};
+		push @libsbits, split /\s+/, $dep->{libs} if $dep->{libs};
+		push @typemaps, @{ $dep->{typemaps} } if $dep->{typemaps};
+	}
+
+	# we have a fair bit of work to do for the xs files...
+	my @clean = ();
+	my @OBJECT = ();
+	my %XS = ();
+	foreach my $xs (@{ $self->{xs} }) {
+		(my $c = $xs) =~ s/\.xs$/\.c/i;
+		(my $o = $xs) =~ s/\.xs$/\$(OBJ_EXT)/i;
+		$XS{$xs} = $c;
+		push @OBJECT, $o;
+		# according to the MakeMaker manpage, the C files listed in
+		# XS will be added automatically to the list of cleanfiles.
+		push @clean, $o;
+	}
+
+	# we may have C files, as well:
+	foreach my $c (@{ $self->{c} }) {
+		(my $o = $c) =~ s/\.c$/\$(OBJ_EXT)/i;
+		push @OBJECT, $o;
+		push @clean, $o;
+	}
+
+	my %vars = (
+		INC => join (' ', uniquify @incbits),
+		LIBS => join (' ', uniquify $self->find_extra_libs, @libsbits),
+		TYPEMAPS => [@typemaps],
+	);
+
+	# we don't want to provide these if there is no data in them;
+	# that way, the caller can still get default behavior out of
+	# MakeMaker when INC, LIBS and TYPEMAPS are all that are required.
+	$vars{PM} = $self->{pm}
+		if %{ $self->{pm} };
+	$vars{clean} = { FILES => join (" ", @clean), }
+		if @clean;
+	$vars{OBJECT} = join (" ", @OBJECT)
+		if @OBJECT;
+	$vars{XS} = \%XS
+		if %XS;
+
+	%vars;
+}
+
+sub find_extra_libs {
+	my $self = shift;
+
+	my %mappers = (
+		MSWin32 => sub { $_[0] . '.lib' },
+		cygwin  => sub { 'lib' . $_[0] . '.dll.a'},
+	);
+	my $mapper = $mappers{$^O};
+	return () unless defined $mapper;
+
+	my @found_libs = ();
+	foreach my $name (keys %{ $self->{deps} }) {
+		(my $stem = $name) =~ s/^.*:://;
+		my $lib = $mapper->($stem);
+		my $pattern = qr/$lib$/;
+
+		my $matching_file;
+		find (sub {
+			if ((not $matching_file) && /$pattern/) {;
+				$matching_file = $File::Find::name;
+			}
+		}, map { -d $_ ? ($_) : () } @INC); # only extant dirs
+
+		if ($matching_file && -f $matching_file) {
+			push @found_libs, $matching_file;
+			next;
+		}
+	}
+
+	return @found_libs;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Depends - Easily build XS extensions that depend on XS extensions
+
+=head1 SYNOPSIS
+
+	use ExtUtils::Depends;
+	$package = new ExtUtils::Depends ('pkg::name', 'base::package')
+	# set the flags and libraries to compile and link the module
+	$package->set_inc("-I/opt/blahblah");
+	$package->set_libs("-lmylib");
+	# add a .c and an .xs file to compile
+	$package->add_c('code.c');
+	$package->add_xs('module-code.xs');
+	# add the typemaps to use
+	$package->add_typemaps("typemap");
+	# install some extra data files and headers
+	$package->install (qw/foo.h data.txt/);
+	# save the info
+	$package->save_config('Files.pm');
+
+	WriteMakefile(
+		'NAME' => 'Mymodule',
+		$package->get_makefile_vars()
+	);
+
+=head1 DESCRIPTION
+
+This module tries to make it easy to build Perl extensions that use
+functions and typemaps provided by other perl extensions. This means
+that a perl extension is treated like a shared library that provides
+also a C and an XS interface besides the perl one.
+
+This works as long as the base extension is loaded with the RTLD_GLOBAL
+flag (usually done with a 
+
+	sub dl_load_flags {0x01}
+
+in the main .pm file) if you need to use functions defined in the module.
+
+The basic scheme of operation is to collect information about a module
+in the instance, and then store that data in the Perl library where it
+may be retrieved later.  The object can also reformat this information
+into the data structures required by ExtUtils::MakeMaker's WriteMakefile
+function.
+
+When creating a new Depends object, you give it a name, which is the name
+of the module you are building.   You can also specify the names of modules
+on which this module depends.  These dependencies will be loaded
+automatically, and their typemaps, header files, etc merged with your new
+object's stuff.  When you store the data for your object, the list of
+dependencies are stored with it, so that another module depending on your
+needn't know on exactly which modules yours depends.
+
+For example:
+
+  Gtk2 depends on Glib
+
+  Gnome2::Canvas depends on Gtk2
+
+  ExtUtils::Depends->new ('Gnome2::Canvas', 'Gtk2');
+     this command automatically brings in all the stuff needed
+     for Glib, since Gtk2 depends on it.
+
+
+=head1 METHODS
+
+=over
+
+=item $object = ExtUtils::Depends->new($name, @deps)
+
+Create a new depends object named I<$name>.  Any modules listed in I<@deps>
+(which may be empty) are added as dependencies and their dependency
+information is loaded.  An exception is raised if any dependency information
+cannot be loaded.
+
+=item $depends->add_deps (@deps)
+
+Add modules listed in I<@deps> as dependencies.
+
+=item (hashes) = $depends->get_deps
+
+Fetch information on the dependencies of I<$depends> as a hash of hashes,
+which are dependency information indexed by module name.  See C<load>.
+
+=item $depends->set_inc (@newinc)
+
+Add strings to the includes or cflags variables.
+
+=item $depends->set_libs (@newlibs)
+
+Add strings to the libs (linker flags) variable.
+
+=item $depends->add_pm (%pm_files)
+
+Add files to the hash to be passed through ExtUtils::WriteMakefile's
+PM key.
+
+=item $depends->add_xs (@xs_files)
+
+Add xs files to be compiled.
+
+=item $depends->add_c (@c_files)
+
+Add C files to be compiled.
+
+=item $depends->add_typemaps (@typemaps)
+
+Add typemap files to be used and installed.
+
+=item $depends->add_headers (list)
+
+No-op, for backward compatibility.
+
+=item $depends->install (@files)
+
+Install I<@files> to the data directory for I<$depends>.
+
+This actually works by adding them to the hash of pm files that gets
+passed through WriteMakefile's PM key.
+
+=item $depends->save_config ($filename)
+
+Save the important information from I<$depends> to I<$filename>, and
+set it up to be installed as I<name>::Install::Files.
+
+Note: the actual value of I<$filename> seems to be irrelevant, but its
+usage is kept for backward compatibility.
+
+=item hash = $depends->get_makefile_vars
+
+Return the information in I<$depends> in a format digestible by
+WriteMakefile.
+
+This sets at least the following keys:
+
+	INC
+	LIBS
+	TYPEMAPS
+	PM
+
+And these if there is data to fill them:
+
+	clean
+	OBJECT
+	XS
+
+=item hashref = ExtUtils::Depends::load (name)
+
+Load and return dependency information for I<name>.  Croaks if no such
+information can be found.  The information is returned as an anonymous
+hash containing these keys:
+
+=over
+
+=item instpath
+
+The absolute path to the data install directory for this module.
+
+=item typemaps
+
+List of absolute pathnames for this module's typemap files.
+
+=item inc
+
+CFLAGS string for this module.
+
+=item libs
+
+LIBS string for this module.
+
+=item deps
+
+List of modules on which this one depends.  This key will not exist when
+loading files created by old versions of ExtUtils::Depends.
+
+=back
+
+=item $depends->load_deps
+
+Load I<$depends> dependencies, by calling C<load> on each dependency module.
+This is usually done for you, and should only be needed if you want to call
+C<get_deps> after calling C<add_deps> manually.
+
+=back
+
+
+=head1 BUGS
+
+Version 0.2 discards some of the more esoteric features provided by the
+older versions.  As they were completely undocumented, and this module
+has yet to reach 1.0, this may not exactly be a bug.
+
+This module is tightly coupled to the ExtUtils::MakeMaker architecture.
+
+=head1 SEE ALSO
+
+ExtUtils::MakeMaker.
+
+=head1 AUTHOR
+
+Paolo Molaro <lupus at debian dot org> wrote the original version for
+Gtk-Perl.  muppet <scott at asofyet dot org> rewrote the innards for
+version 0.2, borrowing liberally from Paolo's code.
+
+=head1 MAINTAINER
+
+The Gtk2 project, http://gtk2-perl.sf.net/
+
+=head1 LICENSE
+
+This library is free software; you may redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+

Modified: B-Utils/lib/B/Utils.pm
==============================================================================
--- B-Utils/lib/B/Utils.pm	(original)
+++ B-Utils/lib/B/Utils.pm	Wed Aug 13 09:20:53 2008
@@ -29,7 +29,10 @@
 
 =cut
 
-$VERSION = '0.05_09';
+$VERSION = '0.06';
+
+use base 'DynaLoader';
+bootstrap B::Utils $VERSION;
 
 =head1 SYNOPSIS
 


More information about the Jifty-commit mailing list