Reputation: 71
We're the authors of a large, complex Perl software product. Some of the code is in executables (network daemons), and some in Perl libraries (.pm files). Some of our customers want to customise their systems by overriding our Perl 'sub xxx {}' functions with code of their own. This is fairly straightforward to do when we invoke a function in another library - we put /usr/local/lib/our_product in @INC, and they can put their custom code there. There are two problems with this:
The custom file they create needs to have every function in the .pm file they're overriding. If any are missing, Perl won't find them in the default .pm file that we ship.
Perl always checks the local file before @INC. This prevents their custom .pm file from overriding function invocations within the same file.
Are there ways around these problems?
Upvotes: 2
Views: 111
Reputation: 132720
When I've done this for legacy code, I've created a package with a different name that will load the vendor packages first, then allow for overrides:
package Local::Overrides;
use Vendor::Real::Name;
use Vendor::Other::Name;
package Vendor::Real::Name {
no warnings 'redefine';
sub new_definition {
}
};
package Vendor::Other::Name {
no warnings 'redefine';
sub new_definition {
}
};
1;
You would then distribute an empty module of the same name and every script would always load this module:
package Local::Overrides;
1;
I cover some of this sort of thing in Effective Perl Programming.
There are plenty of other tricks, but without knowing the specifics of your architecture, there's not much I can recommend.
Upvotes: 3
Reputation: 9231
There is really no need for their custom code to be in files matching the package names, and thus replacing or having to cooperate with its loading from @INC
. You could just arrange for the custom code to be loaded after, from a different file which still modifies the original packages. It would have to happen before any importing from that package of course, and you will want to turn off redefine
warnings in such a file.
# Whatever.pm
package Some::Module;
use strict;
use warnings;
no warnings 'redefine';
sub foo { ... }
Overrides may even leverage Class::Method::Modifiers which is capable of replacing subs with a wrapper in place, even though there are no classes or methods involved.
use Class::Method::Modifiers;
around 'Some::Module::foo' => sub { ... };
The biggest hammer if you really don't want to modify the existing files in any way could be sitecustomize which is described here, or App::MyPerl which is a slightly more focused version of that.
Upvotes: 2