How do YOU manage Perl modules when using a package manager?

落花浮王杯 提交于 2019-12-17 05:50:28

问题


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?


回答1:


Since this question was originally asked, perlbrew has been released. It makes installing custom, self-contained perl installs trivial. And switching between those versions is just as easy:

perlbrew switch $version



回答2:


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:

  • Make links to per-version tools.
  • Manage your Perl modules with Git.



回答3:


We install everything via the CPAN shell. This does ignore what package managers have to offer, but it avoids the headaches you mention when trying to work with them (firing for dependencies, using correct versions).

In addition, it means that our packages can be built programatically (or manually via the shell) on any platform where CPAN runs. Having a dependency on a package manager would affect your ability to distribute your software to platforms that don't use/support that package manager.




回答4:


I do the following on all my boxes:

  • I compile my own perl: I still use 5.8.[89] mostly, the stock 5.10.0 has a performance regression that hits me a lot, waiting for 5.10.1 to try again;
  • I use (and strongly recommend) the local::lib module to keep a module directory per project. Right now, that directory is rsync'ed to all the servers where the project is installed, but I'm testing using git instead;
  • I create a Task:: module for each project, so that I can install all dependencies with a single command.



回答5:


I am using Debian for development, and production, and rely on debian Perl packages that are provided with the distro.

For cases where I need a Perl module that is not available in debian, I usually create my own debian package of it and install it.

Ofcourse, this method is not without faults, as a a lot of debian perl modules are outdated (at least in the current debian stable version - etch), and backporting something like Catalyst which has lots of dependencies is not practical.

However, by relying on the OS package manager, I retain all the great features of it, which bring easy maintenance, especially for deployed servers, as you know exactly what packages are installed, and a simple apt-get update;apt-get upgrade (from debian, or from a local repository) upgrades all servers to the same state, including the Perl modules.




回答6:


I also use the cpan shell and local::lib.

You shouldn't need a Task:: for each project. Just use Module::Install (I like to use Module::Starter like this:

$ module-starter --mi --module=Module::Name --author="Me" --email=me@cpan.org

and then just pop your dependencies in requires 'module::dependency'; in the Makefile.PL. Finally when it's install time, you just perl Makefile.PL (answer yes) then make installdeps

[edit 5 years on from when I gave this answer originally]

These days perlbrew and cpanm are the things to use. local::lib still has a use-case, but the combination of perlbrew and cpanm solve a superset of those cases. Use local::lib when you're not prepared to compile your own perl.




回答7:


I recommend use only cpan. The modules includes in Linux distro is only to cover package dependency. When you are installing linux without internet access with only CDs, it can't use cpan, so some modules are included as packages, but to a Perl developer this is bad.

Also I used to have a cpan configured to install modules in my home, (.perl) without root login needed.




回答8:


For production:

In development, choose a version of the perl module which seems right for the requirements; if possible choose the target OS's shipped version (this makes most of the following superfluous), otherwise, pick another one. Create a RPM spec file for it. Use the clean build VM to build the RPM in a reproducable way (from a specfile / source checked in on the appropriate branch).

When the final build can be built (after merge), do the same build from the release branch, commit generated RPMs into deployment repository. This will be used in final validation and then released to production by being copied to the production repository.

All servers in production use the exact same binary that has been fully tested; they use the same spec file and source as the developer intended.

Perl modules are NOT upgraded by any process which does not follow this model. Nor is any other production software.




回答9:


I use FreeBSD ports and wrap up all the CPAN dependencies in a "meta port" as a sort of a local port. FreeBSD has quite a large number of CPAN modules and their build system is approachable enough that you can easily write your own port if it doesn't exist--just dont forget to submit said port so it gets included in the ports tree. If the port doesn't have the current version in stock, you can always edit the Makefile for the port so it uses the new version, again don't forget to submit the change :-).

Lastly, I use Tinderbox to build the whole mess as binary packages that I then install on the all the production and development machines.

Bottom line--Once you get over your phobia of editing Makefiles, FreeBSD's ports are a great way to maintain your perl application and its dependencies.




回答10:


I have started using Gentoo recently and Gentoo has a few very important advantages in this area. The first is that g-cpan is capable usually of installing many (though not all) modules from CPAN as Gentoo packages natively, though updating becomes a bit of a problem.

Usually on Gentoo, my approach is to use g-cpan to create an ebuild file, then install from that, tweaking if necessary. The advantage is that upgrading becomes really easy. I then move the file from g-cpan/perl to dev-perl and put it in an overlay for others to use. This allows me to quickly handle the cases g-cpan does not and gentoo packaging is a breeze anyway/



来源:https://stackoverflow.com/questions/398221/how-do-you-manage-perl-modules-when-using-a-package-manager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!