I'm having issues figuring out relative paths for use lib
. Here is an example of what I am trying to do:
I have a directory call foo
, which contains a script named myscript.pl
. myscript.pl
uses a module named Mod1.pm
located in a subdirectory called bar
, so at the top of myscript.pl
I put the lines:
use lib 'bar';
use Mod1;
This works fine, until I want Mod1.pm
to use another module, foo/bar/asdf/Mod2.pm
. If I put a use lib 'asdf'
at the top of Mod1.pm
this won't work because it searches relative to the directory I'm running myscript.pl
from. So I did some searching and found FindBin
, and tried adding these lines to Mod1.pm:
use FindBin;
use lib "$FindBin::Bin/asdf";
This didn't work either, because FindBin
finds the directory that the script I am running (myscript.pl
) is located in, not the file that uses FindBin
(in this case Mod1.pm
). So my question is, is there a way to search relative to where Mod1.pm
is located, so that it can find Mod2.pm
no matter where the script that uses Mod1.pm
is located?
EDIT: Further explanation of my situation to address some of your comments:
I'm working on code in a repository, and all CPAN libraries need to be installed in a directory in the repository. That means that the use lib
s can't have any absolute paths. For my project there is a central module "Mod1.pm" which use
es quite a few CPAN modules that are located in various directories in the repository. All of the use lib
statements are of the form use lib '../../foo/bar/asdf'
so that they can be found relative to wherever you're running the script from, but this restricts where you can run scripts that use Mod1.pm, which I'm trying to avoid. Another annoying side effect is that I can't just perl -c Mod1.pm
to make sure any edits I make to Mod1.pm are sane, unless I'm running it in the right place, which conveniently isn't where Mod1.pm is located. Oh the joys of joining a project that already has messy code in place... Another nasty side effect is that I can't use any CPAN modules that any of you are suggesting to fix my problems, because I'd still need a way to find those.
You should
use lib
inmyscript.pl
, which is a convention.For example, your files are organized as:
then
use lib
inmyscript.pl
:then use
Mod1.pm
andMod2.pm
just like using other CPAN modules. Just remember to add the dir name before the module name when usingMod2.pm
.in
Mod1.pm
:in
Mod2.pm
:Usually you want your main program to find all its libraries on its own, in which case you should do as Alec Chen answered.
In some situations, such as finding plug ins, you want a library to find other libraries relative to its location.
You can do this using
__FILE__
which contains the location of the current file of source code.The funny way that's written above is because each Perl file has two (or more) stages of execution. "Compile time" and "run time".
use
statements happen at compile time. In order touse lib $module_dir
, we must set$module_dir
at compile time with aBEGIN
block. Confused? There's easier ways...It is bad form for a module to alter
@INC
globally. Loading a module should not change the global state of the program (unless that's part of its functionality). You would instead localize it.But its probably simpler to just require it directly as a file.
And, this being Perl, there are modules to handle having plugins, Module::Pluggable being very popular.