Reputation: 641
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
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