Distributing Modified Perl Modules With Your Application
26 Jun2007

Pretty usually in our Perl projects we use third-party modules (CPAN or others) and sometimes we can find a bug in such module. What are our options in such cases? This small article describes some useful hints for Perl developers who have such problems.

First of all we could copy used module Xxx::YYY to our project tree, rename it to something like Xxx:MyYYY, patch and use it. This approach is not so good because we would be forced to keep this module up to date and in case of some deep upstream code changes we need to port all these changes to our code tree.

Next option is to patch upstream module in system tree (somewhere like /usr/lib/perl/…) and send patch to upstream module author. In this case everything looks fine except one thing – we need to have an access to system libraries directory and we have to patch module on all machines we use. Plus when upstream module would be updated in our system, our changes will be lost. Of course, this is not acceptable for public applications where we have no access to user’s machine.

Third (not so obvious for many developers) option will be described below.

I work on some project now where I use Net::XMPP library. It is pretty nice implementation of XMPP protocol for Perl applications, but it has some problems. Most annoying thing for me was following one: I can’t specify what server address to use when my Jabber client connects to the server. I can specify jabber domain which would be used as a server name, but for development needs and for better scalability I want to be able to specify what host to use to connect and register my jabber client. After a short investigation I found out that I need to modify two modules: Net::XMPP::Connection and XML::Stream.

Patch was pretty obvious and everything worked fine. I’m going to submit it to upstream code author soon, but at this moment next step was to choose some method to distribute the changes with my code base. Not so many Perl developers know how Perl finds modules we ask it to load with ‘use Module’ statements. If you’d try to find more information about it, you’ll find out that Perl interpreter uses @INC array to store search paths there and you can inject your own paths there in the “BEGIN {}” code section to modify default modules search behavior. If you push some path in front of other paths in this array, then Perl would try to find modules there before trying other paths (including system lib directories).

With all information given above the solution I chose was obvious: I simply created ‘lib/patched’ directory in my code tree, copied patched versions of Net/XMPP/Connection.pm and XML/Stream.pm files there and then I inserted following line to my code:

1
BEGIN { unshift @INC, '../lib/patched'; } # perl hack for patched modules

Now I can use my own patched modules till my patches would be accepted in upstream code. Then I’d be able to remove this line and my code would begin using upstream version of the modules.