A recent question here on SO got me thinking.
On most Linux distributions that I tried, some Perl modules would be available through the package manager. Others, of course, not. For quite a while I would use my package manager whenever I needed to install some CPAN module to find out whether a package was available or not and to install it when it was.
The obvious advantage is that you get your modules updated whenever a new version of the package becomes available.
However, you get in trouble when the module is not available in pre-packaged form and there are dependencies for that module that are. Firing up your package manager every time the cpan shell asks whether it should follow a dependency can be quite tiring.
Often, another drawback is the version of the pre-packaged module. If you are running Debian or Ubuntu you will soon find out that you will not be able to live on the bleeding edge, like many CPAN module authors seem to do.
How do other Perl people on Linux handle that problem? Do you just ignore what your package managers have to offer? Are there any tools that make apt (for example) and cpan better team mates? Or do you simply not install anything via the cpan shell?
A package is a collection or code group in Perl. Meanwhile, a module in Perl is a package defined in a file with the name “package” and the the extension . pm. We can only define the package once in a program; whereas, more than one different module can have the same name in a single code file.
To install Perl modules using CPAN, you need to use the cpan command-line utility. You can either run cpan with arguments from the command-line interface, for example, to install a module (e.g Geo::IP) use the -i flag as shown.
Quick start: at the PPM command prompt, type ' search ' to get a listing of all available packages, then type ' install <packagename> ', where <packagename> is the name of a package displayed by the ' search ' command. To list the packages you have previously installed using PPM, use the ' query ' command.
For development, I install my own Perl and leave the system Perl alone. If I want to upgrade the system Perl, I use the system package manager. For my development Perl, I use the cpan tool.
Since I keep those separate, I should never mess up the Perl that the system needs for its maintenance tasks and so on, but I don't have to rely on the system's decisions for development.
It's very easy to install separate Perls. When you run Configure from the source distribution, it will ask you where you want to install everything. Give it any path that you like. I have many Perls installed in /usr/local/perls, for instance, and everything for each installation lives separately. I then make symlinks in /usr/local/bin for them (e.g. perl5.8.9, perl.5.10.0, perl5.10.0-threaded). When I want a particular version, I just use the one I want:
$ perl5.10.0 program.pl
The particular binary ensures that the program picks up the right module search path and so on (it's the same stuff in the Config.pm module for that binary).
Here's a script I use to create the symlinks. It looks in the bin directory, figures out the Perl version, and makes links like cpan5.10.1
and so on. Each program already knows the right perl to call:
#!perl use 5.010; use strict; use warnings; use File::Basename; use File::Spec::Functions; my $perls_directory = catfile( $ARGV[0] // '/usr/local/perls', 'perl*' ); die "$perls_directory does not exist!\n" unless -d dirname $perls_directory; my $links_directory = $ARGV[1] // catfile( $ENV{HOME}, 'bin' ); #/ die "$links_directory does not exist!\n" unless -d $links_directory; foreach my $directory ( glob( $perls_directory ) ) { say "Processing $directory..."; unless( -e catfile( $directory, 'bin' ) ) { say "\tNo bin/ directory. Skipping!"; next; } my @perls = glob( catfile( $directory, qw( bin perl5* ) ) ); my( $perl_version ) = $perls[0] =~ m/(5\.\d+\.\d+)\z/; say "\tperl version is $perl_version"; foreach my $bin ( glob( catfile( $directory, 'bin', '*' ) ) ) { say "\tFound $bin"; my $basename = basename( $bin ); my $link_basename = do { if( $basename =~ m/5\.\d+\.\d+\z/) { $basename } else { "$basename$perl_version" } }; my $link = catfile( $links_directory, $link_basename ); next if -e $link; say "\t\tlinking $bin => $link"; symlink $bin => $link or warn "\t\tCould not create symlink [$!]: $bin => $link!"; } }
Everything gets install in the right place for that particular Perl.
I've also been thinking that I should put those Perl directories under some sort of source control. If I add a module I don't like, I just back out to an earlier revision. I'm only starting to do that though and haven't played with it much.
I've written more about this sort of thing in the Effective Perler blog:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With