Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Relative Module Path

by pbeckingham (Parson)
on Aug 01, 2004 at 02:56 UTC ( #379010=perlquestion: print w/replies, xml ) Need Help??
pbeckingham has asked for the wisdom of the Perl Monks concerning the following question:

I don't know what the best approach would be to allow the following:

I would like a program P to use a module, and they currently (and always will) reside together in the same directory. I would like to be able to rename that directory and have it still work. I would also like to be able to run P from an arbitrary location, such that $CWD is not predictable. The code below does not satisfy these two requirements.

Here is the program that resides in ~/P:

#! /usr/bin/perl -w use strict; use M; my $m = M->new;
and here is the module 'M' that resides in ~/
package M; sub new {1}; 1;
I have considered:
  • an install-time patching of the shebang to include the correct current path
  • an install-time patching of a config file with the lib path
  • some fiddling with $0, and unshifting the dir onto @INC
Can anyone suggest something better?

Replies are listed 'Best First'.
Re: Relative Module Path
by duff (Parson) on Aug 01, 2004 at 03:05 UTC

      The bin's in the corner :)

      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: Relative Module Path
by tadamec (Beadle) on Aug 01, 2004 at 08:32 UTC

    Why not combine P and M into a single unit? That way you're sure they won't be separated by a too-specific copy command.

    Using your example, ~/P would become:

    #!/usr/bin/perl -w use strict; use M; my $m = M->new; # # End of main program # package M; sub new{1}; 1;

      Why not combine them? Because there are many modules, and many more programs that use them. The example shown was just that - an example. The real code is somewhat more complex.

        Ah, gotcha.

        I use something like this for situations where I have a local "lib" directory. You could probably modify it somewhat:

        #!/usr/bin/perl use strict; # Always use strict. my $BASEPATH; # # Include path magic. # BEGIN { use File::Basename; use File::Spec; my $PROGRAM = File::Spec->rel2abs( $0 ); ( undef, $BASEPATH, undef ) = fileparse( $PROGRAM ); $BASEPATH = File::Spec->catdir( $BASEPATH, "../" ); my $LIBPATH = File::Spec->catdir( $BASEPATH, "lib" ); eval " use lib '$LIBPATH'"; }

        If you want to keep the module files in the same directory this BEGIN block should work (I haven't tested it):

        BEGIN { use File::Basename; use File::Spec; my $PROGRAM = File::Spec->rel2abs( $0 ); ( undef, $BASEPATH, undef ) = fileparse( $PROGRAM ); eval " use lib '$BASEPATH'"; }
Re: Relative Module Path
by Anneq (Vicar) on Aug 02, 2004 at 01:50 UTC

    After running into this problem several times, I've standardized how I place script and module files in each project. Basically in my project directory, I have a sub-directory for scripts (e.g., cgi-bin) and a sub-directory for my modules (my_lib). Then I can include the following code in any script and it always finds my modules.

    #--------------------------------------------------------------------- +-- # Portably Include My Perl Modules #--------------------------------------------------------------------- +-- use Cwd; use File::Spec; my $dir; BEGIN { # Prepare lib path $dir = Cwd->getcwd; # Get directory path of script or get web doc +root my @dirs = File::Spec->splitdir( $dir ); # Split path into array pop @dirs; # Take off last directory (e.g., public_html, cgi-bin,. +..) # Put'em togeth & add modules dir $dir = File::Spec->catdir( @dirs, "my_lib"); unshift(@INC, $dir) if (-d $dir); # Incl. my lib if it exists }

    Hope that helps,


      Excellent. Iíve had a long fight with this too. Many thanks. Worth adding to snippets?
Re: Relative Module Path
by astroboy (Chaplain) on Aug 01, 2004 at 20:46 UTC
    And if your modules are always going to be relative to your bin path (say "." or "../lib") then a compinatoon of "FindBin" and "use lib" does the trick
Re: Relative Module Path
by Forsaken (Friar) on Aug 01, 2004 at 19:52 UTC
    doesn't @INC include the directory of the calling script by default? I have a similar situation where the actual file is located in the same directory as and it works fine. In that same directory is also a module directory which contains all module::something files.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://379010]
Approved by matija
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (8)
As of 2018-10-15 18:54 GMT
Find Nodes?
    Voting Booth?
    When I need money for a bigger acquisition, I usually ...

    Results (82 votes). Check out past polls.