Perl - Modules and path on disk

I don't know if you have ever wondered where a module that you have been using is installed. Working in a corporate with multiple operating systems and having to maintain data update systems on multiple platforms that run on Perl based scripts, you might have to make sure that the CPAN modules you use are of the same versions, to keep your code portable. So recently I ran across one of these problems and came up with some interesting solutions as suggested by my colleague. I didn't understand what I was doing at the time. So I took a break and tried to understand how I actually got to know what it was.

So in order to find out where a Perl module lives you have to run the following:
$ perl -MModuleDir::ModuleName -e 'print $INC{"ModuleDir/ModuleName.pm"}'
Wow! what sorcery was that? Cool isn't it? So what does all mean?
In Perl
@INC
and
%INC
stores information about modules and their locations. This is where the interpreter knows where to look for a module. The array stores the different paths that Perl would look for, to find modules. The hash contains the module name and the file it was loaded from, which is where the module lives. Now you must be wondering but the module name should be something like
ModuleDir::ModuleName
and not
ModuleDir/ModuleName.pm
. Yea, you are right, your argument is perfectly sensible. But Perl doesn't store things in the hash like that. It does it as if it was a file specification. So good luck finding your module's path the other way :).
So in order to explain more about what that magical line of code means, you have to know what the -M option does or means. So I'm borrowing something from the official Perl documentation perlrun:
-m[-]module
-M[-]module
-M[-]'module ...'
-[mM][-]module=arg[,arg]...

-mmodule executes use module (); before executing your program.

-Mmodule executes use module ; before executing your program. You can use quotes to add extra code after the module name, e.g., '-MMODULE qw(foo bar)'.

If the first character after the -M or -m is a dash (-) then the 'use' is replaced with 'no'.

A little builtin syntactic sugar means you can also say -mMODULE=foo,bar or -MMODULE=foo,bar as a shortcut for '-MMODULE qw(foo bar)'. This avoids the need to use quotes when importing symbols. The actual code generated by -MMODULE=foo,bar is use module split(/,/,q{foo,bar}) . Note that the = form removes the distinction between -m and -M.

A consequence of this is that -MMODULE=number never does a version check, unless MODULE::import() itself is set up to do a version check, which could happen for example if MODULE inherits from Exporter.
That should be clear, because I really can't explain it any better. So I will leave it there. Going ahead to explore what -e means when passed to perl. You could find more about it from the perl documentation itself. But this time I have a simpler way to say it, it basically tells perl that you are writing a one-liner and not asking perl to run a program from a script.

I hope that helps.

Comments