Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

"use lib" with low precedence?

by joe++ (Friar)
on Oct 07, 2002 at 12:07 UTC ( [id://203298] : perlquestion . print w/replies, xml ) Need Help??

joe++ has asked for the wisdom of the Perl Monks concerning the following question:


I'm developing a script on a box where I can't install modules. No problem, I just create a local libdir and add

#!/usr/bin/perl -w use lib qw(libdir);
That's classic.

Now this inserts the path libdir in front of @INC, which means that my local library will be ALWAYS used, regardless of the availability of the same module in the regular @INC paths.

This is not wat I want; I want to provide the local library only in case a global installed library is missing.

Now I was thinking about a solution where I require this specific module in an eval block instead of use-ing it, catch errors and require my local version if needed.

eval { require Test::Simple; }; if ($@) { eval { use lib qw(libdir); }; } eval { require Test::Simple; }; die $@ if $@;
However, this is more complicated and I don't get the benefit of compile-time checking of the used module.

Is there a better solution?

Cheers, Joe

Replies are listed 'Best First'.
Re: "use lib" with low precedence?
by Abigail-II (Bishop) on Oct 07, 2002 at 12:28 UTC
    You can make use of the fact that lib::import deletes duplicates from @INC, and do:
    use lib @INC => "libdir";

    That will effectively put libdir after all the other directories in @INC.


      I like this trick better than manipulating @INC directly, as others have suggested.

      Seems like doing this is clearer and more likely to be robust if new magic is added to @INC at some point.

Re: "use lib" with low precedence?
by PodMaster (Abbot) on Oct 07, 2002 at 12:14 UTC
    Yes, modify @INC instead of using lib ;)
    ## instead of the standard ## BEGIN { unshift(@INC, LIST) } ## do BEGIN { push(@INC, LIST) }
    It's important to take a look into the modules you use every once in a while, especially the pragmas ~ you'll learn a thing or two.

    BTW ~ I'm not sure how this will effect version issues, like if you "use CGI 2.81;", and your lib has it, but the standard lib has 2.71.

    update: If you're in the above situation, you could work some magic like in robustly list any Perl code's module dependencies and get fancy with it.

    ** The Third rule of perl club is a statement of fact: pod is sexy.

      Sure, that's exactly it... stupid me ;-)

      Update: the stupidiest question is still the unasked question - learnt a much better trick cf Abigail's tip below!

      Thanks again!

      Cheers, Joe

Re: "use lib" with low precedence?
by broquaint (Abbot) on Oct 07, 2002 at 12:16 UTC
    Since use lib is really just a glorified unshift @INC you could just do a simple push e.g
    BEGIN { push @INC, qw( your/libraries here ) } ...
    Now your local libraries will have a 'lower precedence' than the system libraries.


Re: "use lib" with low precedence?
by belg4mit (Prior) on Oct 07, 2002 at 16:17 UTC
    use lib 'foo'; use Fred; use Barney;

    is different from

    use Fred; use lib 'foo'; use Barney;

    UPDATE: To clarify, in the former both Fred and Barney are included from foo. In the latter Fred comes from the default location and Barney from foo; assuming copies of Fred and Barney exist in both foo and default locations.

    perl -wpe "s/\b;([mnst])/'$1/g"

Re: "use lib" with low precedence?
by shahzbot (Novice) on Oct 07, 2002 at 22:49 UTC
    One other option, for those not wanting to modify their scripts at all: The PERL5LIB environment variable. If you do this:
    perl -e "print join(qq|:|, @INC)"

    you'll get your current perl @INC array in a path format. If you set your PERL5LIB env var to the output of that one-liner and also tack your own custom libs on the end of it, this will have the effect of putting a copy of your @INC in front of your custom libs, even though your original @INC remains untouched (and unused) at runtime. When I do this, my PERL5LIB ends up looking like this (breaks added for readability):

    It ends up doubling your original @INC path in memory, but as a temporary measure, it's much easier to reverse, since you have no code to modify. Just a thought... jpt