Why is prefix=/path/to/perllib not enough to set PERL5LIB? - perl

If I create a Perl module and install it as
perl Makefile.PL prefix=/path/to/perllib
Then I would expect to be able to set PERL5LIB to /path/to/perllib and the module be found. This doesn't seem to be the case. The module gets installed to /path/to/perllib/site_perl/5.8.5/, so that's what PERL5LIB has to be set to (or passed to "use lib").
Am I doing something wrong in how I install the modules or how I set PERL5LIB?

You're conflating PREFIX= and LIB=.
A distribution consists of more than just modules. Documentation, for one, isn't installed in the same directory as the modules themselves. PREFIX= tells Perl the base path for all components.
LIB= tells Perl where to install modules.
Use (for example)
perl Makefile.PL PREFIX=~ LIB=~/lib/perl5
Then you'd use
export PERL5LIB=~/lib/perl5

No, that's how it works. The prefix indicates the root of the installation, but the library directories are usually somewhere deeper within that directory structure.
If you install multiple modules with the same prefix, they should all be able to use the same PERL5LIB value, though.

Long story short, use INSTALL_BASE instead of PREFIX. It works more like the --prefix of other installers and creates a predictable install pattern. Then you can set PERL5LIB to <INSTALL_BASE>/lib/perl5 and go.
ExtUtils::MakeMaker::FAQ explains:
The behavior of PREFIX is complicated and depends closely on how your Perl is
configured. The resulting installation locations will vary from machine to machine
and even different installations of Perl on the same machine. Because of this, its
difficult to document where prefix will place your modules.
In contrast, INSTALL_BASE has predictable, easy to explain installation locations.
Now that Module::Build and MakeMaker both have INSTALL_BASE there is little reason
to use PREFIX other than to preserve your existing installation locations. If you
are starting a fresh Perl installation we encourage you to use INSTALL_BASE. If you
have an existing installation installed via PREFIX, consider moving it to an
installation structure matching INSTALL_BASE and using that instead.

What version of perl? You should only have to specify the path up to 'site_perl'. For libraries not under site_perl, you should also specify the path up to 'perllib'. More recent versions of perl (5.8 or better?) are better at letting you specify only these two directories, without having to specify version and architecture directories.

Related

How is local::lib supposed to handle XS and different versions of Perl?

I love the idea of local::lib. At least, I find it preferable to the default system-wide installs that cpan/perl defualts to in most every way. However, I'm having difficulties with modules that install XS and distribution upgrades to newer Perls. The instructions for local::lib call for adding this line to your .bashrc (or like file)
eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)"
That executes arbitrary shell code, which is fine. You can see the code it executes by running
perl -I$HOME/perl5/lib/perl5 -Mlocal::lib
In my case it returns this code,
PATH="/home/ecarroll/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/home/ecarroll/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/ecarroll/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/ecarroll/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/ecarroll/perl5"; export PERL_MM_OPT;
In the above, we're setting the default options for the two most widely used module build systems,
MB is for Module::Build
MM is for ExtUtils::MakeMaker
We're telling those system to install to /home/ecarroll/perl5. The rest of the command sets
PERL5LIB which is used in setting #INC. The #INC variable in Perl is used to resolve calls with use.
and, PATH which prepends the bin/ directory that local::lib installs to.
So basically, install perl modules in your home directory, and look first for files installed in your home directory.
My question is what happens when you install something that has XS? In my case, I have an XS file,
/home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Class/Load/XS/XS.so
This was installed, with local::lib using an earlier version of Perl. I've since ran a Debian dist-upgrade and got a newer version of Perl (v5.36). Now a lot of utilities produce an obtuse error about this, including ones installed through the distro itself like in my case Dist::Zilla dzil which I installed with Debian's libdist-zilla-perl package.
$ dzil
XS.c: loadable library and perl binaries are mismatched (got first handshake key 0xeb00080, needed 0xeb80080)
Which is all a result of this module's XS,
perl -MClass::Load::XS -e1
XS.c: loadable library and perl binaries are mismatched (got first handshake key 0xeb00080, needed 0xeb80080)
This seems like very routine use of local::lib:
Am I using local::lib in the way intended? What else should I be doing?
How is local::lib supposed to handle XS?
Is there a way to make local::lib support multiple versions of Perl? My distro reads and writes the XS it manages to /usr/share/perl/$PERL_VERSION. This means a dist-upgrade leaves all the XS from the old version behind. It would be nice to have local::lib install not to /home/ecarroll/perl5/lib/perl5/ but instead to /home/ecarroll/perl5/lib/perl5.30/? Note the added minor version. Then at least a dist-upgrade wouldn't break the distribution.
Perl doesn't maintain ABI compatibility between versions. (5.34.x -> 5.36.y, for example.) After installing a new version of Perl, you will need to re-install modules that install themselves in arch dirs (XS modules and a few others). Might be easiest and safest to remove (rename) the local lib directory (/home/ecarroll/perl5) and start from scratch.
That's why I avoid using anything but distro-provided modules with distro-provided perl. The package manager ensures you always have compatible builds of the modules.
If that's not good enough, I recommend installing your own builds of perl instead of using local::lib. Tools like perlbrew makes this easy. You'll still have to re-install all the modules when you install a new perl, but you'll get the cleaner "Can't locate" error message if you forget one.
I rarely use local::lib, but I'm also a minimalist when it comes to administration. The more layers you have, the worse things get. As you see, you're own answer (now deleted) proposes even more complexity to deal with complexity that isn't likely appropriate for your situation.
But, local::lib has a way to set the locations of everything. You are trying to use the same location for everything instead of changing the locations based on what you are trying to do. However, even though local::lib lets you do that, you're likely to forget to switch things up.
My solution is simpler. I merely install a perl for whatever I'm doing (or reuse a suitable perl). I don't change the default locations at all. I never have to manage that. I simply call the perl I want:
$ ls -d /usr/local/perls/*
/usr/local/perls/perl-5.10.1 /usr/local/perls/perl-5.24.3 /usr/local/perls/perl-5.32.0
/usr/local/perls/perl-5.12.5 /usr/local/perls/perl-5.26.1 /usr/local/perls/perl-5.32.1
/usr/local/perls/perl-5.14.4 /usr/local/perls/perl-5.26.2 /usr/local/perls/perl-5.34.0
/usr/local/perls/perl-5.16.3 /usr/local/perls/perl-5.28.0 /usr/local/perls/perl-5.34.1
/usr/local/perls/perl-5.18.4 /usr/local/perls/perl-5.30.0 /usr/local/perls/perl-5.35.11
/usr/local/perls/perl-5.20.3 /usr/local/perls/perl-5.30.1 /usr/local/perls/perl-5.36.0
/usr/local/perls/perl-5.22.4 /usr/local/perls/perl-5.30.2 /usr/local/perls/perl-5.8.9
I have various symlinks and stable path adjustments to I use the tool name and the version tag I gave it:
% cpan5.36.0 ...
% cpan5.32.1 ...
People use all sorts of tools such as perlbrew, plenv, and now some other tool that you think might solve it. It's a big red flag if you have to constantly create new tools to deal with the tools that you are using. I'd rather spend my time doing something else.
I stand by my other answer—this is too much complexity and you should reduce that. But, lets work with that constraint. You want to use local::lib.
The problem is that you are trying to force the same set of modules on any particular perl, no matter how it was compiled. As ikegami explained, you can't assume that two different perls, or the same library compiled with different perls, are compatible. The version of the perls does not matter. Two different perl5.36, or any version, can be incompatible with each other.
But local::lib gives you what you need to set the appropriate values. The module itself can supply some starter values:
$ perl -I$HOME/perl5/lib/perl5 -Mlocal::lib
Attempting to create directory /Users/brian/perl5
PATH="/Users/brian/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/Users/brian/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/Users/brian/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/Users/brian/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/Users/brian/perl5"; export PERL_MM_OPT;
But, you don't need to use those values everywhere. You can have as many sets of those variables as you like. You can have a different set for every project, every perl, or however you want to organize it. The only trick is how you select the right set.
The synopsis of local::lib indicates that it expects you to set the appropriate value for your project:
use FindBin;
use local::lib "$FindBin::Bin/../support"; # app-local support library
Knowing that, you can have your per-version libraries by adding $^V in the path you give to local::lib (still with the binary incompatibility problems):
use FindBin;
use local::lib "/my/modules/$^V";

What is the difference between the core, vendor and site locations in Perl?

I recently ran into some trouble installing some modules and discovered to my surprise that many of the modules that had been installed, have duplicated installations and versions. Trying to track where stuff goes in a standard (if there is such a thing) installation using cpanm, I found the following results very confusing.
The reports show these locations:
Using cpan -V:
# cpan -V
/usr/bin/cpan script version 1.672, CPAN.pm version 2.22
--------------------------------------------------
Checking install dirs...
Checking core
+ /usr/share/perl5/5.26
+ /usr/lib/perl5/5.26/x86_64-cygwin-threads
Checking vendor
+ /usr/share/perl5/vendor_perl/5.26
+ /usr/lib/perl5/vendor_perl/5.26/x86_64-cygwin-threads
Checking site
+ /usr/local/share/perl5/site_perl/5.26
+ /usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads
Checking PERL5LIB
no directories for PERL5LIB
Checking PERLLIB
no directories for PERLLIB
Using perl -V:.*site.*:
# perl -V:.*site.* |column -t -s "=" |sort -d -i -k 1.22
d_sitearch 'define';
usesitecustomize 'undef';
siteprefix '/usr/local';
siteprefixexp '/usr/local';
installsitebin '/usr/local/bin';
installsitescript '/usr/local/bin';
sitebin '/usr/local/bin';
sitebinexp '/usr/local/bin';
sitescript '/usr/local/bin';
sitescriptexp '/usr/local/bin';
installsitearch '/usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads';
sitearch '/usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads';
sitearchexp '/usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads';
installsitehtml1dir '/usr/local/share/doc/perl/html/html1';
sitehtml1dir '/usr/local/share/doc/perl/html/html1';
sitehtml1direxp '/usr/local/share/doc/perl/html/html1';
installsitehtml3dir '/usr/local/share/doc/perl/html/html3';
sitehtml3dir '/usr/local/share/doc/perl/html/html3';
sitehtml3direxp '/usr/local/share/doc/perl/html/html3';
installsiteman1dir '/usr/local/share/man/man1';
siteman1dir '/usr/local/share/man/man1';
siteman1direxp '/usr/local/share/man/man1';
installsiteman3dir '/usr/local/share/man/man3';
siteman3dir '/usr/local/share/man/man3';
siteman3direxp '/usr/local/share/man/man3';
installsitelib '/usr/local/share/perl5/site_perl/5.26';
sitelib '/usr/local/share/perl5/site_perl/5.26';
sitelib_stem '/usr/local/share/perl5/site_perl/5.26';
sitelibexp '/usr/local/share/perl5/site_perl/5.26';
Using #INC:
# perl -e 'print join("\n",#INC,"")'
/usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads
/usr/local/share/perl5/site_perl/5.26
/usr/lib/perl5/vendor_perl/5.26/x86_64-cygwin-threads
/usr/share/perl5/vendor_perl/5.26
/usr/lib/perl5/5.26/x86_64-cygwin-threads
/usr/share/perl5/5.26
The result is that cpan-outdated -p --verbose show a completely different (and shorter) list of outdated modules than what cpan -lO does. Needless to say, modules are installed all over the place and I don't see how to understand if there is a default install location and where it goes, or should go.
QUESTION:
So what is the difference between the core, vendor and site type of paths?
Why are there 2 paths in each type?
The best reference for these install locations is probably the ExtUtils::MakeMaker documentation for where it installs things. In essence:
core (also known as privlib) - is where core modules that are installed with Perl goes. On Perls older than 5.12, updates to dual-life modules also need to be installed here over the core versions instead of into site or vendor lib, because privlib came first in #INC before 5.12. This is especially dangerous in a system Perl where the files in privlib are usually managed by a package manager.
vendor - is where a distribution vendor may install modules to. This is usually where system package managers install non-core modules to.
site - is where CPAN clients install modules to when invoked directly, barring unusual configuration like for dual-life modules as mentioned above.
(Dual-life modules are core modules which are also available separately on CPAN, which means that you can install an updated version.)
Each of these lib locations have an arch variant, which is where distributions with build-specific output files are installed to. Pure-perl distributions with no dynamic configuration are installed into the standard architecture-agnostic directory, and can usually run unmodified in other installations of Perl and architectures provided their requirements are still satisfied (though it's not a good idea unless you really know what you are doing). Distributions with any compiled XS modules or that generate modules dynamically in the build process are installed into the arch directory and are not safe to use from another Perl.
All of these locations are configured when the Perl is built and can be discovered using the perl -V option as you showed. They also each have accompanying script and bin directories (which are usually the same) and directories for manpages.
As to the discrepancy of cpan-outdated - this tool (like many tools using ExtUtils::Installed) is restricted to finding modules that have packlists, which are included when installing a module using a CPAN client, but not with core modules and they are generally stripped from vendor packages. So most likely cpan-outdated will only discover modules in sitelib, but this is usually all you need to find. I'm not sure what mechanism the cpan command uses.
UPDATE:
Thanks to ikegami's SO link, I have since done some source browsing, where we can find a lot of info about this. To get the more specific locations:
# perl -V:'install(privlib|archlib|vendorlib|vendorarch|sitelib|sitearch)' |column -t -s "="
installarchlib '/usr/lib/perl5/5.26/x86_64-cygwin-threads';
installprivlib '/usr/share/perl5/5.26';
installsitearch '/usr/local/lib/perl5/site_perl/5.26/x86_64-cygwin-threads';
installsitelib '/usr/local/share/perl5/site_perl/5.26';
installvendorarch '/usr/lib/perl5/vendor_perl/5.26/x86_64-cygwin-threads';
installvendorlib '/usr/share/perl5/vendor_perl/5.26';
Then for the meaning of those, we can look (in the perl sources) in the file: ./Porting/Glossary:
installarchlib '- is the same for modules with arch- or build-dependent components.'
installprivlib '- contains the "pure Perl" modules that came with Perl.'
installsitearch '- is the same for modules with arch- or build-dependent components.'
installsitelib '- contains the "pure Perl" modules installed by you.'
installvendorarch '- is the same for modules with arch- or build-dependent components.'
installvendorlib '- contains the "pure Perl" modules installed by your distro.'
with the additional interesting note about the installstyle option:
installstyle (installstyle.U):
This variable describes the style of the perl installation. This
is intended to be useful for tools that need to manipulate entire perl
distributions. Perl itself doesn't use this to find its libraries --
the library directories are stored directly in Config.pm. Currently,
there are only two styles: lib and lib/perl5. The default
library locations (e.g. privlib, sitelib) are either $prefix/lib or
$prefix/lib/perl5. The former is useful if $prefix is a
directory dedicated to perl (e.g. /opt/perl), while the latter is
useful if $prefix is shared by many packages, e.g. if
$prefix=/usr/local.
Unfortunately, while this "style" variable is used to set defaults for
all three directory hierarchies (core, vendor, and site), there is no
guarantee that the same style is actually appropriate for all those
directories. For example, $prefix might be /opt/perl, but
$siteprefix might be /usr/local. (Perhaps, in retrospect, the "lib"
style should never have been supported, but it did seem like a nice
idea at the time.)
The situation is even less clear for tools such as MakeMaker that can
be used to install additional modules into non-standard places. For
example, if a user intends to install a module into a private
directory (perhaps by setting PREFIX on the Makefile.PL command line),
then there is no reason to assume that the Configure-time
$installstyle setting will be relevant for that PREFIX.
This may later be extended to include other information, so be careful
with pattern-matching on the results.
For compatibility with perl5.005 and earlier, the default setting is
based on whether or not $prefix contains the string "perl".
All the gritty details can then be found in the INSTALLATION file, under the Installation Directories heading.
Directories for the perl distribution:
By default, Configure will use the following directories (5.28.1):
Configure variable Default value
$prefixexp /usr/local
$binexp $prefixexp/bin
$scriptdirexp $prefixexp/bin
$privlibexp $prefixexp/lib/perl5/$version
$archlibexp $prefixexp/lib/perl5/$version/$archname
Directories for site-specific add-on files:
Configure Default
variable value
$siteprefixexp $prefixexp
$sitebinexp $siteprefixexp/bin
$sitescriptexp $siteprefixexp/bin
$sitelibexp $siteprefixexp/lib/perl5/site_perl/$version
$sitearchexp $siteprefixexp/lib/perl5/site_perl/$version/$archname
Directories for vendor-supplied add-on files:
If are building a binary distribution of perl for distribution, Configure
can optionally set up the following directories for you to use to
distribute add-on modules.
Configure Default
variable value
$vendorprefixexp (none)
(The next ones are set only if vendorprefix is set.)
$vendorbinexp $vendorprefixexp/bin
$vendorscriptexp $vendorprefixexp/bin
$vendorlibexp $vendorprefixexp/lib/perl5/vendor_perl/$version
$vendorarchexp $vendorprefixexp/lib/perl5/vendor_perl/$version/$archname
otherlibdirs:
As a final catch-all, Configure also offers an $otherlibdirs variable.
This variable contains a colon-separated list of additional directories
to add to #INC. By default, it will be empty.
APPLLIB_EXP:
There is one other way of adding paths to #INC at perl build
time, and that is by setting the APPLLIB_EXP C pre-processor
token. The directories defined by APPLLIB_EXP get added to
#INC first, ahead of any others.
sh Configure -Accflags='-DAPPLLIB_EXP=\"/usr/libperl\"'

Non Perl files that need to be installed with CPAN distribution?

I need to have files installed with my CPAN dist that aren't Perl. Where in the dist should I put them? and what's the best way to reference them from within a module so that I have access to them regardless of users configuration?
Well, you're not very clear on what these files are and how they're used, but you're probably looking for File::ShareDir.
File::ShareDir only takes care of the run-time access to the files from your module. The way you get the files installed along with your module depends on which install system you use:
If you use Dist::Zilla, you use its ShareDir plugin, which has an undocumented dir parameter that defaults to share.
For Module::Build, you use the share_dir parameter.
For Module::Install, you use the install_share command.
ExtUtils::MakeMaker doesn't have built in support, but you can use the File::ShareDir::Install module to add it.

Is there a way to avoid putting the Perl version number into the "use lib" line for Perl modules in non-standard locations?

I am trying to install some Perl modules into a non-standard location, let's call it /non/standard/location. I used
perl Makefile.PL PREFIX=/non/standard/location
make;make install
to install them.
In the script which uses the module, it seems to be necessary to specify a long directory path including the version of Perl, like so:
#!/usr/local/bin/perl
use lib '/non/standard/location/lib/perl5/site_perl/5.8.9/';
use A::B;
Is there any use lib or other statement which I can use which is not so long and verbose, and which does not include the actual version of Perl, in order that I don't have to go back and edit this out of the program if the version of Perl is upgraded?
Probably not addressing all your questions, but do you know local::lib? When it’s available in the system perl, you can just use local::lib. If not:
use lib glob '~/perl5/lib/perl5';
use local::lib;
That’s probably a bit constraining – not sure how it works on Windows –, but it’s good enough for my purposes. Of course, if you can set up the environment before the script runs (.bashrc, SetEnv etc.), you can forget about the use lib glob, as the right path will be already set in PERL5LIB.
Currently I have installed via the following prescription, which seems to fix things.
perl Makefile.PL --no-manpages --skipdeps PREFIX=/non/system/location INSTALLSITELIB=/non/system/location/lib INSTALLSITEBIN=/non/system/location/bin INSTALLMAN1DIR=/non/system/location/man/man1 INSTALLMAN3DIR=/non/system/location/man/man3
I welcome any constructive criticism of this. I want to use --no-manpages but the INSTALLMAN1DIR seems to be necessary anyway.

How can I create a portable perl when I can't install modules on the target host?

I need to run Perl applications I develop on cygwin Windows on HP unix / Solaris hosts. I am not a superuser on the unix machines and I can't touch the default Perl module location nor can I install modules to the default Perl module location. Also the unix installation lacks most basic modules and I can't change that.
For example, I have a Perl application that needs Expect which has native C compiled parts to it. How would I roll out this application to unix with its required dependencies without having to install anything else on that box?
Is there way to build the entire Perl application under Cygwin Windows and then just roll out one executable to unix and run it from my home directory there?
EDIT addition based on answers so far:
Thanks in particular to brian, the local LIB dir solution seems to work in case of native Perl, but in case of Perl module needing C components, cross platform compiling, ie compiling on cygwin to run on Solaris, is not really possible as I feared.
However would having an other linux installation help, i.e. would this be possible easier between different flavors of Unix like package Perl on linux and then deploy to Solaris/HP? And what about something like lcc ?
Also I'd still like to hear little more if somebody has rolled out a native Perl package on Windows that includes all dependencies for a complicated Perl app that can then be moved to unix as just one file? (I do now understand that it won't work in case native C code is included like in in Expect.pm, but what about in case of app only using pure perl modules?)
Basically for many reasons I am trying to minimize time I need to spend being logged into these "production" unix hosts and do as much as possible locally beforehand.
Added a new cross-compile question, since I felt I was maybe veering too far from the original perl question.
EDIT -- Par looks promising for pure Perl, although same deal, it doesn't look to solve the cross platform compile problem for native extensions
In this case, I'd consider delivering a complete application complete with its own Perl. You get to choose any version you like and any modules you like. Compile everything, organize everything into a directory, then tar the result. To deploy, copy the file and untar. Use the advice that others have already noted about library search paths, etc. In essence, your application gets its own stack.
Now, the trick there is the cross compilation. Why are you developing on Cygwin? Is that a target too? Is there a reason you don't have an HP/UX or Solaris development machine? What architecture are you targeting (RISC, SPARC, Intel, etc). If you can't get hardware to run those, get some virtual machines for your targets and develop there.
Aside from that, you can install modules anywhere you have permissions. See perlfaq8:
How do I keep my own module/library directory?
How do I add the directory my program lives in to the module/library search path?
How do I add a directory to my include path (#INC) at runtime?
I haven't tried this particular feature, but perl2exe says it supports cross platform builds.
Compiling a Perl script with all its dependencies on Windows with Cygwin and running it Solaris is just not going to work.
Now the question is: do you have access to a compiler on that Solaris computer? It's not because you do not have root access that you cannot compile and install Perl modules in your home directory by using:
perl Makefile.PL PREFIX=$HOME
If you have CPAN available on your Solaris system you can set the prefix in the CPAN shell this way:
start the shell perl -MCPAN -e shell;
change the prefix with conf makepl_arg PREFIX=/path/to/your/home/directory
For your script to run, you can either start perl with the -I $HOME command-line switch, e.g.:
perl -I $HOME script.pl
Your other option would be to place this at the begining of your script
use lib $ENV{'HOME'};
Set your environment variable PERLLIB to your personnal Perl lib directory or use the -I command line switch to Perl to indicate it.
If you have access to the HP-UX machine you can compile Expect there and install it in your directory. But cross compilation from Windows to HP-UX is probably much more difficult. You would have to build a GCC cross compiler.
If you have a compiler on each of your systems (and some other tools needed by configure like grep), you should not only be able to compile modules, but you should also be able to build your own perl executables.
You'll want local::lib. Once you've done that, the pure Perl modules should work cross platform, but you'll have to identify and reinstall the compiled modules on the foreign platform. Do the initial install on a real unix, cpan on cygwin is slow.
I've run across this several times on my work systems. We have a base install of Perl 5.8 and I don't have the ability to add modules. Here's the solution I use:
Create a folder called 'lib' in your
project root (ex:
~/projects/MyProject/lib)
Any
modules you download from CPAN
should have a Makefile as well as a
directory called "lib". Copy the contents of the lib folder into your newly created lib folder. Some modules may only contain a single .pm file, and no lib structure. Just copy the .pm file.
Your code should do the following: first, use any modules that have been installed normally, then unshift your #INC environment variable to use your local libraries:
# Declare Includes --------------------------------------------------------------------------------
use Getopt::Long;
use vars qw($VERSION);
use DirHandle;
use FileHandle;
# Force perl to use our local 'lib' directory for imported modules, this allows us to
# use modules without having to install them in th emain perl assembly. However, this
#also prevents these modules from being used in other projects.
BEGIN { unshift #INC, "lib"; }
use Error qw(:try);
use SOAP::Transport::HTTP;
#use LWP::Protocol::https;
use XML::Simple;
use XML::Writer;
use XML::Writer::String;
The caveat to this method is that some Perl modules don't use the 'lib' method or have additional dependencies. If you run into problems, examine the Makefile.PL for the module and see what it's doing.