Bonus @INC directories

Marek Rouchal wrote to me with an interesting addendum to my previous post Who makes it into @INC first?. Besides the different ways to add directories, some of them also load additional subdirectories that you don’t specify.

Look at the output of perl -V again. Here’s mine for v5.30.2 (just released a couple of days ago) where I installed everything under /usr/local/perls/perl-5.30.2:

$ perl -V
  ...
  @INC:
    /usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2/darwin-2level
    /usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2
    /usr/local/perls/perl-5.30.2/lib/5.30.2/darwin-2level
    /usr/local/perls/perl-5.30.2/lib/5.30.2

The default configuration created these directories when I compiled and installed that perl:

  • lib/site_perl/5.30.2/darwin-2level
  • lib/site_perl/5.30.2
  • 5.30.2/darwin-2level
  • lib/5.30.2

The scheme you see in perl -V allows version- or architecture-dependent modules (such as XS modules) to live peacefully next to each other in the same directory tree (although that’s not how I’ve done it).

Augmenting @INC

I create some directories in my home directory, using the values from the configuration, which you can extract with an argument to -V:

$ perl -V:archname
archname='darwin-2level';

$ perl -V:version
version='5.30.2';

$ mkdir -p ~/lib/perl5/5.30.2/darwin-2level

Here’s the program I used previously:

#!perl
use v5.10;

say "The search paths are:\n\t",
	join "\n\t", @INC;

And here are two runs, where I set PERL5LIB in the second:

$ perl order.pl
The search paths are:
	/usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2/darwin-2level
	/usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2
	/usr/local/perls/perl-5.30.2/lib/5.30.2/darwin-2level
	/usr/local/perls/perl-5.30.2/lib/5.30.2

$ env PERL5LIB=/Users/brian/lib/perl5 perl order.pl
The search paths are:
	/Users/brian/lib/perl5/5.30.2/darwin-2level
	/Users/brian/lib/perl5/5.30.2
	/Users/brian/lib/perl5
	/usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2/darwin-2level
	/usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2
	/usr/local/perls/perl-5.30.2/lib/5.30.2/darwin-2level
	/usr/local/perls/perl-5.30.2/lib/5.30.2

I specified only /Users/brian/lib/perl5, but got as a bonus /Users/brian/lib/perl5/5.30.2 and /Users/brian/lib/perl5/5.30.2/darwin-2level. See perlrun for the details about how PERL5LIB does it.

I have other perls installed, so I can try it with one of those. This time I don’t get the extra directories because the version subdirectory doesn’t match:

$ env PERL5LIB=/Users/brian/lib/perl5 perl5.30.1 order.pl
The search paths are:
	/Users/brian/lib/perl5
	/usr/local/perls/perl-5.30.1/lib/site_perl/5.30.1/darwin-2level
	/usr/local/perls/perl-5.30.1/lib/site_perl/5.30.1
	/usr/local/perls/perl-5.30.1/lib/5.30.1/darwin-2level
	/usr/local/perls/perl-5.30.1/lib/5.30.1

This happens for use lib and -I too. You didn’t see them in the previous article because those subdirectories didn’t exist.

local::lib

local::lib loads these extra directories too (and can create them if they don’t already exist):

$ perl -Mlocal::lib order.pl
The search paths are:
	/Users/brian/perl5/lib/perl5/5.30.2/darwin-2level
	/Users/brian/perl5/lib/perl5/5.30.2
	/Users/brian/perl5/lib/perl5/darwin-2level
	/Users/brian/perl5/lib/perl5
	/usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2/darwin-2level
	/usr/local/perls/perl-5.30.2/lib/site_perl/5.30.2
	/usr/local/perls/perl-5.30.2/lib/5.30.2/darwin-2level
	/usr/local/perls/perl-5.30.2/lib/5.30.2

AutoSplit

There’s another level of directories that you might encounter. An old Perl feature, AutoSplit, would break up modules so that subroutines existed in their own files under auto/, such as auto/to_string.al. A module could load exactly the method they need when it needs it instead of compiling the entire module. This was much more interesting 25 years ago but hardly thought of now. Randy Ray wrote about it for The Perl Journal 2.2 (Summer 1997) in The AutoLoader.