A proper way of using Perl custom modules inside of other Perl modules

馋奶兔 提交于 2019-12-05 21:00:12

I strongly disagree with modifying @INC in modules. It causes all kinds of headaches. Let the script (or even the calling process via the PERL5LIB environment variable) setup @INC correctly.

script.pl:

use FindBin qw( $RealBin );
use lib
   "$RealBin/../ModulesFolder1",
   "$RealBin/../ModulesFolder2";

use ModuleInFolder1;

ModuleInFolder1.pm:

use ModuleInFolder2;  # Works fine.

As for EPIC, do the following:

  1. Right-click on the project.
  2. Properties
  3. Perl Include Path
  4. ${project_loc}/ModulesFolder1, Add to list
  5. ${project_loc}/ModulesFolder2, Add to list

(I literally mean the 14 chars ${project_loc}. That means something to EPIC. It will continue to work even if you move the project.)


PS — $RealBin is better than $Bin because it allows you to use a symlink to your script.

PS — __FILE__ is more appropriate than $INC{'ThisModule.pm'}.

Not sure about Eclipse, but you can use use lib (will probably not work, it changes @INC at compile time) or set the environment variable PERL5LIB to point to your library folder(s).

Set up PERL5LIB environment variable. Every time you use or require, Perl will check all directories listed in it.

Alternatively, place all necessary custom modules under script's directory, so you can use relative paths in use lib. It will also allow you to quickly make a bundle to transfer everything to another PC by just packing recursively from top-level directory.

Another solution (from my colleague) - a change to be made in the module:

sub path_to_current_module() {
  my $package_name = __PACKAGE__ .'.pm';
  $package_name =~ s#::#/#g;

  for my $path ( @INC ) {
    # print "\$path == '$path'\n";
    if ( -e catfile( $path, $package_name ) ) {
      return $path;
    }
  }

  confess;
}

BEGIN {
  my $path_to_current_module = path_to_current_module();
  push @INC, catdir( $path_to_current_module, qw( .. ModulesFolder1 ) );
  push @INC, catdir( $path_to_current_module, qw( .. ModulesFolder2 ) );
}

It seems that the old way (described in the question) Perl couldn't locate current module name in @INC - that's why perl -c was interrupted by error inside of the BEGIN block. And the described sub helps it to determine the real path to the current module. Besides, it doesn't depend on the current file name and can be copied to another module.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!