To Depend Or Not To Depend

When starting an application, I always strive to reduce dependencies as much as possible, especially if I know that there's some way that does not take me too much time to go.

It turns out that I chose one of the worst possible examples. Check out the comments below and - more importantly - check out lib documentation!

This happens when I use lib, for example to add ../lib to @INC. For my own stuff I usually head towards Path::Class:

use Path::Class qw( file );
use lib file(__FILE__)->parent()->parent()->subdir('lib')->stringify();

but when I want to reduce dependencies I revert to File::Spec::Functions (which is CORE since perl 5.5.4 and now part of PathTools):

use File::Spec::Functions qw( splitpath splitdir catdir catpath );
my $path;
BEGIN {
   my ($volume, $directories) = splitpath(__FILE__);
   my @dirs = splitdir($directories);
   push @dirs, qw( .. lib ); # ../lib - naive but effective
   $path = catpath($volume, catdir(@dirs));
}
use lib $path;

Alas, how I miss the Path::Class solution!

4 Comments

Note that $path in 'use lib $path;' must use Unix filepaths (see lib.pm documentation). This means joining with '/' as a directory separator.

Did you test your solution on MS Windows or MacOS X?

BTW, that is what I use

use File::Spec;
# __DIR__ is taken from Dir::Self __DIR__ fragment
sub __DIR__ () {
  File::Spec->rel2abs(join '', (File::Spec->splitpath(__FILE__))[0, 1]);
}
use lib __DIR__ . '/lib';

How about

use FindBin qw($Bin);
use lib "$Bin/../lib";

?

Danger! FindBin considered harmful.

I prefer to structure my perl scripts as a library with a thin "bin" wrapper, and then build/install using Dist::Zilla (or Module::Build, or ExtUtils::MakeMaker). Doing it this way make it so that I never have to resort to crazy File::Spec hacks, and I get other benefits like test-driven development with "prove -l -v t" and the potential to release to CPAN one day

Leave a comment

About Flavio Poletti

user-pic I blog about Perl.