alegria
alegria

Reputation: 1482

A Perl script and a Perl module are using `use lib` and referencing the same module

I have a Perl script that is using two modules. The first module also uses the second module.

If the first module does use lib 'dir1', and the script does use lib 'dir2':

module1.pm

use lib "dir1";
use module2;

script.pl

use lib "dir2";
use module1;
use module2;

which directory is being used by the first module? Does the script's use lib, 'dir2' override the use lib, 'dir1' in the first module, or do they have different scope?

I did my own testing, and printed the @INC inside module1.pm and script.pl, the result was the dir1 was at the top of @INC.

Upvotes: 1

Views: 9006

Answers (3)

Miller
Miller

Reputation: 35198

You obviously know that lib works on the @INC array. However, you appear to be thinking of it as an array of a single value that is replaced by subsequent usage.

Borodin's already explained the mechanisms well, and the docs for lib do an even better job. However, perhaps a little example script will help:

use strict;
use warnings;

use Data::Dump qw(dump);

# Set @INC to minimum required for lib
BEGIN {
    require lib;
    @INC = $INC{'lib.pm'} =~ s/lib.pm//r;
    print "\@INC = " . dump(@INC) . "\n\n";
}

# Try adding two directories

use lib 'foo';
BEGIN {
    print "use lib 'foo';\n";
    print "# \@INC is " . dump(@INC) . "\n\n";
}

use lib 'bar';
BEGIN {
    print "use lib 'bar';\n";
    print "# \@INC is " . dump(@INC) . "\n\n";
}

# Remove a directory

no lib 'foo';
BEGIN {
    print "no lib 'foo';\n";
    print "# \@INC is " . dump(@INC) . "\n";
}

Outputs:

@INC = "C:/strawberry/perl/lib/"

use lib 'foo';
# @INC is ("foo", "C:/strawberry/perl/lib/")

use lib 'bar';
# @INC is ("bar", "foo", "C:/strawberry/perl/lib/")

no lib 'foo';
# @INC is ("bar", "C:/strawberry/perl/lib/")

Upvotes: 2

Borodin
Borodin

Reputation: 126722

The lib pragma just does an unshift of the path onto the global (and package-independent) array @INC. Nothing is ever removed from @INC unless it is done explicitly.

The first time it is encountered is on the first line of the script.pl, so thereafter @INC will contain dir2.

The next thing that happens is that script.pl compiles and runs module1.pm. (It will look for it in dir2 first, and then in the directories that were originally in @INC.) The first line of that file contains another use lib, which will unshift @INC, 'dir1'.

Thereafter @INC stays the same. Any further use or require will look in dir1 first (because it was shifted last) then dir2, and then in the rest of @INC.

Upvotes: 3

imran
imran

Reputation: 1560

See the perl doc on use lib: http://perldoc.perl.org/lib.html

When script.pl runs, it will prepend "dir2" to @INC. It will then look for module1 in the directories listed in @INC starting with "dir2".

When it is loading module1, it will prepend "dir1" to @INC and then look for and load module2 in the directories now listed in @INC, which starts with dir1, then dir2 and then the remaining directories in @INC. Once it has loaded module2, it will finish loading module1.

The use module2 line in script.pl will be ignored at this point.

Upvotes: 1

Related Questions