@@ -1,75 +0,0 @@
-########################################################################
-# housekeeping
-########################################################################
-
-use strict;
-use Module::Build;
-
-########################################################################
-# figure out which versin of libs.pm to install based on the
-# current running version.
-########################################################################
-
-my $path
-= do
-{
- my $type
- = ref $^V
- ? 'curr'
- : '5_8'
- ;
-
- "lib/FindBin/libs_$type.pm"
-};
-
-my @build_argz =
-(
- qw
- (
- module_name FindBin::libs
- license perl
- dist_version 1.8
- ),
-
- pm_files =>
- {
- $path => 'lib/FindBin/libs.pm'
- },
-
- dist_author => 'Steven Lembark <lembark@wrkhors.com',
-
- requires =>
- {
- qw
- (
- strict 0
-
- Carp 0
- Cwd 0
- FindBin 0
- Symbol 0
- File::Spec 0
- File::Temp 0
- List::Util 0
- Test::More 0
-
- )
- },
-
- configure_requires =>
- {
- 'Module::Build' => $Module::Build::VERSION,
- },
-
- dist_abstract => <<END
-FindBin::libs - locate and a 'use lib' or export
-directories based on $FindBin::Bin.
-END
-
-);
-
-Module::Build
-->new( @build_argz )
-->create_build_script;
-
-__END__
@@ -1,338 +0,0 @@
-
-1.8 Tue May 28 21:04:30 CDT 2013
-
-Update to work with v5.18
-
-1.7 Thu Mar 14 15:23:30 GMT 2013
-
-Up version to 1.7, avoids issues with mutliple dots.
-
-1.65.2 Tue Feb 19 20:00:27 CST 2013
-
-Fix tests for Windows (thanks to Alexandr Ciornii
-for patches).
-
-1.65.1 Sat Dec 22 22:47:55 CST 2012
-
-Pod Errors.
-
-
-
-1.65
-
-Skip unusable tests on windows; use abs_path for
-path checks to avoid symlinks botching the tests.
-
-Cleanups in libs_curr.pm to use 5.10 features.
-
-Add "blib" option to prefer "blib" to "lib" at the
-first level only where blib exists, mainly for use
-in testing.
-
-1.64
-
-Update Build.PL to use '0' instead of '>0' for the
-dependencies.
-
-
-1.63
-
-Avoid indexing the older version by splitting the
-package name onto a separate line in the source.
-
-
-1.62 Tue Feb 14 14:11:17 EST 2012
-
-Switch to Module::Build. This allows installing a
-single file based on $^V of the Perl used for
-installation. This leaves a single "libs.pm"
-insalled as either the source's 5.8 version or
-the newer one for 5.10 or later.
-
-I have no way to test this on Windows or VMS;
-any feedback would be appreciated.
-
-1.61 Fri Feb 10 11:10:30 EST 2012
-
-$^V does not compare gracefully prior to 5.10 or
-5.12 (not sure which). Either way, this leaves the
-comparison of $^V useless. Choices are unpack and
-printf or use Config to get the version.
-
-So... libs.pm now uses Config and version to generate
-comparable objects.
-
-1.59 Tue Dec 20 17:05:10 CST 2011
-
-Fix typo; update tests to expliclty include
-both of the back-end modules.
-
-1.58 Fri Dec 16 13:06:42 CST 2011
-
-Hopefully the metadata is un-screwed up enough for
-the thing to succeed at this point.
-
-1.57 Fri Dec 16 12:26:13 CST 2011
-
-So much for midnight hacks... simplified
-the test for older versions: libs.pm is
-the current version, libs_5_8.pm is stable
-for the older perl's.
-
-1.56 Thu Nov 24 10:26:00 CST 2011
-
-Added "use if $^V < v5.12" to pull in version
-of code useful with v5.8 and later. Basically
-this just puts a rather thin layer in front of
-the older code vs. newer (which will use switches
-for some of the logic, among other things).
-
-1.55 Wed Nov 23 16:50:57 CST 2011
-
-Fix version-string bug in Makefile.PL
-
-1.54 Wed Nov 9 17:00:09 CST 2011
-
-OK, seems to make more sense if the code
-uses 5.10, which is still supported.
-
-1.53 Sun Oct 9 11:02:50 CDT 2011
-
-oops... should have upped the module version number
-when I upped the Perl version... also makes more sense
-to use v-strings at this point with v5.12.
-
-1.52 Fri Sep 9 17:10:29 EDT 2011
-
-Add "realbin" option that bases the lookup on
-$FindBin::RealBin. This allows a command line
-executable to be symlinked back to wherever it
-lives and find configuration files adjacent
-to the "real" file. This saves having to symlink
-the configuration files next to the symlinked
-executable.
-
-Up the use to v5.10 now that 5.8 is no longer
-supported.
-
-1.51 Thu Sep 2 18:26:55 EDT 2010
-
-Fix MANIFEST.
-Internal changes.
-
-1.43 Thu Sep 2 12:34:52 EDT 2010
-
-Fix bug that required use=1 instead of "use" alone in
-argument processing.
-
-Add POD for mixing git repositories using git repository
-as base with ( subdir=lib subonly ).
-
-1.41 Sat Jun 13 23:02:36 EDT 2009
-
-Fix errors in tests 06, 07.
-
-1.40 Wed Jun 10 07:22:48 EDT 2009
-
-Blindly regex the lib's before returning them
-from find_libs. This avoids issues running
-tainted.
-
-1.39 Tue Jun 9 18:14:02 EDT 2009
-
-Remove an extraneous $DB::single.
-
-1.38 Tue Jun 9 17:00:29 EDT 2009
-
-Catch: "-T" doesn't like eval-ed code.
-Fix:
- require lib;
- lib->import( @lib_dirs )
-
-It doesn't seem as though lib depends on
-the caller's namespace, so there isn't
-any harm in calling it this way. Otherwise
-I'll have to find some other way of working
-around -T.
-
-
-1.36 Mon Mar 31 19:06:25 EDT 2008
-
-Add tests for mulitple use or require + multiple
-calls to import. Check that calling import once
-with a subdir followed by a second without any
-arg's still gives the same results (t/0[67]).
-
-Update Makefile.PL to use 5.00601.
-
-1.35 Fri Mar 30 13:05:45 EDT 2007
-
-Add additional check for broken abs_path on W32.
-
-Update tests to add ./bin for cases where the
-
-O/S does not supply one.
-
-1.34 Thu Mar 29 15:42:26 EDT 2007
-
-Add block eval for 'abs_path' calls in the
-sub-dir checks to avoid croaking MS platforms
-(not an issue for *NIX or VMS that I can tell).
-
-1.33 Tue Feb 6 11:40:10 EST 2007
-
-Add subdir and subonly to look below the ./lib
-dir's for things like ../lib/perl5.
-
-1.32 Sat Jan 20 15:58:36 EST 2007
-
-Repair botched MANIFEST
-
-1.31 Thu Dec 7 14:34:24 EST 2006
-
-POD
-
-./exmaple/p5run sets PERL5LIB and exec's whatever else
-is on the command line.
-
-MANIFEST cleanups
-
-1.30 Thu Dec 7 14:34:24 EST 2006
-
-Added 'p5lib' to prefix the lib's found to $ENV{ PERL5LIB }.
-
-POD for p5lib, doc cleanups.
-
-1.26 Tue Aug 1 12:26:13 EDT 2006
-
-- Added Bin argument to allow overriding $FindBin::Bin
- as the root of all evil.
-
-1.25 Fri Mar 3 08:37:49 EST 2006
-
-- POD: using prove without a blib.
-
-1.23 Mon Feb 27 12:49:02 EST 2006
-
-- Fix paren bug in catpath.
-
-- Update POD format bugs.
-
-1.21 Wed Feb 8 16:20:44 EST 2006
-
-- Trying to fix regex oddity on VMS...
-
-- Use ".+" to untaint $FindBin::Bin instead of "(.+)/?".
-
-1.20 Sun Jan 29 19:29:03 EST 2006
-
-- Use File::Spec to split, assemble directory paths.
-
-- Optinally stub Cwd::abs_path if it failes to resolve
- cwd at startup.
-
-- Replaced test.pl with t/*.t.
-
-- POD
-
-1.07 Thu Sep 8 09:33:29 EDT 2005
-
-- RedHat Enterprise Version 4 has a bug that leaves $FindBin::Bin
- with a trailing slash. Fix is to regex it off before using the
- variable.
-
-- Added "debug" argument to set $DB::single = 1 after processing
- the arguments; saves having to hack the code to test where the
- things come from.
-
-1.06 Sat Apr 30 00:24:23 EDT 2005
-
-- Set print to undef -- should've been that way
- to begin with.
-
-1.05 Thu Nov 4 17:35:31 EST 2004
-
-- Wrap abs_path in an eval to handle systems that die on
- non-existant directories.
-
-1.03 Wed Oct 20 12:03:30 EDT 2004
-
-- Fix doc bug -- added /jowbloe/ below /home on the
- sandbox examples.
-
-1.03 Tue Oct 19 17:13:04 EDT 2004
-
-- Update doc's to include sandbox manglement.
-
-1.02 Thu Jun 10 14:26:53 CDT 2004
-
-- Fix typo in version number.
-
-1.01 Mon May 31 21:13:13 CDT 2004
-
-- Modify the split for ignored arguments to ignore whitespace
- around the comma separators. This only applies to cases where
- the caller doesn't use qw() for the arguments and ends up
- with something like: 'ignore=/, /foo'.
-
-- Repair default arg's to successfully ignore '/' and
- '/usr' by default.
-
-- Eval symlink creation to handle systems without symlinks.
-
- Caveat utilitor: this module has only been tested by me on
- *NIX, the assumed directory separation on '/' is most
- likely broken on ms-dos, VMS, or related filesystems. If
- any currently available *NIX lacks symlinks please warn
- me, otherwise YMMV.
-
-- Cleaned up some comments.
-
-1.00 Mon Mar 22 11:18:45 CST 2004
-
-- Up the version number. Thing seems stable enough to call it
- 1.00 at this point.
-
-- Reverse the order of CHANGES, with most recent at the top.
-
-0.18 Tue Mar 16 22:22:02 CST 2004
-
-- Added -e test before abs_path to avoid nastygrams
- from Cwd on abs_path of dangling links.
-
-0.17 Mon Mar 8 23:25:20 CST 2004
-
-- Removed leftover $DB::single (d'oh...)
-
-0.16 Sat Jan 24 14:52:23 CST 2004
-
-- Replaced 0 with undef for default print. noprint is
- now the default.
-
-0.15 Sat Jan 24 14:46:22 CST 2004
-
-- POD
-
-0.14 Wed Dec 3 12:23:42 CST 2003
-
-- Modify Makefile.PL to use ABSTRACT_FROM, NAME entry of POD to
- add abstract.
-
-- Added notes to README.
-
-- Included test for bogus directory (unless you DO have a
- ./frobnicatorium) w/ exported array empty.
-
-0.13 Wed Dec 3 10:12:13 CST 2003
-
-- pod for sandbox description.
-
-0.11 Wed Nov 26 16:08:35 CST 2003
-
-- Fixed switch bug for handling print/noprint & verbose.
-- test.pl failed on Solaris due to /bin -> /usr/bin, test
- changed to regex from eq.
-
-0.10 Mon Nov 24 16:06:22 CST 2003
-
-Initial release.
@@ -0,0 +1,413 @@
+2.09 Sat Aug 9 14:43:10 CDT 2014
+
+Fix bug in handling of scalar arg in old (5.10 or older) module.
+Whitespace & POD cleanups.
+
+2.07 Mon Jul 28 02:48:49 CDT 2014
+
+Try one more time to deal with version issues.
+
+2.01 Sat Jul 26 01:52:46 CDT 2014
+
+Version numbers now come from the current build rather than Makefile.PL.
+Upping the version to v2.00 makes it easier to keep track of it all.
+Makefile uses stringy, .pm uses v-string.
+Hopefully that will keep everyone happy.
+
+For libs_curr:
+
+Avoid truncating dirent's with embedded newlines in taint-hack
+by using single-line mode: m{ (.+) }xs
+
+Add "scalar" option to export the first directory found only as
+a scalar (vs list). Mainly useful with things like config dir's
+where the first one will always be used in any case:
+
+ use FindBin::libs qw( base=etc scalar );
+
+exports "$etc" rather than "@etc" (saves using $etc[0]
+everyplace). Also works with
+
+ use FindBin::libs qw( base=etc export=config scalar );
+
+to export $config rather than an array.
+
+Added some examples.
+
+Replace given block to avoid nastygrams from post-5.16 perls.
+
+Add stub libs.pm as placeholder for version.
+
+Finally remembered to fix typo (thanks to x.guimard).
+
+
+1.11 Wed Jul 2 22:34:00 CDT 2014
+
+R.I.P. Build.PL.
+see Makefile.PL
+
+Fix broken assignment of rel2abs from Cwd rather than
+File::Spec::Functions.
+
+Add test for abs_path or rel2abs surviving both '//' and 'cwd' --
+if neither of them is available or working the rest of this is
+a waste.
+
+Note: I don't have access to windows for testing. If any of this
+fails please contact me and we can figure out what is wrong.
+
+
+1.9.1 Tue May 27 08:20:41 CDT 2014
+
+Minor cleanup blows up in 5.12; works in 5.14. Given that 5.20 is
+about to be on the street: the current version is pushed
+up to 5.14 (i.e., if ref $^V and v5.14 le $^V then the
+installed version is *_curr, otherwise it is *_5_8).
+
+1.9 Sat May 24 09:15:15 CDT 2014
+
+Minor cleanup in handling abs_path replacement.
+Seems to work for people with original issue so this one goes
+on CPAN.
+
+
+1.8.1 Sun Mar 23 14:29:44 CDT 2014
+
+Assign local abs_path rather than shuffle the symbol table after using Cwd.
+Avoids issues with munging symbol table in Cwd itself.
+
+1.8 Tue May 28 21:04:30 CDT 2013
+
+Update to work with v5.18
+
+1.7 Thu Mar 14 15:23:30 GMT 2013
+
+Up version to 1.7, avoids issues with mutliple dots.
+
+1.65.2 Tue Feb 19 20:00:27 CST 2013
+
+Fix tests for Windows (thanks to Alexandr Ciornii
+for patches).
+
+1.65.1 Sat Dec 22 22:47:55 CST 2012
+
+Pod Errors.
+
+1.65
+
+Skip unusable tests on windows; use abs_path for
+path checks to avoid symlinks botching the tests.
+
+Cleanups in libs_curr.pm to use 5.10 features.
+
+Add "blib" option to prefer "blib" to "lib" at the
+first level only where blib exists, mainly for use
+in testing.
+
+1.64
+
+Update Build.PL to use '0' instead of '>0' for the
+dependencies.
+
+
+1.63
+
+Avoid indexing the older version by splitting the
+package name onto a separate line in the source.
+
+
+1.62 Tue Feb 14 14:11:17 EST 2012
+
+Switch to Module::Build. This allows installing a
+single file based on $^V of the Perl used for
+installation. This leaves a single "libs.pm"
+insalled as either the source's 5.8 version or
+the newer one for 5.10 or later.
+
+I have no way to test this on Windows or VMS;
+any feedback would be appreciated.
+
+1.61 Fri Feb 10 11:10:30 EST 2012
+
+$^V does not compare gracefully prior to 5.10 or
+5.12 (not sure which). Either way, this leaves the
+comparison of $^V useless. Choices are unpack and
+printf or use Config to get the version.
+
+So... libs.pm now uses Config and version to generate
+comparable objects.
+
+1.59 Tue Dec 20 17:05:10 CST 2011
+
+Fix typo; update tests to expliclty include
+both of the back-end modules.
+
+1.58 Fri Dec 16 13:06:42 CST 2011
+
+Hopefully the metadata is un-screwed up enough for
+the thing to succeed at this point.
+
+1.57 Fri Dec 16 12:26:13 CST 2011
+
+So much for midnight hacks... simplified
+the test for older versions: libs.pm is
+the current version, libs_5_8.pm is stable
+for the older perl's.
+
+1.56 Thu Nov 24 10:26:00 CST 2011
+
+Added "use if $^V < v5.12" to pull in version
+of code useful with v5.8 and later. Basically
+this just puts a rather thin layer in front of
+the older code vs. newer (which will use switches
+for some of the logic, among other things).
+
+1.55 Wed Nov 23 16:50:57 CST 2011
+
+Fix version-string bug in Makefile.PL
+
+1.54 Wed Nov 9 17:00:09 CST 2011
+
+OK, seems to make more sense if the code
+uses 5.10, which is still supported.
+
+1.53 Sun Oct 9 11:02:50 CDT 2011
+
+oops... should have upped the module version number
+when I upped the Perl version... also makes more sense
+to use v-strings at this point with v5.12.
+
+1.52 Fri Sep 9 17:10:29 EDT 2011
+
+Add "realbin" option that bases the lookup on
+$FindBin::RealBin. This allows a command line
+executable to be symlinked back to wherever it
+lives and find configuration files adjacent
+to the "real" file. This saves having to symlink
+the configuration files next to the symlinked
+executable.
+
+Up the use to v5.10 now that 5.8 is no longer
+supported.
+
+1.51 Thu Sep 2 18:26:55 EDT 2010
+
+Fix MANIFEST.
+Internal changes.
+
+1.43 Thu Sep 2 12:34:52 EDT 2010
+
+Fix bug that required use=1 instead of "use" alone in
+argument processing.
+
+Add POD for mixing git repositories using git repository
+as base with ( subdir=lib subonly ).
+
+1.41 Sat Jun 13 23:02:36 EDT 2009
+
+Fix errors in tests 06, 07.
+
+1.40 Wed Jun 10 07:22:48 EDT 2009
+
+Blindly regex the lib's before returning them
+from find_libs. This avoids issues running
+tainted.
+
+1.39 Tue Jun 9 18:14:02 EDT 2009
+
+Remove an extraneous $DB::single.
+
+1.38 Tue Jun 9 17:00:29 EDT 2009
+
+Catch: "-T" doesn't like eval-ed code.
+Fix:
+ require lib;
+ lib->import( @lib_dirs )
+
+It doesn't seem as though lib depends on
+the caller's namespace, so there isn't
+any harm in calling it this way. Otherwise
+I'll have to find some other way of working
+around -T.
+
+
+1.36 Mon Mar 31 19:06:25 EDT 2008
+
+Add tests for mulitple use or require + multiple
+calls to import. Check that calling import once
+with a subdir followed by a second without any
+arg's still gives the same results (t/0[67]).
+
+Update Makefile.PL to use 5.00601.
+
+1.35 Fri Mar 30 13:05:45 EDT 2007
+
+Add additional check for broken abs_path on W32.
+
+Update tests to add ./bin for cases where the
+
+O/S does not supply one.
+
+1.34 Thu Mar 29 15:42:26 EDT 2007
+
+Add block eval for 'abs_path' calls in the
+sub-dir checks to avoid croaking MS platforms
+(not an issue for *NIX or VMS that I can tell).
+
+1.33 Tue Feb 6 11:40:10 EST 2007
+
+Add subdir and subonly to look below the ./lib
+dir's for things like ../lib/perl5.
+
+1.32 Sat Jan 20 15:58:36 EST 2007
+
+Repair botched MANIFEST
+
+1.31 Thu Dec 7 14:34:24 EST 2006
+
+POD
+
+./exmaple/p5run sets PERL5LIB and exec's whatever else
+is on the command line.
+
+MANIFEST cleanups
+
+1.30 Thu Dec 7 14:34:24 EST 2006
+
+Added 'p5lib' to prefix the lib's found to $ENV{ PERL5LIB }.
+
+POD for p5lib, doc cleanups.
+
+1.26 Tue Aug 1 12:26:13 EDT 2006
+
+- Added Bin argument to allow overriding $FindBin::Bin
+ as the root of all evil.
+
+1.25 Fri Mar 3 08:37:49 EST 2006
+
+- POD: using prove without a blib.
+
+1.23 Mon Feb 27 12:49:02 EST 2006
+
+- Fix paren bug in catpath.
+
+- Update POD format bugs.
+
+1.21 Wed Feb 8 16:20:44 EST 2006
+
+- Trying to fix regex oddity on VMS...
+
+- Use ".+" to untaint $FindBin::Bin instead of "(.+)/?".
+
+1.20 Sun Jan 29 19:29:03 EST 2006
+
+- Use File::Spec to split, assemble directory paths.
+
+- Optinally stub Cwd::abs_path if it failes to resolve
+ cwd at startup.
+
+- Replaced test.pl with t/*.t.
+
+- POD
+
+1.07 Thu Sep 8 09:33:29 EDT 2005
+
+- RedHat Enterprise Version 4 has a bug that leaves $FindBin::Bin
+ with a trailing slash. Fix is to regex it off before using the
+ variable.
+
+- Added "debug" argument to set $DB::single = 1 after processing
+ the arguments; saves having to hack the code to test where the
+ things come from.
+
+1.06 Sat Apr 30 00:24:23 EDT 2005
+
+- Set print to undef -- should've been that way
+ to begin with.
+
+1.05 Thu Nov 4 17:35:31 EST 2004
+
+- Wrap abs_path in an eval to handle systems that die on
+ non-existant directories.
+
+1.03 Wed Oct 20 12:03:30 EDT 2004
+
+- Fix doc bug -- added /jowbloe/ below /home on the
+ sandbox examples.
+
+1.03 Tue Oct 19 17:13:04 EDT 2004
+
+- Update doc's to include sandbox manglement.
+
+1.02 Thu Jun 10 14:26:53 CDT 2004
+
+- Fix typo in version number.
+
+1.01 Mon May 31 21:13:13 CDT 2004
+
+- Modify the split for ignored arguments to ignore whitespace
+ around the comma separators. This only applies to cases where
+ the caller doesn't use qw() for the arguments and ends up
+ with something like: 'ignore=/, /foo'.
+
+- Repair default arg's to successfully ignore '/' and
+ '/usr' by default.
+
+- Eval symlink creation to handle systems without symlinks.
+
+ Caveat utilitor: this module has only been tested by me on
+ *NIX, the assumed directory separation on '/' is most
+ likely broken on ms-dos, VMS, or related filesystems. If
+ any currently available *NIX lacks symlinks please warn
+ me, otherwise YMMV.
+
+- Cleaned up some comments.
+
+1.00 Mon Mar 22 11:18:45 CST 2004
+
+- Up the version number. Thing seems stable enough to call it
+ 1.00 at this point.
+
+- Reverse the order of CHANGES, with most recent at the top.
+
+0.18 Tue Mar 16 22:22:02 CST 2004
+
+- Added -e test before abs_path to avoid nastygrams
+ from Cwd on abs_path of dangling links.
+
+0.17 Mon Mar 8 23:25:20 CST 2004
+
+- Removed leftover $DB::single (d'oh...)
+
+0.16 Sat Jan 24 14:52:23 CST 2004
+
+- Replaced 0 with undef for default print. noprint is
+ now the default.
+
+0.15 Sat Jan 24 14:46:22 CST 2004
+
+- POD
+
+0.14 Wed Dec 3 12:23:42 CST 2003
+
+- Modify Makefile.PL to use ABSTRACT_FROM, NAME entry of POD to
+ add abstract.
+
+- Added notes to README.
+
+- Included test for bogus directory (unless you DO have a
+ ./frobnicatorium) w/ exported array empty.
+
+0.13 Wed Dec 3 10:12:13 CST 2003
+
+- pod for sandbox description.
+
+0.11 Wed Nov 26 16:08:35 CST 2003
+
+- Fixed switch bug for handling print/noprint & verbose.
+- test.pl failed on Solaris due to /bin -> /usr/bin, test
+ changed to regex from eq.
+
+0.10 Mon Nov 24 16:06:22 CST 2003
+
+Initial release.
@@ -1,10 +1,16 @@
-README
-CHANGES
-MANIFEST
-Build.PL
-lib/FindBin/libs_5_8.pm
-lib/FindBin/libs_curr.pm
+Changes
+example/multi_config_dir
example/p5run
+example/single_config_dir
+lib/FindBin/libs.pm
+libs_curr_pm
+libs_old_pm
+Makefile.PL
+MANIFEST
+META.json
+META.yml
+README
+t/00-cwd-sanity.t
t/01-use-ok.t
t/02-export-base.t
t/04-export-nouse-base.t
@@ -12,5 +18,4 @@ t/05-export-subdir.t
t/06-base-subdir-subonly.t
t/07-export-subdir-subonly.t
t/08-base-subdir-subonly.t
-META.yml
-META.json
+t/09-base-subdir-scalar.t
@@ -1,22 +1,33 @@
{
- "abstract" : "FindBin::libs - locate and a 'use lib' or export \ndirectories based on .\n",
+ "abstract" : "locate and a 'use lib' or export ",
"author" : [
- "Steven Lembark <lembark@wrkhors.com"
+ "unknown"
],
"dynamic_config" : 1,
- "generated_by" : "Module::Build version 0.4003, CPAN::Meta::Converter version 2.130880",
+ "generated_by" : "ExtUtils::MakeMaker version 6.68, CPAN::Meta::Converter version 2.131560",
"license" : [
- "perl_5"
+ "unknown"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : "2"
},
"name" : "FindBin-libs",
+ "no_index" : {
+ "directory" : [
+ "t",
+ "inc"
+ ]
+ },
"prereqs" : {
+ "build" : {
+ "requires" : {
+ "ExtUtils::MakeMaker" : "0"
+ }
+ },
"configure" : {
"requires" : {
- "Module::Build" : "0.4003"
+ "ExtUtils::MakeMaker" : "0"
}
},
"runtime" : {
@@ -33,17 +44,6 @@
}
}
},
- "provides" : {
- "FindBin::libs" : {
- "file" : "lib/FindBin/libs_curr.pm",
- "version" : "v1.63.0"
- }
- },
"release_status" : "stable",
- "resources" : {
- "license" : [
- "http://dev.perl.org/licenses/"
- ]
- },
- "version" : "1.8"
+ "version" : "2.09"
}
@@ -1,21 +1,22 @@
---
-abstract: "FindBin::libs - locate and a 'use lib' or export \ndirectories based on .\n"
+abstract: "locate and a 'use lib' or export "
author:
- - 'Steven Lembark <lembark@wrkhors.com'
-build_requires: {}
+ - unknown
+build_requires:
+ ExtUtils::MakeMaker: 0
configure_requires:
- Module::Build: 0.4003
+ ExtUtils::MakeMaker: 0
dynamic_config: 1
-generated_by: 'Module::Build version 0.4003, CPAN::Meta::Converter version 2.130880'
-license: perl
+generated_by: 'ExtUtils::MakeMaker version 6.68, CPAN::Meta::Converter version 2.131560'
+license: unknown
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4
name: FindBin-libs
-provides:
- FindBin::libs:
- file: lib/FindBin/libs_curr.pm
- version: v1.63.0
+no_index:
+ directory:
+ - t
+ - inc
requires:
Carp: 0
Cwd: 0
@@ -26,6 +27,4 @@ requires:
Symbol: 0
Test::More: 0
strict: 0
-resources:
- license: http://dev.perl.org/licenses/
-version: 1.8
+version: 2.09
@@ -0,0 +1,52 @@
+# even the old version is guaranteed not to work
+# with anything earlier than 5.008.
+
+use 5.008;
+use strict;
+
+use ExtUtils::MakeMaker;
+
+my $dest = 'lib/FindBin/libs.pm';
+
+my $from
+= ref $^V && v5.10 le $^V
+? 'libs_curr_pm'
+: 'libs_old_pm'
+;
+
+-e $dest && unlink $dest;
+-e $dest && die "Failed unlink: '$dest' ($!)";
+
+link $from => $dest;
+
+[ -e $dest ] || die "Failed link: '$dest' ($!)";
+
+print STDOUT "Installing: '$from' ($dest)\n";
+
+WriteMakefile
+(
+ NAME => 'FindBin::libs',
+ VERSION_FROM => 'libs_curr_pm',
+ ABSTRACT_FROM => $dest,
+ PREREQ_PM =>
+ {
+ # standard distro, particular versions
+ # are unlikely to cause pain.
+
+ qw
+ (
+ strict 0
+
+ Carp 0
+ Cwd 0
+ FindBin 0
+ Symbol 0
+ File::Spec 0
+ File::Temp 0
+ List::Util 0
+ Test::More 0
+ )
+ },
+);
+
+__END__
@@ -18,10 +18,10 @@ optional parameters (e.g., qw(export) and qw(export=foo)).
Installation:
- perl Build.PL;
- ./Build build;
- ./Build test;
- ./Build install;
+ perl Makefile.PL;
+ make all test install;
perldoc FindBin::libs;
+also see the examples for come common use cases.
+
enjoi
@@ -0,0 +1,15 @@
+#!/bin/env perl
+########################################################################
+# locate the first config file named "LocalPaths.conf" looking up the
+# tree in ./etc dir's above FinBin::Bin.
+########################################################################
+
+use Scalar::Util qw( first );
+
+use FindBin::libs qw( base=etc export );
+
+my $base = 'LocalPaths.conf';
+
+my $found = first { -e "$_/$base } @etc
+or die "No config files found ($base)";
+
@@ -1,7 +1,8 @@
-#!/usr/bin/perl
-
+#!/bin/env perl
+########################################################################
# preload PERL5LIB then execute the "real" code with an
# updated environment.
+########################################################################
use FindBin::libs qw( p5lib );
@@ -0,0 +1,14 @@
+#!/bin/env perl
+########################################################################
+# locate a config file in the first etc dir using the basename of this
+# file with '.conf' added to it.
+########################################################################
+
+use File::Basename;
+
+use FindBin::libs qw( base=etc export=conf_dir scalar );
+
+my $base = basename $0;
+my $path = "$conf_dir/$base.conf";
+
+-e $path or die "Missing config file: '$path'";
@@ -0,0 +1,995 @@
+########################################################################
+# FindBin::libs_curr
+#
+# use $FindBin::Bin to search for 'lib' directories and use them.
+#
+# default action is to look for dir's named "lib" and silently use
+# the lib's without exporting anything. print turns on a short
+# message with the abs_path results, export pushes out a variable
+# (default name is the base value), verbose turns on decision output
+# and print. export takes an optional argument with the name of a
+# variable to export.
+#
+#
+########################################################################
+
+########################################################################
+# housekeeping
+########################################################################
+
+package FindBin::libs;
+
+use v5.10;
+use strict;
+
+use FindBin;
+use Symbol;
+
+use File::Basename;
+
+use Carp qw( croak );
+use Symbol qw( qualify_to_ref );
+
+use File::Spec::Functions
+qw
+(
+ &splitpath
+ &splitdir
+ &catpath
+ &catdir
+);
+
+BEGIN
+{
+ # however... there have been complaints of
+ # places where abs_path does not work.
+ #
+ # if abs_path fails on the working directory
+ # then replace it with rel2abs and live with
+ # possibly slower, redundant directories.
+ #
+ # the abs_path '//' hack allows for testing
+ # broken abs_path on primitive systems that
+ # cannot handle the rooted system being linked
+ # back to itself.
+
+ use Cwd qw( &abs_path &cwd );
+
+ unless( eval {abs_path '//'; abs_path cwd } )
+ {
+ # abs_path seems to be having problems,
+ # fix is to stub it out.
+ #
+ # undef avoids nastygram.
+
+ my $ref = qualify_to_ref 'abs_path', __PACKAGE__;
+
+ my $sub = File::Spec::Functions->can( 'rel2abs' );
+
+ undef &{ $ref };
+
+ *$ref = $sub
+ };
+}
+
+########################################################################
+# package variables
+########################################################################
+
+our $VERSION = '2.09';
+$VERSION = eval $VERSION;
+
+my %defaultz =
+(
+ base => 'lib',
+ use => undef,
+ blib => undef, # prefer ./blib at the first level
+
+ subdir => '', # add this subdir also if found.
+ subonly => undef, # leave out lib's, use only subdir.
+ export => undef, # push variable into caller's space.
+ verbose => undef, # boolean: print inputs, results.
+ debug => undef, # boolean: set internal breakpoints.
+
+ print => 1, # display the results
+
+ p5lib => undef, # prefix PERL5LIB with the results
+
+ ignore => '/,/usr', # dir's to skip looking for ./lib
+);
+
+# only new directories are used, ignore pre-loads
+# this with unwanted values.
+
+my %found = ();
+
+# saves passing this between import and $handle_args.
+
+my %argz = ();
+my $verbose = '';
+my $empty = q{};
+
+########################################################################
+# subroutines
+########################################################################
+
+# HAK ALERT: $Bin is an absolute path, there are cases
+# where splitdir does not add the leading '' onto the
+# directory path for it on VMS. Fix is to unshift a leading
+# '' into @dirpath where the leading entry is true.
+
+my $find_libs
+= sub
+{
+ my $base = basename ( shift || $argz{ base } );
+
+ my $subdir = $argz{ subdir } || '';
+
+ my $subonly = defined $argz{ subonly };
+
+ # for some reason, RH Enterprise V/4 has a
+ # trailing '/'; I havn't seen another copy of
+ # FindBin that does this. fix is quick enough:
+ # strip the trailing '/'.
+ #
+ # using a regex to extract the value untaints it
+ # (not useful for anything much, just helps the
+ # poor slobs stuck in taint mode).
+ #
+ # after that splitpath can grab the directory
+ # portion for future use.
+
+ my ( $Bin ) = ( $argz{ Bin } =~ m{^ (.+) }xs );
+
+ print STDERR "\nSearching $Bin for '$base'...\n"
+ if $verbose;
+
+ my( $vol, $dir ) = splitpath $Bin, 1;
+
+ my @dirpath = splitdir $dir;
+
+ # fix for File::Spec::VMS missing the leading empty
+ # string on a split. this can be removed once File::Spec
+ # is fixed.
+
+ unshift @dirpath, '' if $dirpath[ 0 ];
+
+ my @libz = ();
+
+ PATH:
+ for( 1 .. @dirpath )
+ {
+ # note that catpath is extraneous on *NIX; the
+ # volume only means something on DOS- & VMS-based
+ # filesystems, and adding an empty basename on
+ # *nix is unnecessary.
+ #
+ # HAK ALERT: the poor slobs stuck on windog have an
+ # abs_path that croaks on missing directories. have
+ # to eval the check for subdir's.
+
+ my $abs
+ = eval
+ {
+ abs_path
+ catpath $vol, ( catdir @dirpath, $base ), $empty
+ }
+ || '';
+
+ my $sub
+ = $subdir
+ ? eval { abs_path ( catpath '', $abs, $subdir ) } || ''
+ : ''
+ ;
+
+ my @search = $subonly ? ( $sub ) : ( $abs, $sub );
+
+ for my $dir ( @search )
+ {
+ if( $dir && -d $dir && ! exists $found{ $dir } )
+ {
+ $found{ $dir } = ();
+
+ push @libz, $dir;
+
+ last if $argz{ scalar };
+ }
+ }
+
+ pop @dirpath
+ }
+
+ # caller gets back the existing lib paths
+ # (including volume) walking up the path
+ # from $FindBin::Bin -> root.
+ #
+ # passing it back as a list isn't all that
+ # painful for a few paths.
+
+ wantarray ? @libz : \@libz
+};
+
+# break out the messy part into a separate block.
+
+my $handle_args
+= sub
+{
+ # discard the module, rest are arguments.
+
+ shift;
+
+ # anything after the module are options with arguments
+ # assigned via '='.
+
+ %argz
+ = map
+ {
+ my $use_undef
+ = do
+ {
+ my %a = ();
+ @a{ qw( export ignore ) } = ();
+ \%a
+ };
+
+ my ( $k, $v ) = split '=', $_, 2;
+
+ # leave $v undef?
+
+ exists $use_undef->{ $k }
+ or $v //= 1;
+
+ # "no" inverts the sense of the test.
+
+ $k =~ s{^no}{}
+ and $v = ! $v;
+
+ ( $k => $v )
+ }
+ @_;
+
+ # stuff "debug=1" into your arguments and perl -d will stop here.
+
+ $DB::single = 1 if defined $argz{ debug };
+
+ # default if nothing is supplied is to use the result;
+ # otherwise, without use supplied either of export or
+ # p5lib will turn off use.
+
+ if( exists $argz{ use } )
+ {
+ # nothing further to do
+ }
+ elsif( defined $argz{ export } || defined $argz{ p5lib } )
+ {
+ $argz{ use } = undef;
+ }
+ else
+ {
+ $argz{ use } = 1;
+ }
+
+ local $defaultz{ Bin }
+ = exists $argz{ realbin }
+ ? $FindBin::RealBin
+ : $FindBin::Bin
+ ;
+
+ # now apply the defaults, then sanity check the result.
+ # base is a special case since it always has to exist.
+ #
+ # if $argz{ export } is defined but false then it takes
+ # its default from $argz{ base }.
+
+ while( my($k,$v) = each %defaultz )
+ {
+ # //= doesn't work here since undef may be a
+ # legit default.
+
+ exists $argz{ $k }
+ or
+ $argz{ $k } = $v;
+ }
+
+ exists $argz{ base } && $argz{ base }
+ or croak "Bogus FindBin::libs: missing/false base argument, should be 'base=NAME'";
+
+ exists $argz{ export }
+ and
+ $argz{ export } //= $argz{ base };
+
+ $argz{ ignore } =
+ [
+ grep { $_ } split /\s*,\s*/, $argz{ ignore }
+ ];
+
+ $verbose = defined $argz{ verbose };
+
+ my $base = $argz{ base };
+
+ # now locate the libraries.
+ #
+ # %found contains the abs_path results for each directory to
+ # avoid double-including directories.
+ #
+ # note: loop short-curcuts for the (usually) list.
+
+ %found = ();
+
+ for( @{ $argz{ ignore } } )
+ {
+ if( my $dir = eval { abs_path catdir $_, $base } )
+ {
+ if( -d $dir )
+ {
+ $found{ $dir } = 1;
+ }
+ }
+ }
+};
+
+sub import
+{
+ &$handle_args;
+
+ my @libz = $find_libs->();
+
+ # HAK ALERT: the regex does nothing for security,
+ # just dodges -T. putting this down here instead
+ # of inside find_libs allows people to use saner
+ # untainting plans via find_libs.
+
+ @libz = map { m{ (.+) }xs } @libz;
+
+ my $caller = caller;
+
+ if( $verbose || defined $argz{ print } )
+ {
+ local $\ = "\n";
+ local $, = "\n\t";
+
+ print STDERR "Found */$argz{ base }:", @libz
+ if $verbose;
+ }
+
+ if( $argz{ export } )
+ {
+ my $ref = qualify_to_ref $argz{ export }, $caller;
+
+ if( $verbose )
+ {
+ my $dest = qualify $argz{ export }, $caller;
+
+ $argz{ scalar }
+ ? print STDERR "\nExporting: \$$dest\n"
+ : print STDERR "\nExporting: \@$dest\n"
+ ;
+ }
+
+ $argz{ scalar }
+ ? *$ref = \$libz[0]
+ : *$ref = \@libz;
+ ;
+ }
+
+ if( defined $argz{ p5lib } )
+ {
+ # stuff the lib's found at the front of $ENV{ PERL5LIB }
+
+ ( substr $ENV{ PERL5LIB }, 0, 0 ) = join ':', @libz, ''
+ if @libz;
+
+ print STDERR "\nUpdated PERL5LIB:\t$ENV{ PERL5LIB }\n"
+ if $verbose;
+ }
+
+ if( $argz{ use } && @libz )
+ {
+ # this obviously won't work if lib ever depends
+ # on the caller's package.
+ #
+ # it does avoids issues with -T blowing up on the
+ # old eval technique.
+
+ require lib;
+
+ lib->import( @libz );
+ }
+
+ 0
+}
+
+# keep require happy
+
+1
+
+__END__
+
+=head1 NAME
+
+FindBin::libs - locate and a 'use lib' or export
+directories based on $FindBin::Bin.
+
+=head1 SYNOPSIS
+
+This version of FindBin::libs is suitable for
+Perl v5.10+.
+
+ # search up $FindBin::Bin looking for ./lib directories
+ # and "use lib" them.
+
+ use FindBin::libs;
+
+ # same as above with explicit defaults.
+
+ use FindBin::libs qw( base=lib use=1 noexport noprint );
+
+ # print the lib dir's before using them.
+
+ use FindBin::libs qw( print );
+
+ # find and use lib "altlib" dir's
+
+ use FindBin::libs qw( base=altlib );
+
+ # move starting point from $FindBin::Bin to '/tmp'
+
+ use FindBin::libs qw( Bin=/tmp base=altlib );
+
+ # skip "use lib", export "@altlib" instead.
+
+ use FindBin::libs qw( base=altlib export );
+
+ # find altlib directories, use lib them and export @mylibs
+
+ use FindBin::libs qw( base=altlib export=mylibs use );
+
+ # "export" defaults to "nouse", these two are identical:
+
+ use FindBin::libs qw( export nouse );
+ use FindBin::libs qw( export );
+
+ # use and export are not exclusive:
+
+ use FindBin::libs qw( use export ); # do both
+ use FindBin::libs qw( nouse noexport print ); # print only
+ use FindBin::libs qw( nouse noexport ); # do nothting at all
+
+ # print a few interesting messages about the
+ # items found.
+
+ use FindBinlibs qw( verbose );
+
+ # turn on a breakpoint after the args are prcoessed, before
+ # any search/export/use lib is handled.
+
+ use FindBin::libs qw( debug );
+
+ # prefix PERL5LIB with the lib's found.
+
+ use FindBin::libs qw( perl5lib );
+
+ # find a subdir of the lib's looked for.
+ # the first example will use both ../lib and
+ # ../lib/perl5; the second ../lib/perl5/frobnicate
+ # (if they exist). it can also be used with export
+ # and base to locate special configuration dir's.
+ #
+ # subonly with a base is useful for locating config
+ # files. this finds any "./config/mypackage" dir's
+ # without including any ./config dir's. the result
+ # ends up in @config (see also "export=", above).
+
+ use FindBin::libs qw( subdir=perl5 );
+
+ use FindBin::libs qw( subdir=perl5/frobnicate );
+
+ use FindBin::libs qw( base=config subdir=mypackage subonly export );
+
+ # base and subonly are also useful if your
+ # project is stored in multiple git
+ # repositories.
+ #
+ # say you need libs under api_foo/lib from api_bar: a
+ # base of the git repository directory with subdir of
+ # lib and subonly will pull in those lib dirs.
+
+ use FindBin::libs qw( base=api_foo subdir=lib subonly );
+
+ # no harm in using this multiple times to use
+ # or export multple layers of libs.
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( export=found base=lib );
+ use FindBin::libs qw( export=binz base=bin ignore=/foo,/bar );
+ use FindBin::libs qw( export=junk base=frobnicatorium );
+ use FindBin::libs qw( export base=foobar );
+
+=head1 DESCRIPTION
+
+=head2 General Use
+
+This module will locate directories along the path to $FindBin::Bin
+and "use lib" or export an array of the directories found. The default
+is to locate "lib" directories and "use lib" them without printing
+the list.
+
+Options controll whether the lib's found are exported into the caller's
+space, exported to PERL5LIB, or printed. Exporting or setting perl5lib
+will turn off the default of "use lib" so that:
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( p5lib );
+
+are equivalent to
+
+ use FindBin::libs qw( export nouse );
+ use FindBin::libs qw( p5lib nouse );
+
+Combining export with use or p5lib may be useful, p5lib and
+use are probably not all that useful together.
+
+=head3 Alternate directory name: 'base'
+
+The basename searched for can be changed via 'base=name' so
+that
+
+ use FindBin::libs qw( base=altlib );
+
+will search for directories named "altlib" and "use lib" them.
+
+=head3 Exporting a variable: 'export'
+
+The 'export' option will push an array of the directories found
+and takes an optional argument of the array name, which defaults
+to the basename searched for:
+
+ use FindBin::libs qw( export );
+
+will find "lib" directories and export @lib with the
+list of directories found.
+
+ use FindBin::libs qw( export=mylibs );
+
+will find "lib" directories and export them as "@mylibs" to
+the caller.
+
+If "export" only is given then the "use" option defaults to
+false. So:
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( export nouse );
+
+are equivalent. This is mainly for use when looking for data
+directories with the "base=" argument.
+
+If base is used with export the default array name is the base
+directory value:
+
+ use FindBin::libs qw( export base=meta );
+
+exports @meta while
+
+ use FindBin::libs qw( export=metadirs base=meta );
+
+exports @metadirs.
+
+The use and export switches are not exclusive:
+
+ use FindBin::libs qw( use export=mylibs );
+
+will locate "lib" directories, use lib them, and export
+@mylibs into the caller's package.
+
+=head3 Subdirectories
+
+The "subdir" and "subonly" settings will add or
+exclusively use subdir's. This is useful if some
+of your lib's are in ../lib/perl5 along with
+../lib (subdir=perl5) or all of the lib's are
+in ../lib/perl5 (subonly=perl5).
+
+This can also be handy for locating subdir's used
+for configuring packages:
+
+ use FindBin::libs qw( export base=config subonly=mypackage );
+
+Will leave @config with any "mypacakge" holding
+any "mypackage" subdir's.
+
+=head3 Setting PERL5LIB: p5lib
+
+For cases where the environment is more useful for setting
+up library paths "p5lib" can be used to preload this variable.
+This is mainly useful for automatically including directories
+outside of the parent tree of $FindBin::bin.
+
+For example, using:
+
+ $ export PERL5LIB="/usr/local/foo:/usr/local/bar";
+
+ $ myprog;
+
+or simply
+
+ $ PERL5LIB="/usr/local/lib/foo:/usr/lib/bar" myprog;
+
+(depending on your shell) with #! code including:
+
+ use FindBin::libs qw( p5lib );
+
+will not "use lib" any dir's found but will update PERL5LIB
+to something like:
+
+ /home/me/sandbox/branches/lib:/usr/local/lib/foo:/usr/lib/bar
+
+This can make controlling the paths used simpler and avoid
+the use of symlinks for some testing (see examples below).
+
+Note that "p5lib" and "nouse" are proably worth
+
+=head2 Skipping directories
+
+By default, lib directories under / and /usr are
+sliently ignored. This normally means that /lib, /usr/lib, and
+'/usr/local/lib' are skipped. The "ignore" parameter provides
+a comma-separated list of directories to ignore:
+
+ use FindBin::libs qw( ignore=/skip/this,/and/this/also );
+
+will replace the standard list and thus skip "/skip/this/lib"
+and "/and/this/also/lib". It will search "/lib" and "/usr/lib"
+since the argument ignore list replaces the original one.
+
+=head2 Homegrown Library Management
+
+An all-too-common occurrance managing perly projects is
+being unable to install new modules becuse "it might
+break things", and being unable to test them because
+you can't install them. The usual outcome of this is a
+collection of hard-coded
+
+ use lib qw( /usr/local/projectX ... )
+
+code at the top of each #! file that has to be updated by
+hand for each new project.
+
+To get away from this you'll often see relative paths
+for the lib's, which require running the code from one
+specific place. All this does is push the hard-coding
+into cron, shell wrappers, and begin blocks.
+
+With FindBin::libs you need suffer no more.
+
+Automatically finding libraries in and above the executable
+means you can put your modules into cvs/svn and check them
+out with the project, have multiple copies shared by developers,
+or easily move a module up the directory tree in a testbed
+to regression test the module with existing code. All without
+having to modify a single line of code.
+
+=over 4
+
+=item Code-speicfic modules.
+
+Say your sandbox is in ./sandbox and you are currently
+working in ./sandbox/projects/package/bin on a perl
+executable. You may have some number of modules that
+are specific -- or customized -- for this pacakge,
+share some modules within the project, and may want
+to use company-wide modules that are managed out of
+./sandbox in development. All of this lives under a
+./qc tree on the test boxes and under ./production
+on production servers.
+
+For simplicity, say that your sandbox lives in your
+home direcotry, /home/jowbloe, as a directory or a
+symlink.
+
+If your #! uses FindBin::libs in it then it will
+effectively
+
+ use lib
+ qw(
+ /home/jowbloe/sandbox/lib
+ /home/jowbloe/sandbox/project/lib
+ /home/jowbloe/sandbox/project/package/lib
+ );
+
+if you run /home/jowbloe/sandbox/project/package/bin/foobar.
+This will happen the same way if you use a relative or
+absolute path, perl -d the thing, or if any of the lib
+directories are symlinks outside of your sandbox.
+
+This means that the most specific module directories
+("closest" to your executable) will be picked up first.
+
+If you have a version of Frobnicate.pm in your ./package/lib
+for modifications fine: you'll use it before the one in
+./project or ./sandbox.
+
+Using the "p5lib" argument can help in case where some of
+the code lives outside of the sandbox. To test a sandbox
+version of some other module:
+
+ use FindBin::libs qw( p5lib );
+
+and
+
+ $ PERL5LIB=/other/sandbox/module foobar;
+
+=item Regression Testing
+
+Everntually, however, you'll need to regression test
+Frobnicate.pm with other modules.
+
+Fine: move, copy, or symlink it into ./project/lib and
+you can merrily run ./project/*/bin/* with it and see
+if there are any problems. In fact, so can the nice
+folks in QC.
+
+If you want to install and test a new module just
+prefix it into, say, ./sandbox/lib and all the code
+that has FindBin::libs will simply use it first.
+
+=item Testing with Symlinks
+
+$FindBin::Bin is relative to where an executable is started from.
+This allows a symlink to change the location of directories used
+by FindBin::libs. Full regression testing of an executable can be
+accomplished with a symlink:
+
+ ./sandbox
+ ./lib -> /homegrown/dir/lib
+ ./lib/What/Ever.pm
+
+ ./pre-change
+ ./bin/foobar
+
+ ./post-change
+ ./lib/What/Ever.pm
+ ./bin/foobar -> ../../pre-last-change/bin/foobar
+
+Running foobar symlinked into the post-change directory will
+test it with whatever collection of modules is in the post-change
+directory. A large regression test on some collection of
+changed modules can be performed with a few symlinks into a
+sandbox area.
+
+=item Managing Configuration and Meta-data Files
+
+The "base" option alters FindBin::libs standard base directory.
+This allows for a heirarchical set of metadata directories:
+
+ ./sandbox
+ ./meta
+ ./project/
+ ./meta
+
+ ./project/package
+ ./bin
+ ./meta
+
+with
+
+ use FindBin::libs qw( base=meta export );
+
+ sub read_meta
+ {
+ my $base = shift;
+
+ for my $dir ( @meta )
+ {
+ # open the first one and return
+ ...
+ }
+
+ # caller gets back empty list if nothing was read.
+
+ ()
+ }
+
+=item using "prove" with local modules.
+
+Modules that are not intended for CPAN will not usually have
+a Makefile.PL or Build setup. This makes it harder to check
+the code via "make test". Instead of hacking a one-time
+Makefile, FindBin::libs can be used to locate modules in
+a "lib" directory adjacent to the "t: directory. The setup
+for this module would look like:
+
+
+ ./t/01.t
+ ./t/02.t
+ ...
+
+ ./lib/FindBin/libs.pm
+
+since the *.t files use FindBin::libs they can locate the
+most recent version of code without it having to be copied
+into a ./blib directory (usually via make) before being
+processed. If the module did not have a Makefile this would
+allow:
+
+ prove t/*.t;
+
+to check the code.
+
+=back
+
+=head1 Notes
+
+=head2 Alternatives
+
+FindBin::libs was developed to avoid pitfalls with
+the items listed below. As of FindBin::libs-1.20,
+this is also mutli-platform, where other techniques
+may be limited to *NIX or at least less portable.
+
+=over 4
+
+=item PERL5LIBS
+
+PERL5LIB can be used to accomplish the same directory
+lookups as FindBin::libs. The problem is PERL5LIB often
+contains absolte paths and does not automatically change
+depending on where tests are run. This can leave you
+modifying a file, changing directory to see if it works
+with some other code and testing an unmodified version of
+the code via PERL5LIB. FindBin::libs avoids this by using
+$FindBin::bin to reference where the code is running from.
+
+The same is true of trying to use almost any environmental
+solution, with Perl's built in mechanism or one based on
+$ENV{ PWD } or qx( pwd ).
+
+Aside: Combining an existing PERL5LIB for
+out-of-tree lookups with the "p5lib" option
+works well for most development situations.
+
+=item use lib qw( ../../../../Lib );
+
+This works, but how many dots do you need to get all
+the working lib's into a module or #! code? Class
+distrubuted among several levels subdirectories may
+have qw( ../../../lib ) vs. qw( ../../../../lib )
+or various combinations of them. Validating these by
+hand (let alone correcting them) leaves me crosseyed
+after only a short session.
+
+=item Anchor on a fixed lib directory.
+
+Given a standard directory, it is possible to use
+something like:
+
+ BEGIN
+ {
+ my ( $libdir ) = $0 =~ m{ ^( .+? )/SOMEDIR/ }x;
+
+ eval "use lib qw( $libdir )";
+ }
+
+This looks for a standard location (e.g., /path/to/Mylib)
+in the executable path (or cwd) and uses that.
+
+The main problem here is that if the anchor ever changes
+(e.g., when moving code between projects or relocating
+directories now that SVN supports it) the path often has
+to change in multiple files. The regex also may have to
+support multiple platforms, or be broken into more complicated
+File::Spec code that probably looks pretty much like what
+
+ use FindBin::libs qw( base=Mylib )
+
+does anyway.
+
+=back
+
+=head2 FindBin::libs-1.2+ uses File::Spec
+
+In order to accmodate a wider range of filesystems,
+the code has been re-written to use File::Spec for
+all directory and volume manglement.
+
+There is one thing that File::Spec does not handle,
+hoever, which is fully reolving absolute paths. That
+still has to be handled via abs_path, when it works.
+
+The issue is that File::Spec::rel2abs and
+Cwd::abs_path work differently: abs_path only
+returns true for existing directories and
+resolves symlinks; rel2abs simply prepends cwd()
+to any non-absolute paths.
+
+The difference for FinBin::libs is that
+including redundant directories can lead to
+unexpected results in what gets included;
+looking up the contents of heavily-symlinked
+paths is slow (and has some -- admittedly
+unlikely -- failures at runtime). So, abs_path()
+is the preferred way to find where the lib's
+really live after they are found looking up the
+tree. Using abs_path() also avoids problems
+where the same directory is included twice in a
+sandbox' tree via symlinks.
+
+Due to previous complaints that abs_path did not
+work properly on all systems, the current
+version of FindBin::libs uses File::Spec to
+break apart and re-assemble directories, with
+abs_path used optinally. If "abs_path cwd" works
+then abs_path is used on the directory paths
+handed by File::Spec::catpath(); otherwise the
+paths are used as-is. This may leave users on
+systms with non-working abs_path() having extra
+copies of external library directories in @INC.
+
+Another issue is that I've heard reports of
+some systems failing the '-d' test on symlinks,
+where '-e' would have succeded.
+
+=head1 See Also
+
+=over 4
+
+=item File::Spec
+
+This is used for portability in dis- and re-assembling
+directory paths based on $FindBin::Bin.
+
+=item Older code.
+
+FindBin::libs_5_8.pm is installed if $^V indicates
+that the running perl is prior to v5.10.
+
+=back
+
+=head1 BUGS
+
+=over 4
+
+=item
+
+In order to avoid including junk, FindBin::libs
+uses '-d' to test the items before including
+them on the library list. This works fine so
+long as abs_path() is used to disambiguate any
+symlinks first. If abs_path() is turned off
+then legitimate directories may be left off in
+whatever local conditions might cause a valid
+symlink to fail the '-d' test."
+
+=item
+
+File::Spec 3.16 and prior have a bug in VMS of
+not returning an absolute paths in splitdir for
+dir's without a leading '.'. Fix for this is to
+unshift '', @dirpath if $dirpath[0]. While not a
+bug, this is obviously a somewhat kludgy workaround
+and should be removed (with an added test for a
+working version) once the File::Spec is fixed.
+
+=item
+
+The hack for prior-to-5.12 versions of perl is
+messy, but is the only I've found that works for
+the moment on *NIX, VMS, and MSW. I am not sure
+whether any of these systems are normally configured
+to share perl modules between versions. If the
+moduels are not shared on multiple platforms then
+I can make this work by managing the installation
+rather than checking this every time at startup.
+
+For the moment, at least, this seems to work.
+
+=back
+
+=head1 AUTHOR
+
+Steven Lembark, Workhorse Computing <lembark@wrkhors.com>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
+This code is released under the same terms as Perl-5.10
+or any later version of Perl.
@@ -1,963 +0,0 @@
-########################################################################
-# FindBin::libs
-#
-# use $FindBin::Bin to search for 'lib' directories and use them.
-#
-# default action is to look for dir's named "lib" and silently use
-# the lib's without exporting anything. print turns on a short
-# message with the abs_path results, export pushes out a variable
-# (default name is the base value), verbose turns on decision output
-# and print. export takes an optional argument with the name of a
-# variable to export.
-#
-# Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
-# This code is released under the same terms as Perl-5.8
-# or any later version of Perl.
-#
-########################################################################
-
-########################################################################
-# housekeeping
-########################################################################
-
-package # hak to avoid indexing the extra module
-FindBin::libs;
-
-use v5.8;
-use strict;
-
-use FindBin;
-use Symbol;
-
-use File::Basename;
-
-use Carp qw( croak );
-use Symbol qw( qualify_to_ref );
-
-use File::Spec::Functions
-qw
-(
- &splitpath
- &splitdir
- &catpath
- &catdir
-);
-
-BEGIN
-{
- # however... there have been complaints of
- # places where abs_path does not work.
- #
- # if abs_path fails on the working directory
- # then replace it with rel2abs and live with
- # possibly slower, redundant directories.
- #
- # the abs_path '//' hack allows for testing
- # broken abs_path on primitive systems that
- # cannot handle the rooted system being linked
- # back to itself.
-
- use Cwd qw( &abs_path &cwd );
-
- unless( eval {abs_path '//'; abs_path cwd } )
- {
- # abs_path seems to be having problems,
- # fix is to stub it out. ref and sub are
- # syntatic sugar, but do you really want
- # to see it all on one line???
- #
- # undef avoids re-defining subroutine nastygram.
-
- my $ref = qualify_to_ref 'abs_path', __PACKAGE__;
-
- my $sub = File::Spec::Functions->can( 'rel2abs' );
-
- undef &{ $ref };
-
- *$ref = $sub
- };
-}
-
-########################################################################
-# package variables
-########################################################################
-
-our $VERSION = v1.62;
-
-my %defaultz =
-(
- base => 'lib',
- use => undef,
-
- subdir => '', # add this subdir also if found.
- subonly => undef, # leave out lib's, use only subdir.
- export => undef, # push variable into caller's space.
- verbose => undef, # boolean: print inputs, results.
- debug => undef, # boolean: set internal breakpoints.
-
- print => undef, # display the results
-
- p5lib => undef, # prefix PERL5LIB with the results
-
- ignore => '/,/usr', # dir's to skip looking for ./lib
-);
-
-# only new directories are used, ignore pre-loads
-# this with unwanted values.
-
-my %found = ();
-
-# saves passing this between import and $handle_args.
-
-my %argz = ();
-my $verbose = '';
-my $empty = q{};
-
-########################################################################
-# subroutines
-########################################################################
-
-# HAK ALERT: $Bin is an absolute path, there are cases
-# where splitdir does not add the leading '' onto the
-# directory path for it on VMS. Fix is to unshift a leading
-# '' into @dirpath where the leading entry is true.
-
-my $find_libs
-= sub
-{
- my $base = basename ( shift || $argz{ base } );
-
- my $subdir = $argz{ subdir } || '';
-
- my $subonly = defined $argz{ subonly };
-
- # for some reason, RH Enterprise V/4 has a
- # trailing '/'; I havn't seen another copy of
- # FindBin that does this. fix is quick enough:
- # strip the trailing '/'.
- #
- # using a regex to extract the value untaints it
- # (not useful for anything much, just helps the
- # poor slobs stuck in taint mode).
- #
- # after that splitpath can grab the directory
- # portion for future use.
-
- my ( $Bin ) = $argz{ Bin } =~ m{^ (.+) }xs;
-
- print STDERR "\nSearching $Bin for '$base'...\n"
- if $verbose;
-
- my( $vol, $dir ) = splitpath $Bin, 1;
-
- my @dirpath = splitdir $dir;
-
- # fix for File::Spec::VMS missing the leading empty
- # string on a split. this can be removed once File::Spec
- # is fixed.
-
- unshift @dirpath, '' if $dirpath[ 0 ];
-
- my @libz = ();
-
- for( 1 .. @dirpath )
- {
- # note that catpath is extraneous on *NIX; the
- # volume only means something on DOS- & VMS-based
- # filesystems, and adding an empty basename on
- # *nix is unnecessary.
- #
- # HAK ALERT: the poor slobs stuck on windog have an
- # abs_path that croaks on missing directories. have
- # to eval the check for subdir's.
-
- my $abs
- = eval { abs_path catpath $vol, ( catdir @dirpath, $base ), $empty }
- || '';
-
- my $sub
- = $subdir
- ? eval { abs_path ( catpath '', $abs, $subdir ) } || ''
- : ''
- ;
-
- my @search = $subonly ? ( $sub ) : ( $abs, $sub );
-
- for my $dir ( @search )
- {
- if( $dir && -d $dir && ! exists $found{ $dir } )
- {
- $found{ $dir } = 1;
-
- push @libz, $dir;
- }
- }
-
- pop @dirpath
- }
-
- # caller gets back the existing lib paths
- # (including volume) walking up the path
- # from $FindBin::Bin -> root.
- #
- # passing it back as a list isn't all that
- # painful for a few paths.
-
- wantarray ? @libz : \@libz
-};;
-
-# break out the messy part into a separate block.
-
-my $handle_args
-= sub
-{
- # discard the module, rest are arguments.
-
- shift;
-
- # anything after the module are options with arguments
- # assigned via '='.
-
- %argz
- = map
- {
- my ( $k, $v ) = split '=', $_, 2;
-
- $k =~ s{^ (?:!|no) }{}x
- ? ( $k => undef )
- : ( $k => ( $v || '' ) )
- }
- @_;
-
- # stuff "debug=1" into your arguments and perl -d will stop here.
-
- $DB::single = 1 if defined $argz{debug};
-
- # default if nothing is supplied is to use the result;
- # otherwise, without use supplied either of export or
- # p5lib will turn off use.
-
- if( exists $argz{ use } )
- {
- # nothing further to do
- }
- elsif( defined $argz{ export } || defined $argz{ p5lib } )
- {
- $argz{ use } = undef;
- }
- else
- {
- $argz{ use } = 1;
- }
-
- local $defaultz{ Bin }
- = exists $argz{ realbin }
- ? $FindBin::RealBin
- : $FindBin::Bin
- ;
-
- # now apply the defaults, then sanity check the result.
- # base is a special case since it always has to exist.
- #
- # if $argz{export} is defined but false then it takes
- # its default from $argz{base}.
-
- exists $argz{$_} or $argz{$_} = $defaultz{$_}
- for keys %defaultz;
-
- exists $argz{base} && $argz{base}
- or croak "Bogus FindBin::libs: missing/false base argument, should be 'base=NAME'";
-
- defined $argz{export} and $argz{export} ||= $argz{base};
-
- $argz{ ignore } =
- [
- grep { $_ }
- split /\s*,\s*/,
- $argz{ignore}
- ];
-
- $verbose = defined $argz{verbose};
-
- my $base = $argz{base};
-
- # now locate the libraries.
- #
- # %found contains the abs_path results for each directory to
- # avoid double-including directories.
- #
- # note: loop short-curcuts for the (usually) list.
-
- %found = ();
-
- for( @{ $argz{ ignore } } )
- {
- if( my $dir = eval { abs_path catdir $_, $base } )
- {
- if( -d $dir )
- {
- $found{ $dir } = 1;
- }
- }
- }
-};
-
-sub import
-{
- &$handle_args;
-
- my @libz = $find_libs->();
-
- # HAK ALERT: the regex does nothing for security,
- # just dodges -T. putting this down here instead
- # of inside find_libs allows people to use saner
- # untainting plans via find_libs.
-
- @libz = map { m{ (.+) }x } @libz;
-
- my $caller = caller;
-
- if( $verbose || defined $argz{print} )
- {
- local $\ = "\n";
- local $, = "\n\t";
-
- print STDERR "Found */$argz{ base }:", @libz
- }
-
- if( $argz{export} )
- {
- print STDERR join '', "\nExporting: @", $caller, '::', $argz{export}, "\n"
- if $verbose;
-
- # Symbol this is cleaner than "no strict"
- # for installing the array.
-
- my $ref = qualify_to_ref $argz{ export }, $caller;
-
- *$ref = \@libz;
- }
-
- if( defined $argz{ p5lib } )
- {
- # stuff the lib's found at the front of $ENV{ PERL5LIB }
-
- ( substr $ENV{ PERL5LIB }, 0, 0 ) = join ':', @libz, ''
- if @libz;
-
- print STDERR "\nUpdated PERL5LIB:\t$ENV{ PERL5LIB }\n"
- if $verbose;
- }
-
- if( $argz{use} && @libz )
- {
- # this obviously won't work if lib ever depends
- # on the caller's package.
- #
- # it does avoids issues with -T blowing up on the
- # old eval technique.
-
- require lib;
-
- lib->import( @libz );
- }
-
- 0
-};
-
-# keep require happy
-
-1
-
-__END__
-
-=head1 NAME
-
-FindBin::libs_5_8 - stable version of code for older
-perl installations.
-
-=head1 SYNOPSIS
-
-FindBin::libs locates and performs a 'use lib' for
-directories along the path of $FindBin::Bin to automate
-locating modules. Uses File::Spec and Cwd's abs_path to
-accomodate multiple O/S and redundant symlinks.
-
- # search up $FindBin::Bin looking for ./lib directories
- # and "use lib" them.
-
- use FindBin::libs;
-
- # same as above with explicit defaults.
-
- use FindBin::libs qw( base=lib use=1 noexport noprint );
-
- # print the lib dir's before using them.
-
- use FindBin::libs qw( print );
-
- # find and use lib "altlib" dir's
-
- use FindBin::libs qw( base=altlib );
-
- # move starting point from $FindBin::Bin to '/tmp'
-
- use FindBin::libs qw( Bin=/tmp base=altlib );
-
- # skip "use lib", export "@altlib" instead.
-
- use FindBin::libs qw( base=altlib export );
-
- # find altlib directories, use lib them and export @mylibs
-
- use FindBin::libs qw( base=altlib export=mylibs use );
-
- # "export" defaults to "nouse", these two are identical:
-
- use FindBin::libs qw( export nouse );
- use FindBin::libs qw( export );
-
- # use and export are not exclusive:
-
- use FindBin::libs qw( use export ); # do both
- use FindBin::libs qw( nouse noexport print ); # print only
- use FindBin::libs qw( nouse noexport ); # do nothting at all
-
- # print a few interesting messages about the
- # items found.
-
- use FindBinlibs qw( verbose );
-
- # turn on a breakpoint after the args are prcoessed, before
- # any search/export/use lib is handled.
-
- use FindBin::libs qw( debug );
-
- # prefix PERL5LIB with the lib's found.
-
- use FindBin::libs qw( perl5lib );
-
- # find a subdir of the lib's looked for.
- # the first example will use both ../lib and
- # ../lib/perl5; the second ../lib/perl5/frobnicate
- # (if they exist). it can also be used with export
- # and base to locate special configuration dir's.
- #
- # subonly with a base is useful for locating config
- # files. this finds any "./config/mypackage" dir's
- # without including any ./config dir's. the result
- # ends up in @config (see also "export=", above).
-
- use FindBin::libs qw( subdir=perl5 );
-
- use FindBin::libs qw( subdir=perl5/frobnicate );
-
- use FindBin::libs qw( base=config subdir=mypackage subonly export );
-
- # base and subonly are also useful if your
- # project is stored in multiple git
- # repositories.
- #
- # say you need libs under api_foo/lib from api_bar: a
- # base of the git repository directory with subdir of
- # lib and subonly will pull in those lib dirs.
-
- use FindBin::libs qw( base=api_foo subdir=lib subonly );
-
- # no harm in using this multiple times to use
- # or export multple layers of libs.
-
- use FindBin::libs qw( export );
- use FindBin::libs qw( export=found base=lib );
- use FindBin::libs qw( export=binz base=bin ignore=/foo,/bar );
- use FindBin::libs qw( export=junk base=frobnicatorium );
- use FindBin::libs qw( export base=foobar );
-
-=head1 DESCRIPTION
-
-=head2 General Use
-
-This module will locate directories along the path to $FindBin::Bin
-and "use lib" or export an array of the directories found. The default
-is to locate "lib" directories and "use lib" them without printing
-the list.
-
-Options controll whether the lib's found are exported into the caller's
-space, exported to PERL5LIB, or printed. Exporting or setting perl5lib
-will turn off the default of "use lib" so that:
-
- use FindBin::libs qw( export );
- use FindBin::libs qw( p5lib );
-
-are equivalent to
-
- use FindBin::libs qw( export nouse );
- use FindBin::libs qw( p5lib nouse );
-
-Combining export with use or p5lib may be useful, p5lib and
-use are probably not all that useful together.
-
-=head3 Alternate directory name: 'base'
-
-The basename searched for can be changed via 'base=name' so
-that
-
- use FindBin::libs qw( base=altlib );
-
-will search for directories named "altlib" and "use lib" them.
-
-=head3 Exporting a variable: 'export'
-
-The 'export' option will push an array of the directories found
-and takes an optional argument of the array name, which defaults
-to the basename searched for:
-
- use FindBin::libs qw( export );
-
-will find "lib" directories and export @lib with the
-list of directories found.
-
- use FindBin::libs qw( export=mylibs );
-
-will find "lib" directories and export them as "@mylibs" to
-the caller.
-
-If "export" only is given then the "use" option defaults to
-false. So:
-
- use FindBin::libs qw( export );
- use FindBin::libs qw( export nouse );
-
-are equivalent. This is mainly for use when looking for data
-directories with the "base=" argument.
-
-If base is used with export the default array name is the base
-directory value:
-
- use FindBin::libs qw( export base=meta );
-
-exports @meta while
-
- use FindBin::libs qw( export=metadirs base=meta );
-
-exports @metadirs.
-
-The use and export switches are not exclusive:
-
- use FindBin::libs qw( use export=mylibs );
-
-will locate "lib" directories, use lib them, and export
-@mylibs into the caller's package.
-
-=head3 Subdirectories
-
-The "subdir" and "subonly" settings will add or
-exclusively use subdir's. This is useful if some
-of your lib's are in ../lib/perl5 along with
-../lib (subdir=perl5) or all of the lib's are
-in ../lib/perl5 (subonly=perl5).
-
-This can also be handy for locating subdir's used
-for configuring packages:
-
- use FindBin::libs qw( export base=config subonly=mypackage );
-
-Will leave @config with any "mypackage" holding
-any "mypackage" subdir's.
-
-=head3 Setting PERL5LIB: p5lib
-
-For cases where the environment is more useful for setting
-up library paths "p5lib" can be used to preload this variable.
-This is mainly useful for automatically including directories
-outside of the parent tree of $FindBin::bin.
-
-For example, using:
-
- $ export PERL5LIB="/usr/local/foo:/usr/local/bar";
-
- $ myprog;
-
-or simply
-
- $ PERL5LIB="/usr/local/lib/foo:/usr/lib/bar" myprog;
-
-(depending on your shell) with #! code including:
-
- use FindBin::libs qw( p5lib );
-
-will not "use lib" any dir's found but will update PERL5LIB
-to something like:
-
- /home/me/sandbox/branches/lib:/usr/local/lib/foo:/usr/lib/bar
-
-This can make controlling the paths used simpler and avoid
-the use of symlinks for some testing (see examples below).
-
-Note that "p5lib" and "nouse" are proably worth
-
-=head2 Skipping directories
-
-By default, lib directories under / and /usr are
-sliently ignored. This normally means that /lib, /usr/lib, and
-'/usr/local/lib' are skipped. The "ignore" parameter provides
-a comma-separated list of directories to ignore:
-
- use FindBin::libs qw( ignore=/skip/this,/and/this/also );
-
-will replace the standard list and thus skip "/skip/this/lib"
-and "/and/this/also/lib". It will search "/lib" and "/usr/lib"
-since the argument ignore list replaces the original one.
-
-=head2 Homegrown Library Management
-
-An all-too-common occurrance managing perly projects is
-being unable to install new modules becuse "it might
-break things", and being unable to test them because
-you can't install them. The usual outcome of this is a
-collection of hard-coded
-
- use lib qw( /usr/local/projectX ... )
-
-code at the top of each #! file that has to be updated by
-hand for each new project.
-
-To get away from this you'll often see relative paths
-for the lib's, which require running the code from one
-specific place. All this does is push the hard-coding
-into cron, shell wrappers, and begin blocks.
-
-With FindBin::libs you need suffer no more.
-
-Automatically finding libraries in and above the executable
-means you can put your modules into cvs/svn and check them
-out with the project, have multiple copies shared by developers,
-or easily move a module up the directory tree in a testbed
-to regression test the module with existing code. All without
-having to modify a single line of code.
-
-=over 4
-
-=item Code-speicfic modules.
-
-Say your sandbox is in ./sandbox and you are currently
-working in ./sandbox/projects/package/bin on a perl
-executable. You may have some number of modules that
-are specific -- or customized -- for this pacakge,
-share some modules within the project, and may want
-to use company-wide modules that are managed out of
-./sandbox in development. All of this lives under a
-./qc tree on the test boxes and under ./production
-on production servers.
-
-For simplicity, say that your sandbox lives in your
-home direcotry, /home/jowbloe, as a directory or a
-symlink.
-
-If your #! uses FindBin::libs in it then it will
-effectively
-
- use lib
- qw(
- /home/jowbloe/sandbox/lib
- /home/jowbloe/sandbox/project/lib
- /home/jowbloe/sandbox/project/package/lib
- );
-
-if you run /home/jowbloe/sandbox/project/package/bin/foobar.
-This will happen the same way if you use a relative or
-absolute path, perl -d the thing, or if any of the lib
-directories are symlinks outside of your sandbox.
-
-This means that the most specific module directories
-("closest" to your executable) will be picked up first.
-
-If you have a version of Frobnicate.pm in your ./package/lib
-for modifications fine: you'll use it before the one in
-./project or ./sandbox.
-
-Using the "p5lib" argument can help in case where some of
-the code lives outside of the sandbox. To test a sandbox
-version of some other module:
-
- use FindBin::libs qw( p5lib );
-
-and
-
- $ PERL5LIB=/other/sandbox/module foobar;
-
-=item Regression Testing
-
-Everntually, however, you'll need to regression test
-Frobnicate.pm with other modules.
-
-Fine: move, copy, or symlink it into ./project/lib and
-you can merrily run ./project/*/bin/* with it and see
-if there are any problems. In fact, so can the nice
-folks in QC.
-
-If you want to install and test a new module just
-prefix it into, say, ./sandbox/lib and all the code
-that has FindBin::libs will simply use it first.
-
-=item Testing with Symlinks
-
-$FindBin::Bin is relative to where an executable is started from.
-This allows a symlink to change the location of directories used
-by FindBin::libs. Full regression testing of an executable can be
-accomplished with a symlink:
-
- ./sandbox
- ./lib -> /homegrown/dir/lib
- ./lib/What/Ever.pm
-
- ./pre-change
- ./bin/foobar
-
- ./post-change
- ./lib/What/Ever.pm
- ./bin/foobar -> ../../pre-last-change/bin/foobar
-
-Running foobar symlinked into the post-change directory will
-test it with whatever collection of modules is in the post-change
-directory. A large regression test on some collection of
-changed modules can be performed with a few symlinks into a
-sandbox area.
-
-=item Managing Configuration and Meta-data Files
-
-The "base" option alters FindBin::libs standard base directory.
-This allows for a heirarchical set of metadata directories:
-
- ./sandbox
- ./meta
- ./project/
- ./meta
-
- ./project/package
- ./bin
- ./meta
-
-with
-
- use FindBin::libs qw( base=meta export );
-
- sub read_meta
- {
- my $base = shift;
-
- for my $dir ( @meta )
- {
- # open the first one and return
- ...
- }
-
- # caller gets back empty list if nothing was read.
-
- ()
- }
-
-=item using "prove" with local modules.
-
-Modules that are not intended for CPAN will not usually have
-a Makefile.PL or Build setup. This makes it harder to check
-the code via "make test". Instead of hacking a one-time
-Makefile, FindBin::libs can be used to locate modules in
-a "lib" directory adjacent to the "t: directory. The setup
-for this module would look like:
-
-
- ./t/01.t
- ./t/02.t
- ...
-
- ./lib/FindBin/libs.pm
-
-since the *.t files use FindBin::libs they can locate the
-most recent version of code without it having to be copied
-into a ./blib directory (usually via make) before being
-processed. If the module did not have a Makefile this would
-allow:
-
- prove t/*.t;
-
-to check the code.
-
-=back
-
-=head1 Notes
-
-=head2 Alternatives
-
-FindBin::libs was developed to avoid pitfalls with
-the items listed below. As of FindBin::libs-1.20,
-this is also mutli-platform, where other techniques
-may be limited to *NIX or at least less portable.
-
-=over 4
-
-=item PERL5LIBS
-
-PERL5LIB can be used to accomplish the same directory
-lookups as FindBin::libs. The problem is PERL5LIB often
-contains absolte paths and does not automatically change
-depending on where tests are run. This can leave you
-modifying a file, changing directory to see if it works
-with some other code and testing an unmodified version of
-the code via PERL5LIB. FindBin::libs avoids this by using
-$FindBin::bin to reference where the code is running from.
-
-The same is true of trying to use almost any environmental
-solution, with Perl's built in mechanism or one based on
-$ENV{ PWD } or qx( pwd ).
-
-Aside: Combining an existing PERL5LIB for
-out-of-tree lookups with the "p5lib" option
-works well for most development situations.
-
-=item use lib qw( ../../../../Lib );
-
-This works, but how many dots do you need to get all
-the working lib's into a module or #! code? Class
-distrubuted among several levels subdirectories may
-have qw( ../../../lib ) vs. qw( ../../../../lib )
-or various combinations of them. Validating these by
-hand (let alone correcting them) leaves me crosseyed
-after only a short session.
-
-=item Anchor on a fixed lib directory.
-
-Given a standard directory, it is possible to use
-something like:
-
- BEGIN
- {
- my ( $libdir ) = $0 =~ m{ ^( .+? )/SOMEDIR/ }x;
-
- eval "use lib qw( $libdir )";
- }
-
-This looks for a standard location (e.g., /path/to/Mylib)
-in the executable path (or cwd) and uses that.
-
-The main problem here is that if the anchor ever changes
-(e.g., when moving code between projects or relocating
-directories now that SVN supports it) the path often has
-to change in multiple files. The regex also may have to
-support multiple platforms, or be broken into more complicated
-File::Spec code that probably looks pretty much like what
-
- use FindBin::libs qw( base=Mylib )
-
-does anyway.
-
-=back
-
-=head2 FindBin::libs-1.2+ uses File::Spec
-
-In order to accmodate a wider range of filesystems,
-the code has been re-written to use File::Spec for
-all directory and volume manglement.
-
-There is one thing that File::Spec does not handle,
-hoever, which is fully reolving absolute paths. That
-still has to be handled via abs_path, when it works.
-
-The issue is that File::Spec::rel2abs and
-Cwd::abs_path work differently: abs_path only
-returns true for existing directories and
-resolves symlinks; rel2abs simply prepends cwd()
-to any non-absolute paths.
-
-The difference for FinBin::libs is that
-including redundant directories can lead to
-unexpected results in what gets included;
-looking up the contents of heavily-symlinked
-paths is slow (and has some -- admittedly
-unlikely -- failures at runtime). So, abs_path()
-is the preferred way to find where the lib's
-really live after they are found looking up the
-tree. Using abs_path() also avoids problems
-where the same directory is included twice in a
-sandbox' tree via symlinks.
-
-Due to previous complaints that abs_path did not
-work properly on all systems, the current
-version of FindBin::libs uses File::Spec to
-break apart and re-assemble directories, with
-abs_path used optinally. If "abs_path cwd" works
-then abs_path is used on the directory paths
-handed by File::Spec::catpath(); otherwise the
-paths are used as-is. This may leave users on
-systms with non-working abs_path() having extra
-copies of external library directories in @INC.
-
-Another issue is that I've heard reports of
-some systems failing the '-d' test on symlinks,
-where '-e' would have succeded.
-
-=head1 See Also
-
-=over 4
-
-=item File::Spec
-
-This is used for portability in dis- and re-assembling
-directory paths based on $FindBin::Bin.
-
-=item libs_curr.pm
-
-This is installed if $^V indicates that the running
-perl is >= v5.10.
-
-=back
-
-=head1 BUGS
-
-=over 4
-
-=item
-
-In order to avoid including junk, FindBin::libs
-uses '-d' to test the items before including
-them on the library list. This works fine so
-long as abs_path() is used to disambiguate any
-symlinks first. If abs_path() is turned off
-then legitimate directories may be left off in
-whatever local conditions might cause a valid
-symlink to fail the '-d' test."
-
-=item
-
-File::Spec 3.16 and prior have a bug in VMS of
-not returning an absolute paths in splitdir for
-dir's without a leading '.'. Fix for this is to
-unshift '', @dirpath if $dirpath[0]. While not a
-bug, this is obviously a somewhat kludgy workaround
-and should be removed (with an added test for a
-working version) once the File::Spec is fixed.
-
-=item
-
-The hack for prior-to-5.12 versions of perl is
-messy, but is the only I've found that works for
-the moment on *NIX, VMS, and MSW. I am not sure
-whether any of these systems are normally configured
-to share perl modules between versions. If the
-moduels are not shared on multiple platforms then
-I can make this work by managing the installation
-rather than checking this every time at startup.
-
-For the moment, at least, this seems to work.
-
-=back
-
-=head1 AUTHOR
-
-Steven Lembark, Workhorse Computing <lembark@wrkhors.com>
-
-=head1 COPYRIGHT
-
-Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
-This code is released under the same terms as Perl-5.8
-or any later version of Perl.
@@ -1,981 +0,0 @@
-########################################################################
-# FindBin::libs_curr
-#
-# use $FindBin::Bin to search for 'lib' directories and use them.
-#
-# default action is to look for dir's named "lib" and silently use
-# the lib's without exporting anything. print turns on a short
-# message with the abs_path results, export pushes out a variable
-# (default name is the base value), verbose turns on decision output
-# and print. export takes an optional argument with the name of a
-# variable to export.
-#
-#
-########################################################################
-
-########################################################################
-# housekeeping
-########################################################################
-
-package FindBin::libs;
-
-use v5.10;
-use strict;
-
-use FindBin;
-use Symbol;
-
-use File::Basename;
-
-use Carp qw( croak );
-use List::Util qw( first );
-use Symbol qw( qualify_to_ref );
-
-use File::Spec::Functions
-qw
-(
- &splitpath
- &splitdir
- &catpath
- &catdir
-);
-
-BEGIN
-{
- # however... there have been complaints of
- # places where abs_path does not work.
- #
- # if abs_path fails on the working directory
- # then replace it with rel2abs and live with
- # possibly slower, redundant directories.
- #
- # the abs_path '//' hack allows for testing
- # broken abs_path on primitive systems that
- # cannot handle the rooted system being linked
- # back to itself.
-
- use Cwd qw( &abs_path &cwd );
-
- unless( eval {abs_path '//'; abs_path cwd } )
- {
- # abs_path seems to be having problems,
- # fix is to stub it out.
- #
- # undef avoids nastygram.
-
- my $ref = qualify_to_ref 'abs_path', __PACKAGE__;
-
- my $sub = File::Spec::Functions->can( 'rel2abs' );
-
- undef &{ $ref };
-
- *$ref = $sub
- };
-}
-
-########################################################################
-# package variables
-########################################################################
-
-our $VERSION = v1.63;
-
-my %defaultz =
-(
- base => 'lib',
- use => undef,
- blib => undef, # prefer ./blib at the first level
-
- subdir => '', # add this subdir also if found.
- subonly => undef, # leave out lib's, use only subdir.
- export => undef, # push variable into caller's space.
- verbose => undef, # boolean: print inputs, results.
- debug => undef, # boolean: set internal breakpoints.
-
- print => 1, # display the results
-
- p5lib => undef, # prefix PERL5LIB with the results
-
- ignore => '/,/usr', # dir's to skip looking for ./lib
-);
-
-my @use_undef = qw( export ignore );
-
-# only new directories are used, ignore pre-loads
-# this with unwanted values.
-
-my %found = ();
-
-# saves passing this between import and $handle_args.
-
-my %argz = ();
-my $verbose = '';
-my $empty = q{};
-
-########################################################################
-# subroutines
-########################################################################
-
-# HAK ALERT: $Bin is an absolute path, there are cases
-# where splitdir does not add the leading '' onto the
-# directory path for it on VMS. Fix is to unshift a leading
-# '' into @dirpath where the leading entry is true.
-
-my $find_libs
-= sub
-{
- my $base = basename ( shift || $argz{ base } );
-
- my $subdir = $argz{ subdir } || '';
-
- my $subonly = defined $argz{ subonly };
-
- # for some reason, RH Enterprise V/4 has a
- # trailing '/'; I havn't seen another copy of
- # FindBin that does this. fix is quick enough:
- # strip the trailing '/'.
- #
- # using a regex to extract the value untaints it
- # (not useful for anything much, just helps the
- # poor slobs stuck in taint mode).
- #
- # after that splitpath can grab the directory
- # portion for future use.
-
- my ( $Bin ) = ( $argz{ Bin } =~ m{^ (.+) }xs );
-
- print STDERR "\nSearching $Bin for '$base'...\n"
- if $verbose;
-
- my( $vol, $dir ) = splitpath $Bin, 1;
-
- my @dirpath = splitdir $dir;
-
- # fix for File::Spec::VMS missing the leading empty
- # string on a split. this can be removed once File::Spec
- # is fixed.
-
- unshift @dirpath, '' if $dirpath[ 0 ];
-
- my @libz = ();
-
- for( 1 .. @dirpath )
- {
- # note that catpath is extraneous on *NIX; the
- # volume only means something on DOS- & VMS-based
- # filesystems, and adding an empty basename on
- # *nix is unnecessary.
- #
- # HAK ALERT: the poor slobs stuck on windog have an
- # abs_path that croaks on missing directories. have
- # to eval the check for subdir's.
-
- my $abs
- = eval
- {
- abs_path
- catpath $vol, ( catdir @dirpath, $base ), $empty
- }
- || '';
-
- my $sub
- = $subdir
- ? eval { abs_path ( catpath '', $abs, $subdir ) } || ''
- : ''
- ;
-
- my @search = $subonly ? ( $sub ) : ( $abs, $sub );
-
- for my $dir ( @search )
- {
- if( $dir && -d $dir && ! exists $found{ $dir } )
- {
- $found{ $dir } = ();
-
- push @libz, $dir;
- }
- }
-
- pop @dirpath
- }
-
- # caller gets back the existing lib paths
- # (including volume) walking up the path
- # from $FindBin::Bin -> root.
- #
- # passing it back as a list isn't all that
- # painful for a few paths.
-
- wantarray ? @libz : \@libz
-};
-
-# break out the messy part into a separate block.
-
-my $handle_args
-= sub
-{
- # discard the module, rest are arguments.
-
- shift;
-
- # anything after the module are options with arguments
- # assigned via '='.
-
- %argz
- = map
- {
- my ( $k, $v ) = split '=', $_, 2;
-
- defined $v
- or
- first{ $k eq $_ } @use_undef
- or
- $v //= 1;
-
- # "no" inverts the sense of the test.
-
- $k =~ s{^no}{}
- and $v = ! $v;
-
- ( $k => $v )
- }
- @_;
-
- # stuff "debug=1" into your arguments and perl -d will stop here.
-
- $DB::single = 1 if defined $argz{ debug };
-
- # default if nothing is supplied is to use the result;
- # otherwise, without use supplied either of export or
- # p5lib will turn off use.
-
- if( exists $argz{ use } )
- {
- # nothing further to do
- }
- elsif( defined $argz{ export } || defined $argz{ p5lib } )
- {
- $argz{ use } = undef;
- }
- else
- {
- $argz{ use } = 1;
- }
-
- local $defaultz{ Bin }
- = exists $argz{ realbin }
- ? $FindBin::RealBin
- : $FindBin::Bin
- ;
-
- # now apply the defaults, then sanity check the result.
- # base is a special case since it always has to exist.
- #
- # if $argz{ export } is defined but false then it takes
- # its default from $argz{ base }.
-
- while( my($k,$v) = each %defaultz )
- {
- # //= doesn't work here since undef may be a
- # legit default.
-
- exists $argz{ $k }
- or
- $argz{ $k } = $v;
- }
-
- exists $argz{ base } && $argz{ base }
- or croak "Bogus FindBin::libs: missing/false base argument, should be 'base=NAME'";
-
- exists $argz{ export }
- and
- $argz{ export } //= $argz{ base };
-
- $argz{ ignore } =
- [
- grep { $_ } split /\s*,\s*/, $argz{ ignore }
- ];
-
- $verbose = defined $argz{ verbose };
-
- my $base = $argz{ base };
-
- # now locate the libraries.
- #
- # %found contains the abs_path results for each directory to
- # avoid double-including directories.
- #
- # note: loop short-curcuts for the (usually) list.
-
- %found = ();
-
- for( @{ $argz{ ignore } } )
- {
- if( my $dir = eval { abs_path catdir $_, $base } )
- {
- if( -d $dir )
- {
- $found{ $dir } = 1;
- }
- }
- }
-};
-
-sub import
-{
- &$handle_args;
-
- my @libz = $find_libs->();
-
- # HAK ALERT: the regex does nothing for security,
- # just dodges -T. putting this down here instead
- # of inside find_libs allows people to use saner
- # untainting plans via find_libs.
-
- @libz = map { m{ (.+) }x } @libz;
-
- my $caller = caller;
-
- if( $verbose || defined $argz{ print } )
- {
- local $\ = "\n";
- local $, = "\n\t";
-
- print STDERR "Found */$argz{ base }:", @libz
- if $verbose;
- }
-
- if( $argz{ export } )
- {
- my $dest = qualify $argz{ export }, $caller;
- my $ref = qualify_to_ref $dest;
-
- print STDERR "\nExporting: \@$dest\n"
- if $verbose;
-
- # Symbol this is cleaner than "no strict"
- # for installing the array.
-
- *$ref = \@libz;
- }
-
- if( defined $argz{ p5lib } )
- {
- # stuff the lib's found at the front of $ENV{ PERL5LIB }
-
- ( substr $ENV{ PERL5LIB }, 0, 0 ) = join ':', @libz, ''
- if @libz;
-
- print STDERR "\nUpdated PERL5LIB:\t$ENV{ PERL5LIB }\n"
- if $verbose;
- }
-
- if( $argz{ use } && @libz )
- {
- # this obviously won't work if lib ever depends
- # on the caller's package.
- #
- # it does avoids issues with -T blowing up on the
- # old eval technique.
-
- require lib;
-
- lib->import( @libz );
- }
-
- 0
-}
-
-# keep require happy
-
-1
-
-__END__
-
-=head1 NAME
-
-FindBin::libs - locate and a 'use lib' or export
-directories based on $FindBin::Bin.
-
-=head1 SYNOPSIS
-
-This version of FindBin::libs is suitable for
-Perl v5.10+.
-
- # search up $FindBin::Bin looking for ./lib directories
- # and "use lib" them.
-
- use FindBin::libs;
-
- # same as above with explicit defaults.
-
- use FindBin::libs qw( base=lib use=1 noexport noprint );
-
- # print the lib dir's before using them.
-
- use FindBin::libs qw( print );
-
- # find and use lib "altlib" dir's
-
- use FindBin::libs qw( base=altlib );
-
- # move starting point from $FindBin::Bin to '/tmp'
-
- use FindBin::libs qw( Bin=/tmp base=altlib );
-
- # skip "use lib", export "@altlib" instead.
-
- use FindBin::libs qw( base=altlib export );
-
- # find altlib directories, use lib them and export @mylibs
-
- use FindBin::libs qw( base=altlib export=mylibs use );
-
- # "export" defaults to "nouse", these two are identical:
-
- use FindBin::libs qw( export nouse );
- use FindBin::libs qw( export );
-
- # use and export are not exclusive:
-
- use FindBin::libs qw( use export ); # do both
- use FindBin::libs qw( nouse noexport print ); # print only
- use FindBin::libs qw( nouse noexport ); # do nothting at all
-
- # print a few interesting messages about the
- # items found.
-
- use FindBinlibs qw( verbose );
-
- # turn on a breakpoint after the args are prcoessed, before
- # any search/export/use lib is handled.
-
- use FindBin::libs qw( debug );
-
- # prefix PERL5LIB with the lib's found.
-
- use FindBin::libs qw( perl5lib );
-
- # find a subdir of the lib's looked for.
- # the first example will use both ../lib and
- # ../lib/perl5; the second ../lib/perl5/frobnicate
- # (if they exist). it can also be used with export
- # and base to locate special configuration dir's.
- #
- # subonly with a base is useful for locating config
- # files. this finds any "./config/mypackage" dir's
- # without including any ./config dir's. the result
- # ends up in @config (see also "export=", above).
-
- use FindBin::libs qw( subdir=perl5 );
-
- use FindBin::libs qw( subdir=perl5/frobnicate );
-
- use FindBin::libs qw( base=config subdir=mypackage subonly export );
-
- # base and subonly are also useful if your
- # project is stored in multiple git
- # repositories.
- #
- # say you need libs under api_foo/lib from api_bar: a
- # base of the git repository directory with subdir of
- # lib and subonly will pull in those lib dirs.
-
- use FindBin::libs qw( base=api_foo subdir=lib subonly );
-
- # no harm in using this multiple times to use
- # or export multple layers of libs.
-
- use FindBin::libs qw( export );
- use FindBin::libs qw( export=found base=lib );
- use FindBin::libs qw( export=binz base=bin ignore=/foo,/bar );
- use FindBin::libs qw( export=junk base=frobnicatorium );
- use FindBin::libs qw( export base=foobar );
-
-=head1 DESCRIPTION
-
-=head2 General Use
-
-This module will locate directories along the path to $FindBin::Bin
-and "use lib" or export an array of the directories found. The default
-is to locate "lib" directories and "use lib" them without printing
-the list.
-
-Options controll whether the lib's found are exported into the caller's
-space, exported to PERL5LIB, or printed. Exporting or setting perl5lib
-will turn off the default of "use lib" so that:
-
- use FindBin::libs qw( export );
- use FindBin::libs qw( p5lib );
-
-are equivalent to
-
- use FindBin::libs qw( export nouse );
- use FindBin::libs qw( p5lib nouse );
-
-Combining export with use or p5lib may be useful, p5lib and
-use are probably not all that useful together.
-
-=head3 Alternate directory name: 'base'
-
-The basename searched for can be changed via 'base=name' so
-that
-
- use FindBin::libs qw( base=altlib );
-
-will search for directories named "altlib" and "use lib" them.
-
-=head3 Exporting a variable: 'export'
-
-The 'export' option will push an array of the directories found
-and takes an optional argument of the array name, which defaults
-to the basename searched for:
-
- use FindBin::libs qw( export );
-
-will find "lib" directories and export @lib with the
-list of directories found.
-
- use FindBin::libs qw( export=mylibs );
-
-will find "lib" directories and export them as "@mylibs" to
-the caller.
-
-If "export" only is given then the "use" option defaults to
-false. So:
-
- use FindBin::libs qw( export );
- use FindBin::libs qw( export nouse );
-
-are equivalent. This is mainly for use when looking for data
-directories with the "base=" argument.
-
-If base is used with export the default array name is the base
-directory value:
-
- use FindBin::libs qw( export base=meta );
-
-exports @meta while
-
- use FindBin::libs qw( export=metadirs base=meta );
-
-exports @metadirs.
-
-The use and export switches are not exclusive:
-
- use FindBin::libs qw( use export=mylibs );
-
-will locate "lib" directories, use lib them, and export
-@mylibs into the caller's package.
-
-=head3 Subdirectories
-
-The "subdir" and "subonly" settings will add or
-exclusively use subdir's. This is useful if some
-of your lib's are in ../lib/perl5 along with
-../lib (subdir=perl5) or all of the lib's are
-in ../lib/perl5 (subonly=perl5).
-
-This can also be handy for locating subdir's used
-for configuring packages:
-
- use FindBin::libs qw( export base=config subonly=mypackage );
-
-Will leave @config with any "mypackage" holding
-any "mypackage" subdir's.
-
-=head3 Setting PERL5LIB: p5lib
-
-For cases where the environment is more useful for setting
-up library paths "p5lib" can be used to preload this variable.
-This is mainly useful for automatically including directories
-outside of the parent tree of $FindBin::bin.
-
-For example, using:
-
- $ export PERL5LIB="/usr/local/foo:/usr/local/bar";
-
- $ myprog;
-
-or simply
-
- $ PERL5LIB="/usr/local/lib/foo:/usr/lib/bar" myprog;
-
-(depending on your shell) with #! code including:
-
- use FindBin::libs qw( p5lib );
-
-will not "use lib" any dir's found but will update PERL5LIB
-to something like:
-
- /home/me/sandbox/branches/lib:/usr/local/lib/foo:/usr/lib/bar
-
-This can make controlling the paths used simpler and avoid
-the use of symlinks for some testing (see examples below).
-
-Note that "p5lib" and "nouse" are proably worth
-
-=head2 Skipping directories
-
-By default, lib directories under / and /usr are
-sliently ignored. This normally means that /lib, /usr/lib, and
-'/usr/local/lib' are skipped. The "ignore" parameter provides
-a comma-separated list of directories to ignore:
-
- use FindBin::libs qw( ignore=/skip/this,/and/this/also );
-
-will replace the standard list and thus skip "/skip/this/lib"
-and "/and/this/also/lib". It will search "/lib" and "/usr/lib"
-since the argument ignore list replaces the original one.
-
-=head2 Homegrown Library Management
-
-An all-too-common occurrance managing perly projects is
-being unable to install new modules becuse "it might
-break things", and being unable to test them because
-you can't install them. The usual outcome of this is a
-collection of hard-coded
-
- use lib qw( /usr/local/projectX ... )
-
-code at the top of each #! file that has to be updated by
-hand for each new project.
-
-To get away from this you'll often see relative paths
-for the lib's, which require running the code from one
-specific place. All this does is push the hard-coding
-into cron, shell wrappers, and begin blocks.
-
-With FindBin::libs you need suffer no more.
-
-Automatically finding libraries in and above the executable
-means you can put your modules into cvs/svn and check them
-out with the project, have multiple copies shared by developers,
-or easily move a module up the directory tree in a testbed
-to regression test the module with existing code. All without
-having to modify a single line of code.
-
-=over 4
-
-=item Code-speicfic modules.
-
-Say your sandbox is in ./sandbox and you are currently
-working in ./sandbox/projects/package/bin on a perl
-executable. You may have some number of modules that
-are specific -- or customized -- for this pacakge,
-share some modules within the project, and may want
-to use company-wide modules that are managed out of
-./sandbox in development. All of this lives under a
-./qc tree on the test boxes and under ./production
-on production servers.
-
-For simplicity, say that your sandbox lives in your
-home direcotry, /home/jowbloe, as a directory or a
-symlink.
-
-If your #! uses FindBin::libs in it then it will
-effectively
-
- use lib
- qw(
- /home/jowbloe/sandbox/lib
- /home/jowbloe/sandbox/project/lib
- /home/jowbloe/sandbox/project/package/lib
- );
-
-if you run /home/jowbloe/sandbox/project/package/bin/foobar.
-This will happen the same way if you use a relative or
-absolute path, perl -d the thing, or if any of the lib
-directories are symlinks outside of your sandbox.
-
-This means that the most specific module directories
-("closest" to your executable) will be picked up first.
-
-If you have a version of Frobnicate.pm in your ./package/lib
-for modifications fine: you'll use it before the one in
-./project or ./sandbox.
-
-Using the "p5lib" argument can help in case where some of
-the code lives outside of the sandbox. To test a sandbox
-version of some other module:
-
- use FindBin::libs qw( p5lib );
-
-and
-
- $ PERL5LIB=/other/sandbox/module foobar;
-
-=item Regression Testing
-
-Everntually, however, you'll need to regression test
-Frobnicate.pm with other modules.
-
-Fine: move, copy, or symlink it into ./project/lib and
-you can merrily run ./project/*/bin/* with it and see
-if there are any problems. In fact, so can the nice
-folks in QC.
-
-If you want to install and test a new module just
-prefix it into, say, ./sandbox/lib and all the code
-that has FindBin::libs will simply use it first.
-
-=item Testing with Symlinks
-
-$FindBin::Bin is relative to where an executable is started from.
-This allows a symlink to change the location of directories used
-by FindBin::libs. Full regression testing of an executable can be
-accomplished with a symlink:
-
- ./sandbox
- ./lib -> /homegrown/dir/lib
- ./lib/What/Ever.pm
-
- ./pre-change
- ./bin/foobar
-
- ./post-change
- ./lib/What/Ever.pm
- ./bin/foobar -> ../../pre-last-change/bin/foobar
-
-Running foobar symlinked into the post-change directory will
-test it with whatever collection of modules is in the post-change
-directory. A large regression test on some collection of
-changed modules can be performed with a few symlinks into a
-sandbox area.
-
-=item Managing Configuration and Meta-data Files
-
-The "base" option alters FindBin::libs standard base directory.
-This allows for a heirarchical set of metadata directories:
-
- ./sandbox
- ./meta
- ./project/
- ./meta
-
- ./project/package
- ./bin
- ./meta
-
-with
-
- use FindBin::libs qw( base=meta export );
-
- sub read_meta
- {
- my $base = shift;
-
- for my $dir ( @meta )
- {
- # open the first one and return
- ...
- }
-
- # caller gets back empty list if nothing was read.
-
- ()
- }
-
-=item using "prove" with local modules.
-
-Modules that are not intended for CPAN will not usually have
-a Makefile.PL or Build setup. This makes it harder to check
-the code via "make test". Instead of hacking a one-time
-Makefile, FindBin::libs can be used to locate modules in
-a "lib" directory adjacent to the "t: directory. The setup
-for this module would look like:
-
-
- ./t/01.t
- ./t/02.t
- ...
-
- ./lib/FindBin/libs.pm
-
-since the *.t files use FindBin::libs they can locate the
-most recent version of code without it having to be copied
-into a ./blib directory (usually via make) before being
-processed. If the module did not have a Makefile this would
-allow:
-
- prove t/*.t;
-
-to check the code.
-
-=back
-
-=head1 Notes
-
-=head2 Alternatives
-
-FindBin::libs was developed to avoid pitfalls with
-the items listed below. As of FindBin::libs-1.20,
-this is also mutli-platform, where other techniques
-may be limited to *NIX or at least less portable.
-
-=over 4
-
-=item PERL5LIBS
-
-PERL5LIB can be used to accomplish the same directory
-lookups as FindBin::libs. The problem is PERL5LIB often
-contains absolte paths and does not automatically change
-depending on where tests are run. This can leave you
-modifying a file, changing directory to see if it works
-with some other code and testing an unmodified version of
-the code via PERL5LIB. FindBin::libs avoids this by using
-$FindBin::bin to reference where the code is running from.
-
-The same is true of trying to use almost any environmental
-solution, with Perl's built in mechanism or one based on
-$ENV{ PWD } or qx( pwd ).
-
-Aside: Combining an existing PERL5LIB for
-out-of-tree lookups with the "p5lib" option
-works well for most development situations.
-
-=item use lib qw( ../../../../Lib );
-
-This works, but how many dots do you need to get all
-the working lib's into a module or #! code? Class
-distrubuted among several levels subdirectories may
-have qw( ../../../lib ) vs. qw( ../../../../lib )
-or various combinations of them. Validating these by
-hand (let alone correcting them) leaves me crosseyed
-after only a short session.
-
-=item Anchor on a fixed lib directory.
-
-Given a standard directory, it is possible to use
-something like:
-
- BEGIN
- {
- my ( $libdir ) = $0 =~ m{ ^( .+? )/SOMEDIR/ }x;
-
- eval "use lib qw( $libdir )";
- }
-
-This looks for a standard location (e.g., /path/to/Mylib)
-in the executable path (or cwd) and uses that.
-
-The main problem here is that if the anchor ever changes
-(e.g., when moving code between projects or relocating
-directories now that SVN supports it) the path often has
-to change in multiple files. The regex also may have to
-support multiple platforms, or be broken into more complicated
-File::Spec code that probably looks pretty much like what
-
- use FindBin::libs qw( base=Mylib )
-
-does anyway.
-
-=back
-
-=head2 FindBin::libs-1.2+ uses File::Spec
-
-In order to accmodate a wider range of filesystems,
-the code has been re-written to use File::Spec for
-all directory and volume manglement.
-
-There is one thing that File::Spec does not handle,
-hoever, which is fully reolving absolute paths. That
-still has to be handled via abs_path, when it works.
-
-The issue is that File::Spec::rel2abs and
-Cwd::abs_path work differently: abs_path only
-returns true for existing directories and
-resolves symlinks; rel2abs simply prepends cwd()
-to any non-absolute paths.
-
-The difference for FinBin::libs is that
-including redundant directories can lead to
-unexpected results in what gets included;
-looking up the contents of heavily-symlinked
-paths is slow (and has some -- admittedly
-unlikely -- failures at runtime). So, abs_path()
-is the preferred way to find where the lib's
-really live after they are found looking up the
-tree. Using abs_path() also avoids problems
-where the same directory is included twice in a
-sandbox' tree via symlinks.
-
-Due to previous complaints that abs_path did not
-work properly on all systems, the current
-version of FindBin::libs uses File::Spec to
-break apart and re-assemble directories, with
-abs_path used optinally. If "abs_path cwd" works
-then abs_path is used on the directory paths
-handed by File::Spec::catpath(); otherwise the
-paths are used as-is. This may leave users on
-systms with non-working abs_path() having extra
-copies of external library directories in @INC.
-
-Another issue is that I've heard reports of
-some systems failing the '-d' test on symlinks,
-where '-e' would have succeded.
-
-=head1 See Also
-
-=over 4
-
-=item File::Spec
-
-This is used for portability in dis- and re-assembling
-directory paths based on $FindBin::Bin.
-
-=item Older code.
-
-FindBin::libs_5_8.pm is installed if $^V indicates
-that the running perl is prior to v5.10.
-
-=back
-
-=head1 BUGS
-
-=over 4
-
-=item
-
-In order to avoid including junk, FindBin::libs
-uses '-d' to test the items before including
-them on the library list. This works fine so
-long as abs_path() is used to disambiguate any
-symlinks first. If abs_path() is turned off
-then legitimate directories may be left off in
-whatever local conditions might cause a valid
-symlink to fail the '-d' test."
-
-=item
-
-File::Spec 3.16 and prior have a bug in VMS of
-not returning an absolute paths in splitdir for
-dir's without a leading '.'. Fix for this is to
-unshift '', @dirpath if $dirpath[0]. While not a
-bug, this is obviously a somewhat kludgy workaround
-and should be removed (with an added test for a
-working version) once the File::Spec is fixed.
-
-=item
-
-The hack for prior-to-5.12 versions of perl is
-messy, but is the only I've found that works for
-the moment on *NIX, VMS, and MSW. I am not sure
-whether any of these systems are normally configured
-to share perl modules between versions. If the
-moduels are not shared on multiple platforms then
-I can make this work by managing the installation
-rather than checking this every time at startup.
-
-For the moment, at least, this seems to work.
-
-=back
-
-=head1 AUTHOR
-
-Steven Lembark, Workhorse Computing <lembark@wrkhors.com>
-
-=head1 COPYRIGHT
-
-Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
-This code is released under the same terms as Perl-5.10
-or any later version of Perl.
@@ -0,0 +1,995 @@
+########################################################################
+# FindBin::libs_curr
+#
+# use $FindBin::Bin to search for 'lib' directories and use them.
+#
+# default action is to look for dir's named "lib" and silently use
+# the lib's without exporting anything. print turns on a short
+# message with the abs_path results, export pushes out a variable
+# (default name is the base value), verbose turns on decision output
+# and print. export takes an optional argument with the name of a
+# variable to export.
+#
+#
+########################################################################
+
+########################################################################
+# housekeeping
+########################################################################
+
+package FindBin::libs;
+
+use v5.10;
+use strict;
+
+use FindBin;
+use Symbol;
+
+use File::Basename;
+
+use Carp qw( croak );
+use Symbol qw( qualify_to_ref );
+
+use File::Spec::Functions
+qw
+(
+ &splitpath
+ &splitdir
+ &catpath
+ &catdir
+);
+
+BEGIN
+{
+ # however... there have been complaints of
+ # places where abs_path does not work.
+ #
+ # if abs_path fails on the working directory
+ # then replace it with rel2abs and live with
+ # possibly slower, redundant directories.
+ #
+ # the abs_path '//' hack allows for testing
+ # broken abs_path on primitive systems that
+ # cannot handle the rooted system being linked
+ # back to itself.
+
+ use Cwd qw( &abs_path &cwd );
+
+ unless( eval {abs_path '//'; abs_path cwd } )
+ {
+ # abs_path seems to be having problems,
+ # fix is to stub it out.
+ #
+ # undef avoids nastygram.
+
+ my $ref = qualify_to_ref 'abs_path', __PACKAGE__;
+
+ my $sub = File::Spec::Functions->can( 'rel2abs' );
+
+ undef &{ $ref };
+
+ *$ref = $sub
+ };
+}
+
+########################################################################
+# package variables
+########################################################################
+
+our $VERSION = '2.09';
+$VERSION = eval $VERSION;
+
+my %defaultz =
+(
+ base => 'lib',
+ use => undef,
+ blib => undef, # prefer ./blib at the first level
+
+ subdir => '', # add this subdir also if found.
+ subonly => undef, # leave out lib's, use only subdir.
+ export => undef, # push variable into caller's space.
+ verbose => undef, # boolean: print inputs, results.
+ debug => undef, # boolean: set internal breakpoints.
+
+ print => 1, # display the results
+
+ p5lib => undef, # prefix PERL5LIB with the results
+
+ ignore => '/,/usr', # dir's to skip looking for ./lib
+);
+
+# only new directories are used, ignore pre-loads
+# this with unwanted values.
+
+my %found = ();
+
+# saves passing this between import and $handle_args.
+
+my %argz = ();
+my $verbose = '';
+my $empty = q{};
+
+########################################################################
+# subroutines
+########################################################################
+
+# HAK ALERT: $Bin is an absolute path, there are cases
+# where splitdir does not add the leading '' onto the
+# directory path for it on VMS. Fix is to unshift a leading
+# '' into @dirpath where the leading entry is true.
+
+my $find_libs
+= sub
+{
+ my $base = basename ( shift || $argz{ base } );
+
+ my $subdir = $argz{ subdir } || '';
+
+ my $subonly = defined $argz{ subonly };
+
+ # for some reason, RH Enterprise V/4 has a
+ # trailing '/'; I havn't seen another copy of
+ # FindBin that does this. fix is quick enough:
+ # strip the trailing '/'.
+ #
+ # using a regex to extract the value untaints it
+ # (not useful for anything much, just helps the
+ # poor slobs stuck in taint mode).
+ #
+ # after that splitpath can grab the directory
+ # portion for future use.
+
+ my ( $Bin ) = ( $argz{ Bin } =~ m{^ (.+) }xs );
+
+ print STDERR "\nSearching $Bin for '$base'...\n"
+ if $verbose;
+
+ my( $vol, $dir ) = splitpath $Bin, 1;
+
+ my @dirpath = splitdir $dir;
+
+ # fix for File::Spec::VMS missing the leading empty
+ # string on a split. this can be removed once File::Spec
+ # is fixed.
+
+ unshift @dirpath, '' if $dirpath[ 0 ];
+
+ my @libz = ();
+
+ PATH:
+ for( 1 .. @dirpath )
+ {
+ # note that catpath is extraneous on *NIX; the
+ # volume only means something on DOS- & VMS-based
+ # filesystems, and adding an empty basename on
+ # *nix is unnecessary.
+ #
+ # HAK ALERT: the poor slobs stuck on windog have an
+ # abs_path that croaks on missing directories. have
+ # to eval the check for subdir's.
+
+ my $abs
+ = eval
+ {
+ abs_path
+ catpath $vol, ( catdir @dirpath, $base ), $empty
+ }
+ || '';
+
+ my $sub
+ = $subdir
+ ? eval { abs_path ( catpath '', $abs, $subdir ) } || ''
+ : ''
+ ;
+
+ my @search = $subonly ? ( $sub ) : ( $abs, $sub );
+
+ for my $dir ( @search )
+ {
+ if( $dir && -d $dir && ! exists $found{ $dir } )
+ {
+ $found{ $dir } = ();
+
+ push @libz, $dir;
+
+ last if $argz{ scalar };
+ }
+ }
+
+ pop @dirpath
+ }
+
+ # caller gets back the existing lib paths
+ # (including volume) walking up the path
+ # from $FindBin::Bin -> root.
+ #
+ # passing it back as a list isn't all that
+ # painful for a few paths.
+
+ wantarray ? @libz : \@libz
+};
+
+# break out the messy part into a separate block.
+
+my $handle_args
+= sub
+{
+ # discard the module, rest are arguments.
+
+ shift;
+
+ # anything after the module are options with arguments
+ # assigned via '='.
+
+ %argz
+ = map
+ {
+ my $use_undef
+ = do
+ {
+ my %a = ();
+ @a{ qw( export ignore ) } = ();
+ \%a
+ };
+
+ my ( $k, $v ) = split '=', $_, 2;
+
+ # leave $v undef?
+
+ exists $use_undef->{ $k }
+ or $v //= 1;
+
+ # "no" inverts the sense of the test.
+
+ $k =~ s{^no}{}
+ and $v = ! $v;
+
+ ( $k => $v )
+ }
+ @_;
+
+ # stuff "debug=1" into your arguments and perl -d will stop here.
+
+ $DB::single = 1 if defined $argz{ debug };
+
+ # default if nothing is supplied is to use the result;
+ # otherwise, without use supplied either of export or
+ # p5lib will turn off use.
+
+ if( exists $argz{ use } )
+ {
+ # nothing further to do
+ }
+ elsif( defined $argz{ export } || defined $argz{ p5lib } )
+ {
+ $argz{ use } = undef;
+ }
+ else
+ {
+ $argz{ use } = 1;
+ }
+
+ local $defaultz{ Bin }
+ = exists $argz{ realbin }
+ ? $FindBin::RealBin
+ : $FindBin::Bin
+ ;
+
+ # now apply the defaults, then sanity check the result.
+ # base is a special case since it always has to exist.
+ #
+ # if $argz{ export } is defined but false then it takes
+ # its default from $argz{ base }.
+
+ while( my($k,$v) = each %defaultz )
+ {
+ # //= doesn't work here since undef may be a
+ # legit default.
+
+ exists $argz{ $k }
+ or
+ $argz{ $k } = $v;
+ }
+
+ exists $argz{ base } && $argz{ base }
+ or croak "Bogus FindBin::libs: missing/false base argument, should be 'base=NAME'";
+
+ exists $argz{ export }
+ and
+ $argz{ export } //= $argz{ base };
+
+ $argz{ ignore } =
+ [
+ grep { $_ } split /\s*,\s*/, $argz{ ignore }
+ ];
+
+ $verbose = defined $argz{ verbose };
+
+ my $base = $argz{ base };
+
+ # now locate the libraries.
+ #
+ # %found contains the abs_path results for each directory to
+ # avoid double-including directories.
+ #
+ # note: loop short-curcuts for the (usually) list.
+
+ %found = ();
+
+ for( @{ $argz{ ignore } } )
+ {
+ if( my $dir = eval { abs_path catdir $_, $base } )
+ {
+ if( -d $dir )
+ {
+ $found{ $dir } = 1;
+ }
+ }
+ }
+};
+
+sub import
+{
+ &$handle_args;
+
+ my @libz = $find_libs->();
+
+ # HAK ALERT: the regex does nothing for security,
+ # just dodges -T. putting this down here instead
+ # of inside find_libs allows people to use saner
+ # untainting plans via find_libs.
+
+ @libz = map { m{ (.+) }xs } @libz;
+
+ my $caller = caller;
+
+ if( $verbose || defined $argz{ print } )
+ {
+ local $\ = "\n";
+ local $, = "\n\t";
+
+ print STDERR "Found */$argz{ base }:", @libz
+ if $verbose;
+ }
+
+ if( $argz{ export } )
+ {
+ my $ref = qualify_to_ref $argz{ export }, $caller;
+
+ if( $verbose )
+ {
+ my $dest = qualify $argz{ export }, $caller;
+
+ $argz{ scalar }
+ ? print STDERR "\nExporting: \$$dest\n"
+ : print STDERR "\nExporting: \@$dest\n"
+ ;
+ }
+
+ $argz{ scalar }
+ ? *$ref = \$libz[0]
+ : *$ref = \@libz;
+ ;
+ }
+
+ if( defined $argz{ p5lib } )
+ {
+ # stuff the lib's found at the front of $ENV{ PERL5LIB }
+
+ ( substr $ENV{ PERL5LIB }, 0, 0 ) = join ':', @libz, ''
+ if @libz;
+
+ print STDERR "\nUpdated PERL5LIB:\t$ENV{ PERL5LIB }\n"
+ if $verbose;
+ }
+
+ if( $argz{ use } && @libz )
+ {
+ # this obviously won't work if lib ever depends
+ # on the caller's package.
+ #
+ # it does avoids issues with -T blowing up on the
+ # old eval technique.
+
+ require lib;
+
+ lib->import( @libz );
+ }
+
+ 0
+}
+
+# keep require happy
+
+1
+
+__END__
+
+=head1 NAME
+
+FindBin::libs - locate and a 'use lib' or export
+directories based on $FindBin::Bin.
+
+=head1 SYNOPSIS
+
+This version of FindBin::libs is suitable for
+Perl v5.10+.
+
+ # search up $FindBin::Bin looking for ./lib directories
+ # and "use lib" them.
+
+ use FindBin::libs;
+
+ # same as above with explicit defaults.
+
+ use FindBin::libs qw( base=lib use=1 noexport noprint );
+
+ # print the lib dir's before using them.
+
+ use FindBin::libs qw( print );
+
+ # find and use lib "altlib" dir's
+
+ use FindBin::libs qw( base=altlib );
+
+ # move starting point from $FindBin::Bin to '/tmp'
+
+ use FindBin::libs qw( Bin=/tmp base=altlib );
+
+ # skip "use lib", export "@altlib" instead.
+
+ use FindBin::libs qw( base=altlib export );
+
+ # find altlib directories, use lib them and export @mylibs
+
+ use FindBin::libs qw( base=altlib export=mylibs use );
+
+ # "export" defaults to "nouse", these two are identical:
+
+ use FindBin::libs qw( export nouse );
+ use FindBin::libs qw( export );
+
+ # use and export are not exclusive:
+
+ use FindBin::libs qw( use export ); # do both
+ use FindBin::libs qw( nouse noexport print ); # print only
+ use FindBin::libs qw( nouse noexport ); # do nothting at all
+
+ # print a few interesting messages about the
+ # items found.
+
+ use FindBinlibs qw( verbose );
+
+ # turn on a breakpoint after the args are prcoessed, before
+ # any search/export/use lib is handled.
+
+ use FindBin::libs qw( debug );
+
+ # prefix PERL5LIB with the lib's found.
+
+ use FindBin::libs qw( perl5lib );
+
+ # find a subdir of the lib's looked for.
+ # the first example will use both ../lib and
+ # ../lib/perl5; the second ../lib/perl5/frobnicate
+ # (if they exist). it can also be used with export
+ # and base to locate special configuration dir's.
+ #
+ # subonly with a base is useful for locating config
+ # files. this finds any "./config/mypackage" dir's
+ # without including any ./config dir's. the result
+ # ends up in @config (see also "export=", above).
+
+ use FindBin::libs qw( subdir=perl5 );
+
+ use FindBin::libs qw( subdir=perl5/frobnicate );
+
+ use FindBin::libs qw( base=config subdir=mypackage subonly export );
+
+ # base and subonly are also useful if your
+ # project is stored in multiple git
+ # repositories.
+ #
+ # say you need libs under api_foo/lib from api_bar: a
+ # base of the git repository directory with subdir of
+ # lib and subonly will pull in those lib dirs.
+
+ use FindBin::libs qw( base=api_foo subdir=lib subonly );
+
+ # no harm in using this multiple times to use
+ # or export multple layers of libs.
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( export=found base=lib );
+ use FindBin::libs qw( export=binz base=bin ignore=/foo,/bar );
+ use FindBin::libs qw( export=junk base=frobnicatorium );
+ use FindBin::libs qw( export base=foobar );
+
+=head1 DESCRIPTION
+
+=head2 General Use
+
+This module will locate directories along the path to $FindBin::Bin
+and "use lib" or export an array of the directories found. The default
+is to locate "lib" directories and "use lib" them without printing
+the list.
+
+Options controll whether the lib's found are exported into the caller's
+space, exported to PERL5LIB, or printed. Exporting or setting perl5lib
+will turn off the default of "use lib" so that:
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( p5lib );
+
+are equivalent to
+
+ use FindBin::libs qw( export nouse );
+ use FindBin::libs qw( p5lib nouse );
+
+Combining export with use or p5lib may be useful, p5lib and
+use are probably not all that useful together.
+
+=head3 Alternate directory name: 'base'
+
+The basename searched for can be changed via 'base=name' so
+that
+
+ use FindBin::libs qw( base=altlib );
+
+will search for directories named "altlib" and "use lib" them.
+
+=head3 Exporting a variable: 'export'
+
+The 'export' option will push an array of the directories found
+and takes an optional argument of the array name, which defaults
+to the basename searched for:
+
+ use FindBin::libs qw( export );
+
+will find "lib" directories and export @lib with the
+list of directories found.
+
+ use FindBin::libs qw( export=mylibs );
+
+will find "lib" directories and export them as "@mylibs" to
+the caller.
+
+If "export" only is given then the "use" option defaults to
+false. So:
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( export nouse );
+
+are equivalent. This is mainly for use when looking for data
+directories with the "base=" argument.
+
+If base is used with export the default array name is the base
+directory value:
+
+ use FindBin::libs qw( export base=meta );
+
+exports @meta while
+
+ use FindBin::libs qw( export=metadirs base=meta );
+
+exports @metadirs.
+
+The use and export switches are not exclusive:
+
+ use FindBin::libs qw( use export=mylibs );
+
+will locate "lib" directories, use lib them, and export
+@mylibs into the caller's package.
+
+=head3 Subdirectories
+
+The "subdir" and "subonly" settings will add or
+exclusively use subdir's. This is useful if some
+of your lib's are in ../lib/perl5 along with
+../lib (subdir=perl5) or all of the lib's are
+in ../lib/perl5 (subonly=perl5).
+
+This can also be handy for locating subdir's used
+for configuring packages:
+
+ use FindBin::libs qw( export base=config subonly=mypackage );
+
+Will leave @config with any "mypacakge" holding
+any "mypackage" subdir's.
+
+=head3 Setting PERL5LIB: p5lib
+
+For cases where the environment is more useful for setting
+up library paths "p5lib" can be used to preload this variable.
+This is mainly useful for automatically including directories
+outside of the parent tree of $FindBin::bin.
+
+For example, using:
+
+ $ export PERL5LIB="/usr/local/foo:/usr/local/bar";
+
+ $ myprog;
+
+or simply
+
+ $ PERL5LIB="/usr/local/lib/foo:/usr/lib/bar" myprog;
+
+(depending on your shell) with #! code including:
+
+ use FindBin::libs qw( p5lib );
+
+will not "use lib" any dir's found but will update PERL5LIB
+to something like:
+
+ /home/me/sandbox/branches/lib:/usr/local/lib/foo:/usr/lib/bar
+
+This can make controlling the paths used simpler and avoid
+the use of symlinks for some testing (see examples below).
+
+Note that "p5lib" and "nouse" are proably worth
+
+=head2 Skipping directories
+
+By default, lib directories under / and /usr are
+sliently ignored. This normally means that /lib, /usr/lib, and
+'/usr/local/lib' are skipped. The "ignore" parameter provides
+a comma-separated list of directories to ignore:
+
+ use FindBin::libs qw( ignore=/skip/this,/and/this/also );
+
+will replace the standard list and thus skip "/skip/this/lib"
+and "/and/this/also/lib". It will search "/lib" and "/usr/lib"
+since the argument ignore list replaces the original one.
+
+=head2 Homegrown Library Management
+
+An all-too-common occurrance managing perly projects is
+being unable to install new modules becuse "it might
+break things", and being unable to test them because
+you can't install them. The usual outcome of this is a
+collection of hard-coded
+
+ use lib qw( /usr/local/projectX ... )
+
+code at the top of each #! file that has to be updated by
+hand for each new project.
+
+To get away from this you'll often see relative paths
+for the lib's, which require running the code from one
+specific place. All this does is push the hard-coding
+into cron, shell wrappers, and begin blocks.
+
+With FindBin::libs you need suffer no more.
+
+Automatically finding libraries in and above the executable
+means you can put your modules into cvs/svn and check them
+out with the project, have multiple copies shared by developers,
+or easily move a module up the directory tree in a testbed
+to regression test the module with existing code. All without
+having to modify a single line of code.
+
+=over 4
+
+=item Code-speicfic modules.
+
+Say your sandbox is in ./sandbox and you are currently
+working in ./sandbox/projects/package/bin on a perl
+executable. You may have some number of modules that
+are specific -- or customized -- for this pacakge,
+share some modules within the project, and may want
+to use company-wide modules that are managed out of
+./sandbox in development. All of this lives under a
+./qc tree on the test boxes and under ./production
+on production servers.
+
+For simplicity, say that your sandbox lives in your
+home direcotry, /home/jowbloe, as a directory or a
+symlink.
+
+If your #! uses FindBin::libs in it then it will
+effectively
+
+ use lib
+ qw(
+ /home/jowbloe/sandbox/lib
+ /home/jowbloe/sandbox/project/lib
+ /home/jowbloe/sandbox/project/package/lib
+ );
+
+if you run /home/jowbloe/sandbox/project/package/bin/foobar.
+This will happen the same way if you use a relative or
+absolute path, perl -d the thing, or if any of the lib
+directories are symlinks outside of your sandbox.
+
+This means that the most specific module directories
+("closest" to your executable) will be picked up first.
+
+If you have a version of Frobnicate.pm in your ./package/lib
+for modifications fine: you'll use it before the one in
+./project or ./sandbox.
+
+Using the "p5lib" argument can help in case where some of
+the code lives outside of the sandbox. To test a sandbox
+version of some other module:
+
+ use FindBin::libs qw( p5lib );
+
+and
+
+ $ PERL5LIB=/other/sandbox/module foobar;
+
+=item Regression Testing
+
+Everntually, however, you'll need to regression test
+Frobnicate.pm with other modules.
+
+Fine: move, copy, or symlink it into ./project/lib and
+you can merrily run ./project/*/bin/* with it and see
+if there are any problems. In fact, so can the nice
+folks in QC.
+
+If you want to install and test a new module just
+prefix it into, say, ./sandbox/lib and all the code
+that has FindBin::libs will simply use it first.
+
+=item Testing with Symlinks
+
+$FindBin::Bin is relative to where an executable is started from.
+This allows a symlink to change the location of directories used
+by FindBin::libs. Full regression testing of an executable can be
+accomplished with a symlink:
+
+ ./sandbox
+ ./lib -> /homegrown/dir/lib
+ ./lib/What/Ever.pm
+
+ ./pre-change
+ ./bin/foobar
+
+ ./post-change
+ ./lib/What/Ever.pm
+ ./bin/foobar -> ../../pre-last-change/bin/foobar
+
+Running foobar symlinked into the post-change directory will
+test it with whatever collection of modules is in the post-change
+directory. A large regression test on some collection of
+changed modules can be performed with a few symlinks into a
+sandbox area.
+
+=item Managing Configuration and Meta-data Files
+
+The "base" option alters FindBin::libs standard base directory.
+This allows for a heirarchical set of metadata directories:
+
+ ./sandbox
+ ./meta
+ ./project/
+ ./meta
+
+ ./project/package
+ ./bin
+ ./meta
+
+with
+
+ use FindBin::libs qw( base=meta export );
+
+ sub read_meta
+ {
+ my $base = shift;
+
+ for my $dir ( @meta )
+ {
+ # open the first one and return
+ ...
+ }
+
+ # caller gets back empty list if nothing was read.
+
+ ()
+ }
+
+=item using "prove" with local modules.
+
+Modules that are not intended for CPAN will not usually have
+a Makefile.PL or Build setup. This makes it harder to check
+the code via "make test". Instead of hacking a one-time
+Makefile, FindBin::libs can be used to locate modules in
+a "lib" directory adjacent to the "t: directory. The setup
+for this module would look like:
+
+
+ ./t/01.t
+ ./t/02.t
+ ...
+
+ ./lib/FindBin/libs.pm
+
+since the *.t files use FindBin::libs they can locate the
+most recent version of code without it having to be copied
+into a ./blib directory (usually via make) before being
+processed. If the module did not have a Makefile this would
+allow:
+
+ prove t/*.t;
+
+to check the code.
+
+=back
+
+=head1 Notes
+
+=head2 Alternatives
+
+FindBin::libs was developed to avoid pitfalls with
+the items listed below. As of FindBin::libs-1.20,
+this is also mutli-platform, where other techniques
+may be limited to *NIX or at least less portable.
+
+=over 4
+
+=item PERL5LIBS
+
+PERL5LIB can be used to accomplish the same directory
+lookups as FindBin::libs. The problem is PERL5LIB often
+contains absolte paths and does not automatically change
+depending on where tests are run. This can leave you
+modifying a file, changing directory to see if it works
+with some other code and testing an unmodified version of
+the code via PERL5LIB. FindBin::libs avoids this by using
+$FindBin::bin to reference where the code is running from.
+
+The same is true of trying to use almost any environmental
+solution, with Perl's built in mechanism or one based on
+$ENV{ PWD } or qx( pwd ).
+
+Aside: Combining an existing PERL5LIB for
+out-of-tree lookups with the "p5lib" option
+works well for most development situations.
+
+=item use lib qw( ../../../../Lib );
+
+This works, but how many dots do you need to get all
+the working lib's into a module or #! code? Class
+distrubuted among several levels subdirectories may
+have qw( ../../../lib ) vs. qw( ../../../../lib )
+or various combinations of them. Validating these by
+hand (let alone correcting them) leaves me crosseyed
+after only a short session.
+
+=item Anchor on a fixed lib directory.
+
+Given a standard directory, it is possible to use
+something like:
+
+ BEGIN
+ {
+ my ( $libdir ) = $0 =~ m{ ^( .+? )/SOMEDIR/ }x;
+
+ eval "use lib qw( $libdir )";
+ }
+
+This looks for a standard location (e.g., /path/to/Mylib)
+in the executable path (or cwd) and uses that.
+
+The main problem here is that if the anchor ever changes
+(e.g., when moving code between projects or relocating
+directories now that SVN supports it) the path often has
+to change in multiple files. The regex also may have to
+support multiple platforms, or be broken into more complicated
+File::Spec code that probably looks pretty much like what
+
+ use FindBin::libs qw( base=Mylib )
+
+does anyway.
+
+=back
+
+=head2 FindBin::libs-1.2+ uses File::Spec
+
+In order to accmodate a wider range of filesystems,
+the code has been re-written to use File::Spec for
+all directory and volume manglement.
+
+There is one thing that File::Spec does not handle,
+hoever, which is fully reolving absolute paths. That
+still has to be handled via abs_path, when it works.
+
+The issue is that File::Spec::rel2abs and
+Cwd::abs_path work differently: abs_path only
+returns true for existing directories and
+resolves symlinks; rel2abs simply prepends cwd()
+to any non-absolute paths.
+
+The difference for FinBin::libs is that
+including redundant directories can lead to
+unexpected results in what gets included;
+looking up the contents of heavily-symlinked
+paths is slow (and has some -- admittedly
+unlikely -- failures at runtime). So, abs_path()
+is the preferred way to find where the lib's
+really live after they are found looking up the
+tree. Using abs_path() also avoids problems
+where the same directory is included twice in a
+sandbox' tree via symlinks.
+
+Due to previous complaints that abs_path did not
+work properly on all systems, the current
+version of FindBin::libs uses File::Spec to
+break apart and re-assemble directories, with
+abs_path used optinally. If "abs_path cwd" works
+then abs_path is used on the directory paths
+handed by File::Spec::catpath(); otherwise the
+paths are used as-is. This may leave users on
+systms with non-working abs_path() having extra
+copies of external library directories in @INC.
+
+Another issue is that I've heard reports of
+some systems failing the '-d' test on symlinks,
+where '-e' would have succeded.
+
+=head1 See Also
+
+=over 4
+
+=item File::Spec
+
+This is used for portability in dis- and re-assembling
+directory paths based on $FindBin::Bin.
+
+=item Older code.
+
+FindBin::libs_5_8.pm is installed if $^V indicates
+that the running perl is prior to v5.10.
+
+=back
+
+=head1 BUGS
+
+=over 4
+
+=item
+
+In order to avoid including junk, FindBin::libs
+uses '-d' to test the items before including
+them on the library list. This works fine so
+long as abs_path() is used to disambiguate any
+symlinks first. If abs_path() is turned off
+then legitimate directories may be left off in
+whatever local conditions might cause a valid
+symlink to fail the '-d' test."
+
+=item
+
+File::Spec 3.16 and prior have a bug in VMS of
+not returning an absolute paths in splitdir for
+dir's without a leading '.'. Fix for this is to
+unshift '', @dirpath if $dirpath[0]. While not a
+bug, this is obviously a somewhat kludgy workaround
+and should be removed (with an added test for a
+working version) once the File::Spec is fixed.
+
+=item
+
+The hack for prior-to-5.12 versions of perl is
+messy, but is the only I've found that works for
+the moment on *NIX, VMS, and MSW. I am not sure
+whether any of these systems are normally configured
+to share perl modules between versions. If the
+moduels are not shared on multiple platforms then
+I can make this work by managing the installation
+rather than checking this every time at startup.
+
+For the moment, at least, this seems to work.
+
+=back
+
+=head1 AUTHOR
+
+Steven Lembark, Workhorse Computing <lembark@wrkhors.com>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
+This code is released under the same terms as Perl-5.10
+or any later version of Perl.
@@ -0,0 +1,978 @@
+########################################################################
+# FindBin::libs
+#
+# use $FindBin::Bin to search for 'lib' directories and use them.
+#
+# default action is to look for dir's named "lib" and silently use
+# the lib's without exporting anything. print turns on a short
+# message with the abs_path results, export pushes out a variable
+# (default name is the base value), verbose turns on decision output
+# and print. export takes an optional argument with the name of a
+# variable to export.
+#
+# Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
+# This code is released under the same terms as Perl-5.8
+# or any later version of Perl.
+#
+########################################################################
+
+########################################################################
+# housekeeping
+########################################################################
+
+package # hak to avoid indexing the extra module
+FindBin::libs;
+
+use v5.8;
+use strict;
+
+use FindBin;
+use Symbol;
+
+use File::Basename;
+
+use Carp qw( croak );
+use Symbol qw( qualify_to_ref );
+
+use File::Spec::Functions
+qw
+(
+ &splitpath
+ &splitdir
+ &catpath
+ &catdir
+);
+
+BEGIN
+{
+ # however... there have been complaints of
+ # places where abs_path does not work.
+ #
+ # if abs_path fails on the working directory
+ # then replace it with rel2abs and live with
+ # possibly slower, redundant directories.
+ #
+ # the abs_path '//' hack allows for testing
+ # broken abs_path on primitive systems that
+ # cannot handle the rooted system being linked
+ # back to itself.
+
+ use Cwd qw( &cwd );
+
+ my $abs = Cwd->can( 'abs_path' )
+ or die "Odd: Cwd cannot 'abs_path'\n";
+
+ if
+ (
+ eval { $abs->( '//' ); $abs->( cwd ); 1 }
+ )
+ {
+ # nothing more to do: abs_path works.
+ }
+ elsif
+ (
+ $abs = File::Spec::Functions->can( 'rel2abs' )
+ )
+ {
+ # ok, we have a substitute
+ }
+ else
+ {
+ die "Cwd fails abs_path test && lacks 'rel2abs'\n";
+ }
+
+ my $ref = *{ qualify_to_ref 'abs_path', __PACKAGE__ };
+
+ undef &{ *$ref };
+
+ *{ $ref } = $abs;
+}
+
+########################################################################
+# package variables
+########################################################################
+
+our $VERSION = v1.63;
+
+my %defaultz =
+(
+ base => 'lib',
+ use => undef,
+
+ subdir => '', # add this subdir also if found.
+ subonly => undef, # leave out lib's, use only subdir.
+ export => undef, # push variable into caller's space.
+ verbose => undef, # boolean: print inputs, results.
+ debug => undef, # boolean: set internal breakpoints.
+
+ print => undef, # display the results
+
+ p5lib => undef, # prefix PERL5LIB with the results
+
+ ignore => '/,/usr', # dir's to skip looking for ./lib
+);
+
+# only new directories are used, ignore pre-loads
+# this with unwanted values.
+
+my %found = ();
+
+# saves passing this between import and $handle_args.
+
+my %argz = ();
+my $verbose = '';
+my $empty = q{};
+
+########################################################################
+# subroutines
+########################################################################
+
+# HAK ALERT: $Bin is an absolute path, there are cases
+# where splitdir does not add the leading '' onto the
+# directory path for it on VMS. Fix is to unshift a leading
+# '' into @dirpath where the leading entry is true.
+
+my $find_libs
+= sub
+{
+ my $base = basename ( shift || $argz{ base } );
+
+ my $subdir = $argz{ subdir } || '';
+
+ my $subonly = defined $argz{ subonly };
+
+ # for some reason, RH Enterprise V/4 has a
+ # trailing '/'; I havn't seen another copy of
+ # FindBin that does this. fix is quick enough:
+ # strip the trailing '/'.
+ #
+ # using a regex to extract the value untaints it
+ # (not useful for anything much, just helps the
+ # poor slobs stuck in taint mode).
+ #
+ # after that splitpath can grab the directory
+ # portion for future use.
+
+ my ( $Bin ) = $argz{ Bin } =~ m{^ (.+) }xs;
+
+ print STDERR "\nSearching $Bin for '$base'...\n"
+ if $verbose;
+
+ my( $vol, $dir ) = splitpath $Bin, 1;
+
+ my @dirpath = splitdir $dir;
+
+ # fix for File::Spec::VMS missing the leading empty
+ # string on a split. this can be removed once File::Spec
+ # is fixed.
+
+ unshift @dirpath, '' if $dirpath[ 0 ];
+
+ my @libz = ();
+
+ for( 1 .. @dirpath )
+ {
+ # note that catpath is extraneous on *NIX; the
+ # volume only means something on DOS- & VMS-based
+ # filesystems, and adding an empty basename on
+ # *nix is unnecessary.
+ #
+ # HAK ALERT: the poor slobs stuck on windog have an
+ # abs_path that croaks on missing directories. have
+ # to eval the check for subdir's.
+
+ my $abs
+ = eval { abs_path catpath $vol, ( catdir @dirpath, $base ), $empty }
+ || '';
+
+ my $sub
+ = $subdir
+ ? eval { abs_path ( catpath '', $abs, $subdir ) } || ''
+ : ''
+ ;
+
+ my @search = $subonly ? ( $sub ) : ( $abs, $sub );
+
+ for my $dir ( @search )
+ {
+ if( $dir && -d $dir && ! exists $found{ $dir } )
+ {
+ $found{ $dir } = 1;
+
+ push @libz, $dir;
+
+ last if $argz{ scalar };
+ }
+ }
+
+ pop @dirpath
+ }
+
+ # caller gets back the existing lib paths
+ # (including volume) walking up the path
+ # from $FindBin::Bin -> root.
+ #
+ # passing it back as a list isn't all that
+ # painful for a few paths.
+
+ wantarray ? @libz : \@libz
+};
+
+# break out the messy part into a separate block.
+
+my $handle_args
+= sub
+{
+ # discard the module, rest are arguments.
+
+ shift;
+
+ # anything after the module are options with arguments
+ # assigned via '='.
+
+ %argz
+ = map
+ {
+ my ( $k, $v ) = split '=', $_, 2;
+
+ $k =~ s{^ (?:!|no) }{}x
+ ? ( $k => undef )
+ : ( $k => ( $v || '' ) )
+ }
+ @_;
+
+ # stuff "debug=1" into your arguments and perl -d will stop here.
+
+ $DB::single = 1 if defined $argz{ debug };
+
+ # default if nothing is supplied is to use the result;
+ # otherwise, without use supplied either of export or
+ # p5lib will turn off use.
+
+ if( exists $argz{ use } )
+ {
+ # nothing further to do
+ }
+ elsif( defined $argz{ export } || defined $argz{ p5lib } )
+ {
+ $argz{ use } = undef;
+ }
+ else
+ {
+ $argz{ use } = 1;
+ }
+
+ local $defaultz{ Bin }
+ = exists $argz{ realbin }
+ ? $FindBin::RealBin
+ : $FindBin::Bin
+ ;
+
+ # now apply the defaults, then sanity check the result.
+ # base is a special case since it always has to exist.
+ #
+ # if $argz{export} is defined but false then it takes
+ # its default from $argz{base}.
+
+ exists $argz{$_} or $argz{$_} = $defaultz{$_}
+ for keys %defaultz;
+
+ exists $argz{base} && $argz{base}
+ or croak "Bogus FindBin::libs: missing/false base argument, should be 'base=NAME'";
+
+ defined $argz{export} and $argz{export} ||= $argz{base};
+
+ $argz{ ignore } =
+ [
+ grep { $_ }
+ split /\s*,\s*/,
+ $argz{ignore}
+ ];
+
+ $verbose = defined $argz{verbose};
+
+ my $base = $argz{base};
+
+ # now locate the libraries.
+ #
+ # %found contains the abs_path results for each directory to
+ # avoid double-including directories.
+ #
+ # note: loop short-curcuts for the (usually) list.
+
+ %found = ();
+
+ for( @{ $argz{ ignore } } )
+ {
+ if( my $dir = eval { abs_path catdir $_, $base } )
+ {
+ if( -d $dir )
+ {
+ $found{ $dir } = 1;
+ }
+ }
+ }
+};
+
+sub import
+{
+ &$handle_args;
+
+ my @libz = $find_libs->();
+
+ # HAK ALERT: the regex does nothing for security,
+ # just dodges -T. putting this down here instead
+ # of inside find_libs allows people to use saner
+ # untainting plans via find_libs.
+
+ @libz = map { m{ (.+) }x } @libz;
+
+ my $caller = caller;
+
+ if( $verbose || defined $argz{print} )
+ {
+ local $\ = "\n";
+ local $, = "\n\t";
+
+ print STDERR "Found */$argz{ base }:", @libz
+ }
+
+ if( $argz{export} )
+ {
+ print STDERR join '', "\nExporting: @", $caller, '::', $argz{export}, "\n"
+ if $verbose;
+
+ # Symbol this is cleaner than "no strict"
+ # for installing the array.
+
+ my $ref = qualify_to_ref $argz{ export }, $caller;
+
+ exists $argz{ scalar }
+ ? *$ref = \$libz[0]
+ : *$ref = \@libz
+ ;
+ }
+
+ if( defined $argz{ p5lib } )
+ {
+ # stuff the lib's found at the front of $ENV{ PERL5LIB }
+
+ ( substr $ENV{ PERL5LIB }, 0, 0 ) = join ':', @libz, ''
+ if @libz;
+
+ print STDERR "\nUpdated PERL5LIB:\t$ENV{ PERL5LIB }\n"
+ if $verbose;
+ }
+
+ if( $argz{use} && @libz )
+ {
+ # this obviously won't work if lib ever depends
+ # on the caller's package.
+ #
+ # it does avoids issues with -T blowing up on the
+ # old eval technique.
+
+ require lib;
+
+ lib->import( @libz );
+ }
+
+ 0
+};
+
+# keep require happy
+
+1
+
+__END__
+
+=head1 NAME
+
+FindBin::libs_5_8 - stable version of code for older
+perl installations.
+
+=head1 SYNOPSIS
+
+FindBin::libs locates and performs a 'use lib' for
+directories along the path of $FindBin::Bin to automate
+locating modules. Uses File::Spec and Cwd's abs_path to
+accomodate multiple O/S and redundant symlinks.
+
+ # search up $FindBin::Bin looking for ./lib directories
+ # and "use lib" them.
+
+ use FindBin::libs;
+
+ # same as above with explicit defaults.
+
+ use FindBin::libs qw( base=lib use=1 noexport noprint );
+
+ # print the lib dir's before using them.
+
+ use FindBin::libs qw( print );
+
+ # find and use lib "altlib" dir's
+
+ use FindBin::libs qw( base=altlib );
+
+ # move starting point from $FindBin::Bin to '/tmp'
+
+ use FindBin::libs qw( Bin=/tmp base=altlib );
+
+ # skip "use lib", export "@altlib" instead.
+
+ use FindBin::libs qw( base=altlib export );
+
+ # find altlib directories, use lib them and export @mylibs
+
+ use FindBin::libs qw( base=altlib export=mylibs use );
+
+ # "export" defaults to "nouse", these two are identical:
+
+ use FindBin::libs qw( export nouse );
+ use FindBin::libs qw( export );
+
+ # use and export are not exclusive:
+
+ use FindBin::libs qw( use export ); # do both
+ use FindBin::libs qw( nouse noexport print ); # print only
+ use FindBin::libs qw( nouse noexport ); # do nothting at all
+
+ # print a few interesting messages about the
+ # items found.
+
+ use FindBinlibs qw( verbose );
+
+ # turn on a breakpoint after the args are prcoessed, before
+ # any search/export/use lib is handled.
+
+ use FindBin::libs qw( debug );
+
+ # prefix PERL5LIB with the lib's found.
+
+ use FindBin::libs qw( perl5lib );
+
+ # find a subdir of the lib's looked for.
+ # the first example will use both ../lib and
+ # ../lib/perl5; the second ../lib/perl5/frobnicate
+ # (if they exist). it can also be used with export
+ # and base to locate special configuration dir's.
+ #
+ # subonly with a base is useful for locating config
+ # files. this finds any "./config/mypackage" dir's
+ # without including any ./config dir's. the result
+ # ends up in @config (see also "export=", above).
+
+ use FindBin::libs qw( subdir=perl5 );
+
+ use FindBin::libs qw( subdir=perl5/frobnicate );
+
+ use FindBin::libs qw( base=config subdir=mypackage subonly export );
+
+ # base and subonly are also useful if your
+ # project is stored in multiple git
+ # repositories.
+ #
+ # say you need libs under api_foo/lib from api_bar: a
+ # base of the git repository directory with subdir of
+ # lib and subonly will pull in those lib dirs.
+
+ use FindBin::libs qw( base=api_foo subdir=lib subonly );
+
+ # no harm in using this multiple times to use
+ # or export multple layers of libs.
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( export=found base=lib );
+ use FindBin::libs qw( export=binz base=bin ignore=/foo,/bar );
+ use FindBin::libs qw( export=junk base=frobnicatorium );
+ use FindBin::libs qw( export base=foobar );
+
+=head1 DESCRIPTION
+
+=head2 General Use
+
+This module will locate directories along the path to $FindBin::Bin
+and "use lib" or export an array of the directories found. The default
+is to locate "lib" directories and "use lib" them without printing
+the list.
+
+Options controll whether the lib's found are exported into the caller's
+space, exported to PERL5LIB, or printed. Exporting or setting perl5lib
+will turn off the default of "use lib" so that:
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( p5lib );
+
+are equivalent to
+
+ use FindBin::libs qw( export nouse );
+ use FindBin::libs qw( p5lib nouse );
+
+Combining export with use or p5lib may be useful, p5lib and
+use are probably not all that useful together.
+
+=head3 Alternate directory name: 'base'
+
+The basename searched for can be changed via 'base=name' so
+that
+
+ use FindBin::libs qw( base=altlib );
+
+will search for directories named "altlib" and "use lib" them.
+
+=head3 Exporting a variable: 'export'
+
+The 'export' option will push an array of the directories found
+and takes an optional argument of the array name, which defaults
+to the basename searched for:
+
+ use FindBin::libs qw( export );
+
+will find "lib" directories and export @lib with the
+list of directories found.
+
+ use FindBin::libs qw( export=mylibs );
+
+will find "lib" directories and export them as "@mylibs" to
+the caller.
+
+If "export" only is given then the "use" option defaults to
+false. So:
+
+ use FindBin::libs qw( export );
+ use FindBin::libs qw( export nouse );
+
+are equivalent. This is mainly for use when looking for data
+directories with the "base=" argument.
+
+If base is used with export the default array name is the base
+directory value:
+
+ use FindBin::libs qw( export base=meta );
+
+exports @meta while
+
+ use FindBin::libs qw( export=metadirs base=meta );
+
+exports @metadirs.
+
+The use and export switches are not exclusive:
+
+ use FindBin::libs qw( use export=mylibs );
+
+will locate "lib" directories, use lib them, and export
+@mylibs into the caller's package.
+
+=head3 Subdirectories
+
+The "subdir" and "subonly" settings will add or
+exclusively use subdir's. This is useful if some
+of your lib's are in ../lib/perl5 along with
+../lib (subdir=perl5) or all of the lib's are
+in ../lib/perl5 (subonly=perl5).
+
+This can also be handy for locating subdir's used
+for configuring packages:
+
+ use FindBin::libs qw( export base=config subonly=mypackage );
+
+Will leave @config with any "mypackage" holding
+any "mypackage" subdir's.
+
+=head3 Setting PERL5LIB: p5lib
+
+For cases where the environment is more useful for setting
+up library paths "p5lib" can be used to preload this variable.
+This is mainly useful for automatically including directories
+outside of the parent tree of $FindBin::bin.
+
+For example, using:
+
+ $ export PERL5LIB="/usr/local/foo:/usr/local/bar";
+
+ $ myprog;
+
+or simply
+
+ $ PERL5LIB="/usr/local/lib/foo:/usr/lib/bar" myprog;
+
+(depending on your shell) with #! code including:
+
+ use FindBin::libs qw( p5lib );
+
+will not "use lib" any dir's found but will update PERL5LIB
+to something like:
+
+ /home/me/sandbox/branches/lib:/usr/local/lib/foo:/usr/lib/bar
+
+This can make controlling the paths used simpler and avoid
+the use of symlinks for some testing (see examples below).
+
+Note that "p5lib" and "nouse" are proably worth
+
+=head2 Skipping directories
+
+By default, lib directories under / and /usr are
+sliently ignored. This normally means that /lib, /usr/lib, and
+'/usr/local/lib' are skipped. The "ignore" parameter provides
+a comma-separated list of directories to ignore:
+
+ use FindBin::libs qw( ignore=/skip/this,/and/this/also );
+
+will replace the standard list and thus skip "/skip/this/lib"
+and "/and/this/also/lib". It will search "/lib" and "/usr/lib"
+since the argument ignore list replaces the original one.
+
+=head2 Homegrown Library Management
+
+An all-too-common occurrance managing perly projects is
+being unable to install new modules becuse "it might
+break things", and being unable to test them because
+you can't install them. The usual outcome of this is a
+collection of hard-coded
+
+ use lib qw( /usr/local/projectX ... )
+
+code at the top of each #! file that has to be updated by
+hand for each new project.
+
+To get away from this you'll often see relative paths
+for the lib's, which require running the code from one
+specific place. All this does is push the hard-coding
+into cron, shell wrappers, and begin blocks.
+
+With FindBin::libs you need suffer no more.
+
+Automatically finding libraries in and above the executable
+means you can put your modules into cvs/svn and check them
+out with the project, have multiple copies shared by developers,
+or easily move a module up the directory tree in a testbed
+to regression test the module with existing code. All without
+having to modify a single line of code.
+
+=over 4
+
+=item Code-speicfic modules.
+
+Say your sandbox is in ./sandbox and you are currently
+working in ./sandbox/projects/package/bin on a perl
+executable. You may have some number of modules that
+are specific -- or customized -- for this pacakge,
+share some modules within the project, and may want
+to use company-wide modules that are managed out of
+./sandbox in development. All of this lives under a
+./qc tree on the test boxes and under ./production
+on production servers.
+
+For simplicity, say that your sandbox lives in your
+home direcotry, /home/jowbloe, as a directory or a
+symlink.
+
+If your #! uses FindBin::libs in it then it will
+effectively
+
+ use lib
+ qw(
+ /home/jowbloe/sandbox/lib
+ /home/jowbloe/sandbox/project/lib
+ /home/jowbloe/sandbox/project/package/lib
+ );
+
+if you run /home/jowbloe/sandbox/project/package/bin/foobar.
+This will happen the same way if you use a relative or
+absolute path, perl -d the thing, or if any of the lib
+directories are symlinks outside of your sandbox.
+
+This means that the most specific module directories
+("closest" to your executable) will be picked up first.
+
+If you have a version of Frobnicate.pm in your ./package/lib
+for modifications fine: you'll use it before the one in
+./project or ./sandbox.
+
+Using the "p5lib" argument can help in case where some of
+the code lives outside of the sandbox. To test a sandbox
+version of some other module:
+
+ use FindBin::libs qw( p5lib );
+
+and
+
+ $ PERL5LIB=/other/sandbox/module foobar;
+
+=item Regression Testing
+
+Everntually, however, you'll need to regression test
+Frobnicate.pm with other modules.
+
+Fine: move, copy, or symlink it into ./project/lib and
+you can merrily run ./project/*/bin/* with it and see
+if there are any problems. In fact, so can the nice
+folks in QC.
+
+If you want to install and test a new module just
+prefix it into, say, ./sandbox/lib and all the code
+that has FindBin::libs will simply use it first.
+
+=item Testing with Symlinks
+
+$FindBin::Bin is relative to where an executable is started from.
+This allows a symlink to change the location of directories used
+by FindBin::libs. Full regression testing of an executable can be
+accomplished with a symlink:
+
+ ./sandbox
+ ./lib -> /homegrown/dir/lib
+ ./lib/What/Ever.pm
+
+ ./pre-change
+ ./bin/foobar
+
+ ./post-change
+ ./lib/What/Ever.pm
+ ./bin/foobar -> ../../pre-last-change/bin/foobar
+
+Running foobar symlinked into the post-change directory will
+test it with whatever collection of modules is in the post-change
+directory. A large regression test on some collection of
+changed modules can be performed with a few symlinks into a
+sandbox area.
+
+=item Managing Configuration and Meta-data Files
+
+The "base" option alters FindBin::libs standard base directory.
+This allows for a heirarchical set of metadata directories:
+
+ ./sandbox
+ ./meta
+ ./project/
+ ./meta
+
+ ./project/package
+ ./bin
+ ./meta
+
+with
+
+ use FindBin::libs qw( base=meta export );
+
+ sub read_meta
+ {
+ my $base = shift;
+
+ for my $dir ( @meta )
+ {
+ # open the first one and return
+ ...
+ }
+
+ # caller gets back empty list if nothing was read.
+
+ ()
+ }
+
+=item using "prove" with local modules.
+
+Modules that are not intended for CPAN will not usually have
+a Makefile.PL or Build setup. This makes it harder to check
+the code via "make test". Instead of hacking a one-time
+Makefile, FindBin::libs can be used to locate modules in
+a "lib" directory adjacent to the "t: directory. The setup
+for this module would look like:
+
+
+ ./t/01.t
+ ./t/02.t
+ ...
+
+ ./lib/FindBin/libs.pm
+
+since the *.t files use FindBin::libs they can locate the
+most recent version of code without it having to be copied
+into a ./blib directory (usually via make) before being
+processed. If the module did not have a Makefile this would
+allow:
+
+ prove t/*.t;
+
+to check the code.
+
+=back
+
+=head1 Notes
+
+=head2 Alternatives
+
+FindBin::libs was developed to avoid pitfalls with
+the items listed below. As of FindBin::libs-1.20,
+this is also mutli-platform, where other techniques
+may be limited to *NIX or at least less portable.
+
+=over 4
+
+=item PERL5LIBS
+
+PERL5LIB can be used to accomplish the same directory
+lookups as FindBin::libs. The problem is PERL5LIB often
+contains absolte paths and does not automatically change
+depending on where tests are run. This can leave you
+modifying a file, changing directory to see if it works
+with some other code and testing an unmodified version of
+the code via PERL5LIB. FindBin::libs avoids this by using
+$FindBin::bin to reference where the code is running from.
+
+The same is true of trying to use almost any environmental
+solution, with Perl's built in mechanism or one based on
+$ENV{ PWD } or qx( pwd ).
+
+Aside: Combining an existing PERL5LIB for
+out-of-tree lookups with the "p5lib" option
+works well for most development situations.
+
+=item use lib qw( ../../../../Lib );
+
+This works, but how many dots do you need to get all
+the working lib's into a module or #! code? Class
+distrubuted among several levels subdirectories may
+have qw( ../../../lib ) vs. qw( ../../../../lib )
+or various combinations of them. Validating these by
+hand (let alone correcting them) leaves me crosseyed
+after only a short session.
+
+=item Anchor on a fixed lib directory.
+
+Given a standard directory, it is possible to use
+something like:
+
+ BEGIN
+ {
+ my ( $libdir ) = $0 =~ m{ ^( .+? )/SOMEDIR/ }x;
+
+ eval "use lib qw( $libdir )";
+ }
+
+This looks for a standard location (e.g., /path/to/Mylib)
+in the executable path (or cwd) and uses that.
+
+The main problem here is that if the anchor ever changes
+(e.g., when moving code between projects or relocating
+directories now that SVN supports it) the path often has
+to change in multiple files. The regex also may have to
+support multiple platforms, or be broken into more complicated
+File::Spec code that probably looks pretty much like what
+
+ use FindBin::libs qw( base=Mylib )
+
+does anyway.
+
+=back
+
+=head2 FindBin::libs-1.2+ uses File::Spec
+
+In order to accmodate a wider range of filesystems,
+the code has been re-written to use File::Spec for
+all directory and volume manglement.
+
+There is one thing that File::Spec does not handle,
+hoever, which is fully reolving absolute paths. That
+still has to be handled via abs_path, when it works.
+
+The issue is that File::Spec::rel2abs and
+Cwd::abs_path work differently: abs_path only
+returns true for existing directories and
+resolves symlinks; rel2abs simply prepends cwd()
+to any non-absolute paths.
+
+The difference for FinBin::libs is that
+including redundant directories can lead to
+unexpected results in what gets included;
+looking up the contents of heavily-symlinked
+paths is slow (and has some -- admittedly
+unlikely -- failures at runtime). So, abs_path()
+is the preferred way to find where the lib's
+really live after they are found looking up the
+tree. Using abs_path() also avoids problems
+where the same directory is included twice in a
+sandbox' tree via symlinks.
+
+Due to previous complaints that abs_path did not
+work properly on all systems, the current
+version of FindBin::libs uses File::Spec to
+break apart and re-assemble directories, with
+abs_path used optinally. If "abs_path cwd" works
+then abs_path is used on the directory paths
+handed by File::Spec::catpath(); otherwise the
+paths are used as-is. This may leave users on
+systms with non-working abs_path() having extra
+copies of external library directories in @INC.
+
+Another issue is that I've heard reports of
+some systems failing the '-d' test on symlinks,
+where '-e' would have succeded.
+
+=head1 See Also
+
+=over 4
+
+=item File::Spec
+
+This is used for portability in dis- and re-assembling
+directory paths based on $FindBin::Bin.
+
+=item libs_curr.pm
+
+This is installed if $^V indicates that the running
+perl is >= v5.10.
+
+=back
+
+=head1 BUGS
+
+=over 4
+
+=item
+
+In order to avoid including junk, FindBin::libs
+uses '-d' to test the items before including
+them on the library list. This works fine so
+long as abs_path() is used to disambiguate any
+symlinks first. If abs_path() is turned off
+then legitimate directories may be left off in
+whatever local conditions might cause a valid
+symlink to fail the '-d' test."
+
+=item
+
+File::Spec 3.16 and prior have a bug in VMS of
+not returning an absolute paths in splitdir for
+dir's without a leading '.'. Fix for this is to
+unshift '', @dirpath if $dirpath[0]. While not a
+bug, this is obviously a somewhat kludgy workaround
+and should be removed (with an added test for a
+working version) once the File::Spec is fixed.
+
+=item
+
+The hack for prior-to-5.12 versions of perl is
+messy, but is the only I've found that works for
+the moment on *NIX, VMS, and MSW. I am not sure
+whether any of these systems are normally configured
+to share perl modules between versions. If the
+moduels are not shared on multiple platforms then
+I can make this work by managing the installation
+rather than checking this every time at startup.
+
+For the moment, at least, this seems to work.
+
+=back
+
+=head1 AUTHOR
+
+Steven Lembark, Workhorse Computing <lembark@wrkhors.com>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2003-2012, Steven Lembark, Workhorse Computing.
+This code is released under the same terms as Perl-5.8
+or any later version of Perl.
@@ -0,0 +1,103 @@
+########################################################################
+# housekeeping
+########################################################################
+package Testophile;
+use strict;
+
+use Test::More;
+
+use Symbol qw( qualify_to_ref );
+
+require_ok qw( Cwd );
+require_ok qw( File::Spec::Functions );
+
+########################################################################
+# sanity check whether Cwd has working subs
+########################################################################
+
+sub sanity
+{
+ my $handler = shift
+ or return;
+
+ eval
+ {
+ $handler->( '//' );
+ $handler->( 'cwd' );
+ 1
+ }
+}
+
+my $abs = Cwd->can( 'abs_path' );
+my $rel = File::Spec::Functions->can( 'rel2abs' );
+
+$abs || $rel
+or BAIL_OUT "Cwd lacks 'abs_path' and F::S::F lacks 'rel2abs'";
+
+sanity $abs
+or
+sanity $rel
+or
+BAIL_OUT "Neither abs_path nor rel2abs handle '//' and 'cwd'";
+
+my $ref = *{ qualify_to_ref 'abs_path', __PACKAGE__ };
+
+undef &{ *$ref };
+
+*{ $ref } = $abs || $rel;
+
+__PACKAGE__->can( 'abs_path' )
+or BAIL_OUT "Failed installing 'abs_path'";
+
+pass 'Functinal abs_path installed';
+
+done_testing
+
+
+__END__
+
+BEGIN
+{
+ # however... there have been complaints of
+ # places where abs_path does not work.
+ #
+ # if abs_path fails on the working directory
+ # then replace it with rel2abs and live with
+ # possibly slower, redundant directories.
+ #
+ # the abs_path '//' hack allows for testing
+ # broken abs_path on primitive systems that
+ # cannot handle the rooted system being linked
+ # back to itself.
+
+ use Cwd qw( &cwd );
+
+ my $abs = Cwd->can( 'abs_path' )
+ or die "Odd: Cwd cannot 'abs_path'\n";
+
+ if
+ (
+ eval { $abs->( '//' ); $abs->( cwd ); 1 }
+ )
+ {
+ # nothing more to do: abs_path works.
+ }
+ elsif
+ (
+ $abs = Cwd->can( 'rel2abs' )
+ )
+ {
+ # ok, we have a substitute
+ }
+ else
+ {
+ die "Cwd fails abs_path test && lacks 'rel2abs'\n";
+ }
+
+ my $ref = *{ qualify_to_ref 'abs_path', __PACKAGE__ };
+
+ undef &{ *$ref };
+
+ *{ $ref } = $abs;
+
+}
@@ -26,7 +26,7 @@ BEGIN
END
{
- -e './foobar' && unlink './foobar';
+ unlink './foobar';
}
use FindBin::libs qw( export );
@@ -0,0 +1,35 @@
+package Testophile;
+
+use v5.8;
+
+use File::Spec::Functions qw( catpath );
+use Symbol qw( qualify_to_ref );
+
+use Test::More tests => 2;
+
+BEGIN { mkdir './blib/blort', 0555 }
+END { rmdir './blib/blort' }
+
+require FindBin::libs;
+
+FindBin::libs->import
+(
+ qw
+ (
+ base=blib
+ subdir=blort
+ subonly
+ export=snark
+ scalar
+ )
+);
+
+my $ref = qualify_to_ref 'snark';
+my $expect = catpath '' => qw( blib blort );
+
+my $value = ${ *$ref };
+
+ok $value, "Exported scalar '\$snark'";
+like $value, qr{ \Q$expect\E $}x, "Found 'blib/blort' ($value)";
+
+__END__