Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

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 browsing the Monastery: (2)
As of 2018-08-17 07:01 GMT
Find Nodes?
    Voting Booth?
    Asked to put a square peg in a round hole, I would:

    Results (174 votes). Check out past polls.