Herdsman
Herdsman

Reputation: 879

perl - package name: Can I use path from root?

I am reading documentation about use. It is the same as

BEGIN{ require Namespace::NameOfModule; }

And the perl interpreter loads the module and translate the double colon :: to system path's separator (UNIX / and WINDOWS \\, if I remember correctly). I just wondered, If I am able to load module from root. Because in that case, for example module DateTime.pm in dir /home/nickname/dir. It would be (according to double colons rule) ::home::nickname::dir, which is wrong (like it should even look like terrible package path). So how - if even - is possible to load a module from root dir? And Does the path starts from current dir by default? (That is from dir where is the perl script located in), or only from @INC dirs?

Upvotes: 0

Views: 386

Answers (2)

ikegami
ikegami

Reputation: 386676

Even if you could load the module like that, you'd have numerous other problems.

  • The module's package directive would have to be package ::home::nickname::dir::SomeModule; for import to be found.
  • You'd have to use ::home::nickname::dir::SomeModule->some_method to call a static method.
  • You'd have to use ::home::nickname::dir::SomeModule::some_sub to call a sub.

That's obviously the wrong approach.

For modules installed in a position relative to a script, use the following in the script to tell perl where to look:

use FindBin qw( $RealBin );
use lib "$RealBin/../lib";  # Or whatever.

For modules installed for any script to use, use the following environment variable:

export PERL5LIB="$HOME/dir"  # Or whatever.

Upvotes: 2

Grinnz
Grinnz

Reputation: 9231

The module namespace is relative to @INC directories only. These are by default set up according to where Perl was installed, with privlib (core modules installed with Perl), sitelib (modules installed by a CPAN client), and vendorlib (modules installed by a vendor package manager), and architecture-specific versions of each of these. Additional @INC directories may be added by local::lib, and before Perl 5.26 @INC also included . (the current working directory), but this was a bad idea.

When you invoke use or require on a bareword package name, it does the translation you described (convert :: to path separator and append .pm), and then appends it to each directory in @INC until it finds a file. (It also checks for .pmc but this is rarely relevant.) The package statement inside the file is expected to match the module path used to look it up for the import component of use.

You can modify @INC manually, but it is best to do it with one of the following mechanisms, so that architecture-specific and version-specific subdirectories will be respected if present.

  • lib - use lib '/path/to/lib';
  • -I - perl -I/path/to/lib ...
  • PERL5LIB - env PERL5LIB=/path/to/lib perl ...

These options should only be used to insert absolute paths into @INC, since relative paths will have the same vulnerability as . used to, in that they may mean something different when the current directory is changed. To add a path relative to the script wherever it may be, lib::relative can be installed to simplify the process, or its documentation describes equivalent functionality using core modules.

use lib::relative '../lib';

Once you have added your custom location(s) to @INC, that directory will be searched first for any further use calls.

use Foo::Bar; # now checks /path/to/lib/Foo/Bar.pm first
# which should contain package Foo::Bar

Upvotes: 5

Related Questions