The right way to use custom Perl modules inside other Perl modules

I use custom modules in my scripts and must store them outside the Perl directory lib. Therefore, in Perl ( *.pl) scripts, I use the following block to include them in @INC:

BEGIN {
  use FindBin qw($Bin);
  push @INC, "$Bin/../ModulesFolder1";
  push @INC, "$Bin/../ModulesFolder2";
}

But I also have to use modules inside my other Perl ( *.pm) modules , and as far as I understand, it FindBinworks only for scripts. Therefore, I change this block to:

BEGIN {
  push @INC, catdir( dirname( $INC{'ThisModule.pm'} ), qw( .. ModulesFolder1 ) );
  push @INC, catdir( dirname( $INC{'ThisModule.pm'} ), qw( .. ModulesFolder2 ) );
}

This works, but with a little problem. I have the code in Eclipse with the EPIC plugin and "if you have something in the BEGIN block that causes the compiler to abort prematurely, it will not report EPIC syntax errors" , so I will lose the Perl syntax check in the modules.
So, with FindBin(in scripts) I do not need to use any functions (for example catdir) in the block BEGIN{}, and the syntax checking of the following code is performed correctly. In addition, I would not want to change environment variables (for example, PERL5LIB) so that I could use scripts on the computers of my colleagues without any additional preparations.

Perl , EPIC ? , , ?

+3
4

@INC . . script ( PERL5LIB) @INC.

script.pl:

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

use ModuleInFolder1;

ModuleInFolder1.pm:

use ModuleInFolder2;  # Works fine.

EPIC, :

  • .
  • Perl Include Path
  • ${project_loc}/ModulesFolder1,
  • ${project_loc}/ModulesFolder2,

( 14 ${project_loc}. - EPIC. , .)


PS — $RealBin , $Bin, script.

PS — __FILE__ , $INC{'ThisModule.pm'}.

+2

Eclipse, lib (, , @INC ) PERL5LIB, .

+1

PERL5LIB. , , Perl .

script, use lib. , .

+1

Another solution (from my colleague) is a change 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 could not find the current module name in @INC- that is why it perl -cwas interrupted by an error inside the block BEGIN. And the described auxiliary module helps to determine the real path to the current module. In addition, it does not depend on the current file name and can be copied to another module.

0
source

All Articles