File Coverage

blib/lib/FindBin/libs.pm
Criterion Covered Total %
statement 46 58 79.3
branch 12 26 46.1
condition 2 5 40.0
subroutine 10 10 100.0
pod n/a
total 70 99 70.7


line stmt bran cond sub pod time code
1             ########################################################################
2             # housekeeping
3             ########################################################################
4              
5             use v5.14;
6 10     10   219020 use strict;
  10         82  
7 10     10   54  
  10         19  
  10         213  
8             use FindBin;
9 10     10   4083  
  10         9636  
  10         441  
10             use File::Basename;
11 10     10   66  
  10         18  
  10         511  
12             use Carp qw( croak );
13 10     10   55 use Symbol qw( qualify qualify_to_ref );
  10         20  
  10         401  
14 10     10   2310  
  10         4204  
  10         651  
15             use File::Spec::Functions
16             qw
17             (
18 10         1493 &splitpath
19             &splitdir
20             &catpath
21             &catdir
22             );
23 10     10   3170  
  10         5860  
24             BEGIN
25             {
26             # however... there have been complaints of
27             # places where abs_path does not work.
28             #
29             # if abs_path fails on the working directory
30             # then replace it with rel2abs and live with
31             # possibly slower, redundant directories.
32             #
33             # the abs_path '//' hack allows for testing
34             # broken abs_path on primitive systems that
35             # cannot handle the rooted system being linked
36             # back to itself.
37              
38             use Cwd qw( &abs_path &cwd );
39 10     10   75  
  10         21  
  10         1668  
40             if
41 10 50   10   39 (
42             # abs_path has a fixed bug dealing with infinite
43             # recursion. if upping the version of Cwd does
44             # not fix this then the only other test I can
45             # think of is ( -e '/.' && -e '/..' && -e '/../.' )
46              
47             eval
48             {
49             abs_path '//';
50 10         70 abs_path cwd
51 10         47171 }
52             )
53             {
54             # abs_path seems clean on this platform.
55             }
56             else
57             {
58             # abs_path seems to be having problems,
59             # fix is to stub it out.
60             #
61             # undef avoids nastygram.
62              
63             my $ref = qualify_to_ref 'abs_path', __PACKAGE__;
64 0         0  
65             my $sub = File::Spec::Functions->can( 'rel2abs' );
66 0         0  
67             undef &{ $ref };
68 0         0  
  0         0  
69             *$ref = $sub
70 0         0 };
71             }
72              
73             ########################################################################
74             # package variables
75             ########################################################################
76              
77             my %defaultz =
78             (
79             base => 'lib',
80             use => undef,
81             blib => undef, # prefer ./blib at the first level
82              
83             subdir => '', # add this subdir also if found.
84             subonly => undef, # leave out lib's, use only subdir.
85             export => undef, # push variable into caller's space.
86             append => undef, # push onto existing array (vs. overwrite)
87             verbose => undef, # boolean: print inputs, results.
88             debug => undef, # boolean: set internal breakpoints.
89              
90             print => 1, # display the results
91              
92             p5lib => undef, # prefix PERL5LIB with the results
93              
94             ignore => '/,/usr', # dir's to skip looking for ./lib
95             );
96              
97             # only new directories are used, ignore pre-loads
98             # this with unwanted values.
99              
100             my %found = ();
101              
102             # saves passing this between import and $handle_args.
103              
104             my %argz = ();
105             my $verbose = '';
106             my $empty = q{};
107              
108             ########################################################################
109             # subroutines
110             ########################################################################
111              
112             # HAK ALERT: $Bin is an absolute path, there are cases
113             # where splitdir does not add the leading '' onto the
114             # directory path for it on VMS. Fix is to unshift a leading
115             # '' into @dirpath where the leading entry is true.
116              
117             my $find_libs
118             = sub
119             {
120             my $base = basename ( shift || $argz{ base } );
121              
122             my $subdir = $argz{ subdir } || '';
123              
124             my $subonly = defined $argz{ subonly };
125              
126             # for some reason, RH Enterprise V/4 has a
127             # trailing '/'; I havn't seen another copy of
128             # FindBin that does this. fix is quick enough:
129             # strip the trailing '/'.
130             #
131             # using a regex to extract the value untaints it
132             # (not useful for anything much, just helps the
133             # poor slobs stuck in taint mode).
134             #
135             # after that splitpath can grab the directory
136             # portion for future use.
137              
138             my ( $Bin ) = ( $argz{ Bin } =~ m{^ (.+) }xs );
139              
140             print STDERR "\nSearching $Bin for '$base'...\n"
141             if $verbose;
142              
143             my( $vol, $dir ) = splitpath $Bin, 1;
144              
145             my @dirpath = splitdir $dir;
146              
147             # fix for File::Spec::VMS missing the leading empty
148             # string on a split. this can be removed once File::Spec
149             # is fixed.
150              
151             unshift @dirpath, '' if $dirpath[ 0 ];
152              
153             my @libz = ();
154              
155             PATH:
156             for( 1 .. @dirpath )
157             {
158             # note that catpath is extraneous on *NIX; the
159             # volume only means something on DOS- & VMS-based
160             # filesystems, and adding an empty basename on
161             # *nix is unnecessary.
162             #
163             # HAK ALERT: the poor slobs stuck on windog have an
164             # abs_path that croaks on missing directories. have
165             # to eval the check for subdir's.
166              
167             my $abs
168             = eval
169             {
170             abs_path
171             catpath $vol, ( catdir @dirpath, $base ), $empty
172             }
173             || '';
174              
175             my $sub
176             = $subdir
177             ? eval { abs_path ( catpath '', $abs, $subdir ) } || ''
178             : ''
179             ;
180              
181             my @search = $subonly ? ( $sub ) : ( $abs, $sub );
182              
183             for my $dir ( @search )
184             {
185             if( $dir && -d $dir && ! exists $found{ $dir } )
186             {
187             $found{ $dir } = ();
188              
189             push @libz, $dir;
190              
191             last if $argz{ scalar };
192             }
193             }
194              
195             pop @dirpath
196             }
197              
198             # caller gets back the existing lib paths
199             # (including volume) walking up the path
200             # from $FindBin::Bin -> root.
201             #
202             # no libs found is empty list or undef for
203             # scalar.
204             #
205             # passing it back as a list isn't all that
206             # painful for a few paths.
207              
208             wantarray ? @libz : \@libz
209             };
210              
211             # break out the messy part into a separate block.
212              
213             my $handle_args
214             = sub
215             {
216             # discard the module, rest are arguments.
217              
218             shift;
219              
220             # anything after the module are options with arguments
221             # assigned via '='.
222              
223             %argz
224             = map
225             {
226             my $use_undef
227             = do
228             {
229             my %a = ();
230             @a{ qw( export ignore ) } = ();
231             \%a
232             };
233              
234             my ( $k, $v ) = split '=', $_, 2;
235              
236             exists $use_undef->{ $k }
237             or $v //= 1;
238              
239             # "no" inverts the sense of the test.
240              
241             $k =~ s{^no}{}
242             and $v = ! $v;
243              
244             ( $k => $v )
245             }
246             @_;
247              
248             # stuff "debug=1" into your arguments and perl -d will stop here.
249              
250             $DB::single = 1 if defined $argz{ debug };
251              
252             # default if nothing is supplied is to use the result;
253             # otherwise, without use supplied either of export or
254             # p5lib will turn off use.
255              
256             if( exists $argz{ use } )
257             {
258             # nothing further to do
259             }
260             elsif( defined $argz{ export } || defined $argz{ p5lib } )
261             {
262             $argz{ use } = undef;
263             }
264             else
265             {
266             $argz{ use } = 1;
267             }
268              
269             local $defaultz{ Bin }
270             = do
271             {
272             if( my $bin = $argz{ Bin } )
273             {
274             -d $bin
275             ? $bin
276             : -f $bin
277             ? dirname $bin
278             : die "Botched Bin: '$bin' neither file nor dir.\n";
279             }
280             else
281             {
282             exists $argz{ realbin }
283             ? $FindBin::RealBin
284             : $FindBin::Bin
285             }
286             };
287              
288             # now apply the defaults, then sanity check the result.
289             # base is a special case since it always has to exist.
290             #
291             # if $argz{ export } is defined but false then it takes
292             # its default from $argz{ base }.
293              
294             while( my($k,$v) = each %defaultz )
295             {
296             # //= doesn't work here since undef may be a
297             # legit default.
298              
299             exists $argz{ $k }
300             or
301             $argz{ $k } = $v;
302             }
303              
304             exists $argz{ base } && $argz{ base }
305             or croak "Bogus FindBin::libs: missing/false base argument, should be 'base=NAME'";
306              
307             exists $argz{ export }
308             and
309             $argz{ export } //= $argz{ base };
310              
311             $argz{ ignore } =
312             [
313             grep { $_ } split /\s*,\s*/, $argz{ ignore }
314             ];
315              
316             $verbose = defined $argz{ verbose };
317              
318             my $base = $argz{ base };
319              
320             # now locate the libraries.
321             #
322             # %found contains the abs_path results for each directory to
323             # avoid double-including directories.
324             #
325             # note: loop short-curcuts for the (usually) list.
326              
327             %found = ();
328              
329             for( @{ $argz{ ignore } } )
330             {
331             if( my $dir = eval { abs_path catdir $_, $base } )
332             {
333             if( -d $dir )
334             {
335             $found{ $dir } = 1;
336             }
337             }
338             }
339             };
340              
341             {
342             &$handle_args;
343              
344 14     14   14548 my @libz = $find_libs->();
345              
346 14         40 # HAK ALERT: the regex does nothing for security,
347             # just dodges -T. putting this down here instead
348             # of inside find_libs allows people to use saner
349             # untainting plans via find_libs.
350              
351             @libz = map { m{ (.+) }xs } @libz;
352              
353 14         31 my $caller = caller;
  14         81  
354              
355 14         35 if( $verbose || defined $argz{ print } )
356             {
357 14 50 33     78 local $\ = "\n";
358             local $, = "\n\t";
359 14         118  
360 14         30 print STDERR "Found */$argz{ base }:", @libz
361             if $verbose;
362 14 50       69 }
363              
364             if( $argz{ export } )
365             {
366 14 50       51 # this has to run in order to install variables that
367             # the caller is expecting to exist at runtime -- even
368             # if they are empty/undef at the end of it.
369              
370             my $ref = qualify_to_ref $argz{ export }, $caller;
371              
372 14         92 if( $verbose )
373             {
374 14 50       577 my $dest = qualify $argz{ export }, $caller;
375              
376 0         0 $argz{ scalar }
377             ? print STDERR "\nExporting: \$$dest\n"
378             : print STDERR "\nExporting: \@$dest\n"
379 0 0       0 ;
380             }
381              
382             if( $argz{ scalar } )
383             {
384 14 50 50     97 *$ref
    50          
385             = @libz
386 0 0       0 ? \$libz[0]
387             : \( my $a = '' )
388             ;
389             }
390             elsif
391             (
392             $argz{ append }
393             and
394             my $ary = *{ $ref }{ ARRAY }
395             )
396 0         0 {
397             push @$ary, @libz;
398             }
399 0         0 else
400             {
401             *$ref = \@libz
402             }
403 14         44 }
404              
405             # no 'else', these are not exclusive
406              
407             if( @libz )
408             {
409 14 100       40 if( defined $argz{ p5lib } )
410             {
411 12 50       32 # stuff the lib's found at the front of $ENV{ PERL5LIB }
412             # yes, virginia, substr is an lvalue -- and saner than
413             # dealing with \Q and a regex on arbitrary paths.
414              
415             ( substr $ENV{ PERL5LIB }, 0, 0 ) = join ':', @libz, '';
416              
417 0         0 print STDERR "\nUpdated PERL5LIB:\t$ENV{ PERL5LIB }\n"
418             if $verbose;
419 0 0       0 }
420              
421             if( $argz{ use } )
422             {
423 12 100       45 # this obviously won't work if lib ever depends
424             # on the caller's package.
425             #
426             # it does avoids issues with -T blowing up on the
427             # old eval technique.
428              
429             require lib;
430              
431 7         4050 lib->import( @libz );
432             }
433 7         4725 }
434              
435             0
436             }
437              
438 14         6662 # keep require happy
439              
440             1
441              
442              
443             =head1 NAME
444              
445             FindBin::libs - locate and a 'use lib' or export
446             directories based on $FindBin::Bin.
447              
448             =head1 SYNOPSIS
449              
450             # search up $FindBin::Bin looking for ./lib directories
451             # and "use lib" them.
452              
453             use FindBin::libs;
454              
455             # same as above with explicit defaults.
456              
457             use FindBin::libs qw( base=lib use=1 noexport noprint );
458              
459             # print the lib dir's before using them.
460              
461             use FindBin::libs qw( print );
462              
463             # find and use lib "altlib" dir's
464              
465             use FindBin::libs qw( base=altlib );
466              
467             # move starting point from $FindBin::Bin to '/tmp'
468              
469             use FindBin::libs qw( Bin=/tmp base=altlib );
470              
471             # if Bin is a file then it's dirname will be used.
472             # useful for ./t files living above files being
473             # tested. __FILE__ is a token, doesn't work with
474             # qw().
475              
476             use FindBin::libs ( 'Bin=' . __FILE__ );
477             use FindBin::libs ( 'Bin=' . __FILE__, 'base=config' );
478              
479             # skip "use lib", export "@altlib" instead.
480              
481             use FindBin::libs qw( base=altlib export );
482              
483             # find altlib directories, use lib them and export @mylibs
484              
485             use FindBin::libs qw( base=altlib export=mylibs use );
486              
487             # "export" defaults to "nouse", these two are identical:
488              
489             use FindBin::libs qw( export nouse );
490             use FindBin::libs qw( export );
491              
492             # use and export are not exclusive:
493              
494             use FindBin::libs qw( use export ); # do both
495             use FindBin::libs qw( nouse noexport print ); # print only
496             use FindBin::libs qw( nouse noexport ); # do nothting at all
497              
498             # print a few interesting messages about the
499             # items found.
500              
501             use FindBinlibs qw( verbose );
502              
503             # turn on a breakpoint after the args are prcoessed, before
504             # any search/export/use lib is handled.
505              
506             use FindBin::libs qw( debug );
507              
508             # prefix PERL5LIB with the lib's found.
509              
510             use FindBin::libs qw( perl5lib );
511              
512             # find a subdir of the lib's looked for.
513             # the first example will use both ../lib and
514             # ../lib/perl5; the second ../lib/perl5/frobnicate
515             # (if they exist). it can also be used with export
516             # and base to locate special configuration dir's.
517             #
518             # subonly with a base is useful for locating config
519             # files. this finds any "./config/mypackage" dir's
520             # without including any ./config dir's. the result
521             # ends up in @config (see also "export=", above).
522              
523             use FindBin::libs qw( subdir=perl5 );
524              
525             use FindBin::libs qw( subdir=perl5/frobnicate );
526              
527             use FindBin::libs qw( base=config subdir=mypackage subonly export );
528              
529             # base and subonly are also useful if your
530             # project is stored in multiple git
531             # repositories.
532             #
533             # say you need libs under api_foo/lib from api_bar: a
534             # base of the git repository directory with subdir of
535             # lib and subonly will pull in those lib dirs.
536              
537             use FindBin::libs qw( base=api_foo subdir=lib subonly );
538              
539             # no harm in using this multiple times to use
540             # or export multple layers of libs.
541              
542             use FindBin::libs qw( export );
543             use FindBin::libs qw( export=found base=lib );
544             use FindBin::libs qw( export=binz base=bin ignore=/foo,/bar );
545             use FindBin::libs qw( export=junk base=frobnicatorium );
546             use FindBin::libs qw( export base=foobar );
547              
548             =head1 DESCRIPTION
549              
550             =head2 General Use
551              
552             This module will locate directories along the path to $FindBin::Bin
553             and "use lib" or export an array of the directories found. The default
554             is to locate "lib" directories and "use lib" them without printing
555             the list.
556              
557             Options controll whether the lib's found are exported into the caller's
558             space, exported to PERL5LIB, or printed. Exporting or setting perl5lib
559             will turn off the default of "use lib" so that:
560              
561             use FindBin::libs qw( export );
562             use FindBin::libs qw( p5lib );
563              
564             are equivalent to
565              
566             use FindBin::libs qw( export nouse );
567             use FindBin::libs qw( p5lib nouse );
568              
569             Combining export with use or p5lib may be useful, p5lib and
570             use are probably not all that useful together.
571              
572             =head3 Alternate directory name: 'base'
573              
574             The basename searched for can be changed via 'base=name' so
575             that
576              
577             use FindBin::libs qw( base=altlib );
578              
579             will search for directories named "altlib" and "use lib" them.
580              
581             =head3 Exporting a variable: "export", "scalar", "append"
582              
583             =over 4
584              
585             =item "export"
586              
587             This installs the results of locating directories into the caller's
588             space. Without any argument, export pushes out a variable named after
589             the located [sub]dir; an argument can be supplied to give the variable
590             name. Without the "scalar" option, the exported variable will be an
591             array in increasing order of "distance" (i.e., "up" the file tree);
592             with the "scalar" option only the first (i.e., "nearest") path is
593             exported.
594              
595             If "export" is given then "nouse" is assumed; using both leaves the
596             variable exported and its contents handed to "use lib".
597              
598             For example:
599              
600             use FindBin::libs qw( export );
601              
602             will find "lib" directories and export @lib with the
603             list of directories found.
604              
605             use FindBin::libs qw( export=mylibs );
606              
607             will find "lib" directories and export them as "@mylibs" to
608             the caller.
609              
610             If "export" only is given then the "use" option defaults to
611             false. So:
612              
613             use FindBin::libs qw( export );
614             use FindBin::libs qw( export nouse );
615              
616             are equivalent. This is mainly for use when looking for data
617             directories with the "base=" argument.
618              
619             If base is used with export the default array name is the base
620             directory value:
621              
622             use FindBin::libs qw( export base=meta );
623              
624             exports @meta while
625              
626             use FindBin::libs qw( export=metadirs base=meta );
627              
628             exports @metadirs as a list of paths ending in "/meta".
629              
630             The use and export switches are not exclusive:
631              
632             use FindBin::libs qw( use export=mylibs );
633              
634             will locate "lib" directories, use lib them, and export
635             @mylibs into the caller's package.
636              
637             =item "scalar"
638              
639             Only searches for the first directory, which is exported (or
640             overwritten) as a scalar rather than array. For example, if
641             a project directory has ./bin and ./etc dir's then #! code in
642             bin with
643              
644             use FindBin::libs qw( export scalar base=etc );
645              
646             will have an $etc variable with the absolute path to ./bin/../etc.
647             For configuration varibles this is usually what you want and allows
648             for "$etc/Foo.conf" rather than "$etc[0]/Foo.conf".
649              
650             =item "append"
651              
652             Sometimes it's simpler to accumulate multiple searches into a
653             single array. Say for ./etc dir's in collection of standard
654             locations.
655              
656             In that case:
657              
658             use FindBin::libs qw( export=etc base=foo subdir=etc );
659             use FindBin::libs qw( export=etc base=bar subdir=etc append );
660              
661             produces something like
662              
663             (
664             /path/to/foo/etc
665             /path/to/bar/etc
666             )
667              
668             without append @etc will have only ./bar/etc since the array would
669             be overwritten with each call to import.
670              
671             =back
672              
673             =head3 Subdirectories
674              
675             The "subdir" and "subonly" settings will add or
676             exclusively use subdir's. This is useful if some
677             of your lib's are in ../lib/perl5 along with
678             ../lib or all of the lib's are in ../lib/perl5.
679              
680             These could be handled with:
681              
682             use FindBin::libs;
683             use FindBin::libs qw( subdir=perl5 subonly );
684              
685             which uses the "lib" dir's along with any lib/perl5 dirs.
686              
687             This can also be handy for locating subdir's used
688             for configuring packages:
689              
690             use FindBin::libs qw( export base=config subonly=mypackage );
691              
692             Will leave @config containing any mypackage dir's found up
693             the tree, nearest to closest.
694              
695             The array format is convienent for locating configuration files
696             shared between projects in separate, sibling directories. For
697             example given:
698              
699             ./proj/Foo/etc
700             ./proj/etc
701              
702             with
703              
704             use FindBin::libs qw( export subdir=etc subonly )
705              
706             will export @etc with qw( ../proj/Foo/etc ../proj/etc ) in lexical
707             order by distance from the #! code. At that point
708              
709             use List::Util qw( first );
710              
711             my $path = first { -e "$_/Global.config" } @etc;
712              
713             will locate the nearest "Global.confg" file. Note that this is
714             not the same as using "scalar" since that will export
715             $etc with only ./Foo/etc.
716              
717             =head3 Setting PERL5LIB: p5lib
718              
719             For cases where the environment is more useful for setting
720             up library paths "p5lib" can be used to preload this variable.
721             This is mainly useful for automatically including directories
722             outside of the parent tree of $FindBin::bin.
723              
724             For example, using:
725              
726             $ export PERL5LIB="/usr/local/foo:/usr/local/bar";
727              
728             $ myprog;
729              
730             or simply
731              
732             $ PERL5LIB="/usr/local/lib/foo:/usr/lib/bar" myprog;
733              
734             (depending on your shell) with #! code including:
735              
736             use FindBin::libs qw( p5lib );
737              
738             will not "use lib" any dir's found but will update PERL5LIB
739             to something like:
740              
741             /home/me/sandbox/branches/lib:/usr/local/lib/foo:/usr/lib/bar
742              
743             This can make controlling the paths used simpler and avoid
744             the use of symlinks for some testing (see examples below).
745              
746             =head2 Skipping directories
747              
748             By default, lib directories under / and /usr are
749             sliently ignored. This normally means that /lib, /usr/lib, and
750             '/usr/local/lib' are skipped. The "ignore" parameter provides
751             a comma-separated list of directories to ignore:
752              
753             use FindBin::libs qw( ignore=/skip/this,/and/this/also );
754              
755             will replace the standard list and thus skip "/skip/this/lib"
756             and "/and/this/also/lib". It will search "/lib" and "/usr/lib"
757             since the argument ignore list replaces the original one.
758              
759             =head2 Homegrown Library Management
760              
761             An all-too-common occurrance managing perly projects is
762             being unable to install new modules becuse "it might
763             break things", and being unable to test them because
764             you can't install them. The usual outcome of this is a
765             collection of hard-coded
766              
767             use lib qw( /usr/local/projectX ... )
768              
769             code at the top of each #! file that has to be updated by
770             hand for each new project.
771              
772             To get away from this you'll often see relative paths
773             for the lib's, which require running the code from one
774             specific place. All this does is push the hard-coding
775             into cron, shell wrappers, and begin blocks.
776              
777             With FindBin::libs you need suffer no more.
778              
779             Automatically finding libraries in and above the executable
780             means you can put your modules into cvs/svn and check them
781             out with the project, have multiple copies shared by developers,
782             or easily move a module up the directory tree in a testbed
783             to regression test the module with existing code. All without
784             having to modify a single line of code.
785              
786             =over 4
787              
788             =item Code-speicfic modules.
789              
790             Say your sandbox is in ./sandbox and you are currently
791             working in ./sandbox/projects/package/bin on a perl
792             executable. You may have some number of modules that
793             are specific -- or customized -- for this pacakge,
794             share some modules within the project, and may want
795             to use company-wide modules that are managed out of
796             ./sandbox in development. All of this lives under a
797             ./qc tree on the test boxes and under ./production
798             on production servers.
799              
800             For simplicity, say that your sandbox lives in your
801             home direcotry, /home/jowbloe, as a directory or a
802             symlink.
803              
804             If your #! uses FindBin::libs in it then it will
805             effectively
806              
807             use lib
808             qw(
809             /home/jowbloe/sandbox/lib
810             /home/jowbloe/sandbox/project/lib
811             /home/jowbloe/sandbox/project/package/lib
812             );
813              
814             if you run /home/jowbloe/sandbox/project/package/bin/foobar.
815             This will happen the same way if you use a relative or
816             absolute path, perl -d the thing, or if any of the lib
817             directories are symlinks outside of your sandbox.
818              
819             This means that the most specific module directories
820             ("closest" to your executable) will be picked up first.
821              
822             If you have a version of Frobnicate.pm in your ./package/lib
823             for modifications fine: you'll use it before the one in
824             ./project or ./sandbox.
825              
826             Using the "p5lib" argument can help in case where some of
827             the code lives outside of the sandbox. To test a sandbox
828             version of some other module:
829              
830             use FindBin::libs qw( p5lib );
831              
832             and
833              
834             $ PERL5LIB=/other/sandbox/module foobar;
835              
836             =item Regression Testing
837              
838             Everntually, however, you'll need to regression test
839             Frobnicate.pm with other modules.
840              
841             Fine: move, copy, or symlink it into ./project/lib and
842             you can merrily run ./project/*/bin/* with it and see
843             if there are any problems. In fact, so can the nice
844             folks in QC.
845              
846             If you want to install and test a new module just
847             prefix it into, say, ./sandbox/lib and all the code
848             that has FindBin::libs will simply use it first.
849              
850             =item Testing with Symlinks
851              
852             $FindBin::Bin is relative to where an executable is started from.
853             This allows a symlink to change the location of directories used
854             by FindBin::libs. Full regression testing of an executable can be
855             accomplished with a symlink:
856              
857             ./sandbox
858             ./lib -> /homegrown/dir/lib
859             ./lib/What/Ever.pm
860              
861             ./pre-change
862             ./bin/foobar
863              
864             ./post-change
865             ./lib/What/Ever.pm
866             ./bin/foobar -> ../../pre-last-change/bin/foobar
867              
868             Running foobar symlinked into the post-change directory will
869             test it with whatever collection of modules is in the post-change
870             directory. A large regression test on some collection of
871             changed modules can be performed with a few symlinks into a
872             sandbox area.
873              
874             =item Managing Configuration and Meta-data Files
875              
876             The "base" option alters FindBin::libs standard base directory.
877             This allows for a heirarchical set of metadata directories:
878              
879             ./sandbox
880             ./meta
881             ./project/
882             ./meta
883              
884             ./project/package
885             ./bin
886             ./meta
887              
888             with
889              
890             use FindBin::libs qw( base=meta export );
891              
892             sub read_meta
893             {
894             my $base = shift;
895              
896             for my $dir ( @meta )
897             {
898             # open the first one and return
899             ...
900             }
901              
902             # caller gets back empty list if nothing was read.
903              
904             ()
905             }
906              
907             =item using "prove" with local modules.
908              
909             Modules that are not intended for CPAN will not usually have
910             a Makefile.PL or Build setup. This makes it harder to check
911             the code via "make test". Instead of hacking a one-time
912             Makefile, FindBin::libs can be used to locate modules in
913             a "lib" directory adjacent to the "t: directory. The setup
914             for this module would look like:
915              
916              
917             ./t/01.t
918             ./t/02.t
919             ...
920              
921             ./lib/FindBin/libs.pm
922              
923             since the *.t files use FindBin::libs they can locate the
924             most recent version of code without it having to be copied
925             into a ./blib directory (usually via make) before being
926             processed. If the module did not have a Makefile this would
927             allow:
928              
929             prove t/*.t;
930              
931             to check the code.
932              
933             =back
934              
935             =head1 Notes
936              
937             =head2 Alternatives
938              
939             FindBin::libs was developed to avoid pitfalls with
940             the items listed below. As of FindBin::libs-1.20,
941             this is also mutli-platform, where other techniques
942             may be limited to *NIX or at least less portable.
943              
944             =over 4
945              
946             =item PERL5LIBS
947              
948             PERL5LIB can be used to accomplish the same directory
949             lookups as FindBin::libs. The problem is PERL5LIB often
950             contains absolte paths and does not automatically change
951             depending on where tests are run. This can leave you
952             modifying a file, changing directory to see if it works
953             with some other code and testing an unmodified version of
954             the code via PERL5LIB. FindBin::libs avoids this by using
955             $FindBin::bin to reference where the code is running from.
956              
957             The same is true of trying to use almost any environmental
958             solution, with Perl's built in mechanism or one based on
959             $ENV{ PWD } or qx( pwd ).
960              
961             Aside: Combining an existing PERL5LIB for
962             out-of-tree lookups with the "p5lib" option
963             works well for most development situations.
964              
965             =item use lib qw( ../../../../Lib );
966              
967             This works, but how many dots do you need to get all
968             the working lib's into a module or #! code? Class
969             distrubuted among several levels subdirectories may
970             have qw( ../../../lib ) vs. qw( ../../../../lib )
971             or various combinations of them. Validating these by
972             hand (let alone correcting them) leaves me crosseyed
973             after only a short session.
974              
975             =item Anchor on a fixed lib directory.
976              
977             Given a standard directory, it is possible to use
978             something like:
979              
980             BEGIN
981             {
982             my ( $libdir ) = $0 =~ m{ ^( .+? )/SOMEDIR/ }x;
983              
984             eval "use lib qw( $libdir )";
985             }
986              
987             This looks for a standard location (e.g., /path/to/Mylib)
988             in the executable path (or cwd) and uses that.
989              
990             The main problem here is that if the anchor ever changes
991             (e.g., when moving code between projects or relocating
992             directories now that SVN supports it) the path often has
993             to change in multiple files. The regex also may have to
994             support multiple platforms, or be broken into more complicated
995             File::Spec code that probably looks pretty much like what
996              
997             use FindBin::libs qw( base=Mylib )
998              
999             does anyway.
1000              
1001             =back
1002              
1003             =head2 FindBin::libs-1.2+ uses File::Spec
1004              
1005             In order to accmodate a wider range of filesystems,
1006             the code has been re-written to use File::Spec for
1007             all directory and volume manglement.
1008              
1009             There is one thing that File::Spec does not handle,
1010             hoever, which is fully reolving absolute paths. That
1011             still has to be handled via abs_path, when it works.
1012              
1013             The issue is that File::Spec::rel2abs and
1014             Cwd::abs_path work differently: abs_path only
1015             returns true for existing directories and
1016             resolves symlinks; rel2abs simply prepends cwd()
1017             to any non-absolute paths.
1018              
1019             The difference for FinBin::libs is that
1020             including redundant directories can lead to
1021             unexpected results in what gets included;
1022             looking up the contents of heavily-symlinked
1023             paths is slow (and has some -- admittedly
1024             unlikely -- failures at runtime). So, abs_path()
1025             is the preferred way to find where the lib's
1026             really live after they are found looking up the
1027             tree. Using abs_path() also avoids problems
1028             where the same directory is included twice in a
1029             sandbox' tree via symlinks.
1030              
1031             Due to previous complaints that abs_path did not
1032             work properly on all systems, the current
1033             version of FindBin::libs uses File::Spec to
1034             break apart and re-assemble directories, with
1035             abs_path used optinally. If "abs_path cwd" works
1036             then abs_path is used on the directory paths
1037             handed by File::Spec::catpath(); otherwise the
1038             paths are used as-is. This may leave users on
1039             systms with non-working abs_path() having extra
1040             copies of external library directories in @INC.
1041              
1042             Another issue is that I've heard reports of
1043             some systems failing the '-d' test on symlinks,
1044             where '-e' would have succeded.
1045              
1046             =head1 See Also
1047              
1048             =over 4
1049              
1050             =item File::Spec
1051              
1052             This is used for portability in dis- and re-assembling
1053             directory paths based on $FindBin::Bin.
1054              
1055             =item Older code.
1056              
1057             FindBin::libs_5_8.pm is installed if $^V indicates
1058             that the running perl is prior to v5.10.
1059              
1060             =back
1061              
1062             =head1 BUGS
1063              
1064             =over 4
1065              
1066             =item
1067              
1068             In order to avoid including junk, FindBin::libs
1069             uses '-d' to test the items before including
1070             them on the library list. This works fine so
1071             long as abs_path() is used to disambiguate any
1072             symlinks first. If abs_path() is turned off
1073             then legitimate directories may be left off in
1074             whatever local conditions might cause a valid
1075             symlink to fail the '-d' test."
1076              
1077             =item
1078              
1079             File::Spec 3.16 and prior have a bug in VMS of
1080             not returning an absolute paths in splitdir for
1081             dir's without a leading '.'. Fix for this is to
1082             unshift '', @dirpath if $dirpath[0]. While not a
1083             bug, this is obviously a somewhat kludgy workaround
1084             and should be removed (with an added test for a
1085             working version) once the File::Spec is fixed.
1086              
1087             =item
1088              
1089             The hack for prior-to-5.12 versions of perl is
1090             messy, but is the only I've found that works for
1091             the moment on *NIX, VMS, and MSW. I am not sure
1092             whether any of these systems are normally configured
1093             to share perl modules between versions. If the
1094             moduels are not shared on multiple platforms then
1095             I can make this work by managing the installation
1096             rather than checking this every time at startup.
1097              
1098             For the moment, at least, this seems to work.
1099              
1100             =back
1101              
1102             =head1 SEE ALSO
1103              
1104             =over 4
1105              
1106             =item Module::FromPerlVer
1107              
1108             Explains where the installed version comes from.
1109              
1110             =item File::Copy::Recursive
1111              
1112             Note: Due to issues with File::Copy::Recusive, this is
1113             using File::Copy::Recursive::Reduced and a version directory
1114             for the moment. Once the Recursive module has been dealt with
1115             Module::FromPerlVer shoud Just Work.
1116              
1117             =back
1118              
1119             =head2 Cwd
1120              
1121             A bug in Cwd was fixed with 3.73. That should, hopefully,
1122             fix the issue with FB::l croaking perl during testing.
1123             If it does not then I will have to modify the sanity check
1124             for using abs_path vs. rel2abs.
1125              
1126             =head1 AUTHOR
1127              
1128             Steven Lembark, Workhorse Computing <lembark@wrkhors.com>
1129              
1130             =head1 COPYRIGHT
1131              
1132             Copyright (C) 2003-2022, Steven Lembark, Workhorse Computing.
1133             This code is released under the same terms as Perl-5.24
1134             or any later version of Perl.
1135              
1136             =head1 LICENSE
1137              
1138             This code is released under the same terms as Perl-5.24
1139             or any later version of Perl.