NAME
lib::root - find perl root and push lib modules path to @INC
VERSION
version 0.10
SYNOPSIS
lib::root looks for a .libroot file on parent directories and pushes ./*/lib to @INC.
When a file does use lib::root
, lib::root will try to read the file parent directories and look for a rootfile (default is .libroot) that is usually located inside a /some/dir/perl that contains many modules used by your app. Many apps have a /some/dir/perl/.perl-version file inside a perl directory, when that is the case, the app can piggy back on that filename and look for that file instead of .libroot with the example below:
use lib::root rootfile => '.perl-version';
To use the defaults, create an empty file named .libroot and place it in your /app/dir/perl/.libroot
use lib::root;
... or use another custom file to determine a libroot
use lib::root; # rootfile defaults to .libroot
use lib::root rootfile => '.perl-version';
... or add a callback if needed
use lib::root callback => sub { ... };
... or look for a given file in approot and use a perl root dir to push to inc
use lib::root rootfile => '.app-root', perldir => 'perl';
WHY IS THIS USEFUL
lib::root can be useful when your application perl modules are not installed globally.
When your app uses lib::root, the lib::root will look for the .libroot file into parent directories relative to the file using it.
For example, your app has the following structure:
/dir/myapp/perl/MyApp-Thing/lib/...
/dir/myapp/perl/MyApp-Another/lib/...
/dir/myapp/perl/MyApp-Stuff/lib/...
/dir/myapp/perl/.perl-version
/dir/myapp/bin/some_script.pl
/dir/myapp/bin/another_script.pl
/dir/myapp/.app-root
... and the app needs to push all those perl/*/lib to @INC. There are some ways to do that
Add the directory to env PERLLIB
PERLLIB=$PERLLIB:/dir/myapp/perl/MyApp-Thing/lib:/dir/myapp/perl/MyApp-Another/lib
Or use -I
perl -I/dir/myapp/perl/MyApp-Thing/lib -I/dir/myapp/perl/MyApp-Another/lib
Or use a BEGIN block:
BEGIN { push @INC, glob "/dir/myapp/perl/*/lib"; }
Or use lib::root:
use lib::root rootfile => '.perl_is_here';
lib::root can also be instructed to look in a cousin dir relative to bin
in the structure above
use lib::root perldir => '../perl';
Or use lib
use FindBin qw($Bin);
use lib "$Bin/../lib";
use lib "/home/user/MyApp/lib";
Or some other way ...
USAGE
For a project with the following strucutre:
/dir/myapp/perl/MyApp-Thing/lib/MyApp/Thing.pm
/dir/myapp/perl/MyApp-Another/lib/MyApp/Another.pm
/dir/myapp/perl/MyApp-Stuff/lib/MyApp/Stuff.pm
/dir/myapp/perl/.libroot
/dir/myapp/perl/.perl-version
/dir/myapp/bin/some_script.pl
/dir/myapp/bin/another_script.pl
/dir/myapp/.app-root
EXAMPLE 1 - DEFAULT USAGE
When using /dir/myapp/perl/MyApp-Thing/lib/MyApp/Thing.pm its possible to include perl/*/lib to @INC by adding the following to Thing.pm
use lib::root;
The above will detect the location of Thing.pm and go recursively to parent directories and look for the default .libroot
file. Given that the .libroot file exists under /dir/myapp/perl/.libroot (/dir/myapp/perl/) , lib::root will do: push @INC, glob "/dir/myapp/perl/*/lib";
EXAMPLE 2 - CUSTOM lib::root FILE
Some plenv projects have a .perl-version
file sitting under the perl dir ie. /perl/.perl-version (see structure above). If thats the case, lib::root can piggy back on the .perl-version file with:
use lib::root rootfile => '.perl-version';
EXAMPLE 3 - CALLING FROM SCRIPT OUTSIDE perl DIRECTORY
If the project has bin
directories like the structure above, and the file /dir/myapp/bin/some_script.pl needs to use lib::root, the file is outside the perl
dir. It will use the .app-root
file with a custom perl perldir
to push libs to @INC, ie:
use lib::root rootfile => '.app-root', perldir => 'perl';
The lib::root call insite the script in bin
will look for a directory that contains .app-root
and then it will use the child directory perl
(the perldir option) to push the modules to @INC;
The same could be done to make the .pm files above also use the .app-root
instead of the .libroot
. Or, also, use .libroot
with a custom perldir
, ie:
use lib::root perldir => 'perl';
use lib::root perldir => 'dir1/dir2/dir3/perl';
use lib::root perldir => '../perl';
EXAMPLE 4 - CALLBACKS
If necessary, lib::root also accepts a callback as an option. The callback is executed after libs are pushed to @INC ie:
use lib::root callback => sub { ... };
EXAMPLE 5 - GET ROOT DIR
IT is also possible to get the root dir calling the root sub:
my $rootdir = lib::root->root;
EXAMPLE 5 - GET ROOT DIR
IT is also possible to get the root dir calling the root sub:
my $rootdir = lib::root->root;
ACCEPTED PARAMETERS
All the parameters are optional. The default libroot file is .libroot
rootfile parameter
The rootfile
parameter defines the which file lib::root must look for in parent directories.
That file (.libroot or other) must exist inside a perl $directory because lib::root will use that $dir to push to @INC.
Once lib::root finds the .libroot file inside $dir, it will push $dir/*/lib to @INC.
The default libroot file is .libroot
, however you may override it with a different name, or maybe use one that already exists, for example the very used cpanfile
or .perl-version
use lib::root rootfile => '.perl-version';
use lib::root rootfile => 'cpanfile';
use lib::root; #defaults to .libroot
The file must exists or lib::root will throw a warning and will not be able to push to @INC.
Example of such warning:
lib::root error: Could not find rootfile [ .libroot ]. lib::root loaded from [ /home/user/myapp/perl/MyApp/lib/MyApp.pm ].
perldir parameter
As mentioned in "rootfile parameter" section, lib::root will find the $dir that contains .libroot. Then push $dir/*/lib to @INC. However, your app might have a different structure and needs some extra directories ie. $dir/some/extra/dir/perl/*/lib
to @INC.
You can add that extra dir with the perldir parameter:
use lib::root perldir => 'some/extra/dir/perl'; #push $librootdir/some/extra/dir/perl/*/lib to @INC
use lib::root rootfile => 'cpanfile', perldir => 'local/myapp'; #push $dir/local/myapp/*/lib
callback parameter
lib::root accepts a callback that will be executed after paths are pushed to @INC. However the callback will only execute if libroot found the rootfile and pushed to @INC.
use lib::root callback => sub { warn "lib::root pushed to @INC" };
rootdir function
After using lib::root
it is possible to retrieve the directory that contains the rootfile.
Use the root
function to get the rootdir. returns a Path::Tiny object. ie:
use lib::root;
print lib::root->rootdir; # /home/user/myapp/perl/ (Path::Tiny object)
rootdir
function is an alias for the root
function. If you prefer to use root:
use lib::root;
print lib::root->root; # /home/user/myapp/perl/ (Path::Tiny object)
INSTALLATION
To install this module via cpanm:
cpanm lib::root
Or via cpan shell:
cpan> install lib::root
SEE ALSO
Similar ideas have been implemented before in the modules below and possibly others
RepRoot
lib::glob
LICENSE
Copyright (C) Hernan Lopes.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
AUTHOR
Hernan Lopes