ericyoung
ericyoung

Reputation: 641

How to include BEGIN section in a perl script

I have a bunch of perl scripts, each of them needs to have an identical BEGIN section, which adds to @INC the path of perl modules we developed. Because it is not a sub, I cannot simply call it. Currently I inlcude this section in every perl script, which is obviously a headache to maintain. Is there a easier way to include the BEGIN section?

BEGIN
{
     my $current_script_dir = File::Basename::dirname(File::Spec::Functions::rel2abs($0));

     # Assume that the root of all libraries is two levels up from the directory of the 
     # script being run.

     my $all_libs_root = File::Spec->canonpath("$current_script_dir/../..");

     # Make sure the path is absolute,      
     $all_libs_root = File::Spec->rel2abs($all_libs_root);

     unshift(@INC, "$all_libs_root");
} 

Upvotes: 3

Views: 449

Answers (1)

DVK
DVK

Reputation: 129433

Yes. You can simply put that code (that would go into BEGIN) into a new Perl module.

package MyIncPathMaintenance;
push @INC, "something_bvaluable";
1;

Then, all your scripts merely need to do:

use MyIncPathMaintenance;

as their first line after shebang and use strict

This works, because use XYZ is equivalent to BEGIN { require XYZ; XYZ->import() } (source); whereas that require will execute the module's code (including your @INC manipulation) as if it was eval-ed (source).

This approach has a number of benefits over BEGIN + @INC change:

  • It's a lot more maintainable going forward. Any changes to you path (or adding a new path) are encapsulated in the module, instead of being copied/pasted across tons of scripts

  • It encapsulates away somewhat advanced functionality that may be a bit dangerous to expose to junior developers who don't know what they are doing and can break it ("hey, I'll just add my home directory to this path so I can run my ad-hoc library version without core review/testing/releasing SDLC").

  • It allows more fancy logic in the script down the line (in our case, the module automagically prepends BETA library paths for BETA scripts).


To address the question of "where does MyIncPathMaintenance.pm go?", it depends on your environment. You can find a detailed discussion of how @INC is built here: How is Perl's @INC constructed? (aka What are all the ways of affecting where Perl modules are searched for?)

including what your Perl interpreter's default @INC is and how you can affect it via environmental variables.

Upvotes: 8

Related Questions