2010-09-17

Installing Multiple Perls with App::perlbrew and App::cpanminus

Having learnt from my previous mistakes, this is a simplistic way to set up multiple somewhat isolated installs of Perl in a user profile

App::perlbrew is a very handy tool for managing several user-installs of Perl, and facilitates the easy switching between Perl versions.

App::cpanminus is the most straight-forward and lightweight cpan client I've ever seen, and it just works, and works well, and leads to relatively pain-free installation 80% of the time.

1. Install A Bare copy of Perlbrew

Getting a copy of Perlbrew should be the very first thing you do. No cpanm, no local::lib, just straight perlbrew.
$ cd ~ 
$ curl -LO http://xrl.us/perlbrew

2. Setup Perlbrew

Once we have a copy of perlbrew, we run the install command of it, which completes the bootstrapping of perlbrew. Then all thats needed is to update your profile with the right magic line so that new shells will have the right environment set up.
$ perl ~/perlbrew install
$ rm ~/perlbrew
$ ~/perl5/perlbrew/bin/perlbrew init
# use the line perlbrew spits out.
$ echo "source /home/test_1/perl5/perlbrew/etc/bashrc" | tee -a ~/.bashrc

3. Enter your new perlbrew ENV

Now we enter our new shell so that we can test the change to our configuration. We run env and grep the PATH value just to double check perlbrew has worked properly.
$ bash
$ env | grep PATH
PATH=/home/test_1/perl5/perlbrew/bin:/home/test_1/perl5/perlbrew/perls/current/bin:/home/test_1/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:.

4. Choose a mirror

This step is mostly optional, but it lets you choose which mirror perlbrew will download Perl sources from, so a local one is best for speed sakes.
$ perlbrew mirror

5. Install your wanted perl versions

Now we perform the slow installation of our Perls. In my case, I'm installing a copy of the current stable ( 5.12.2 ) and the current development release ( 5.13.2 ). The -v is optional, but you'll want it if you do not wish to die of boredom because it generally just sits there doing nothing for 10+ minutes without it.
$ perlbrew -v install perl-5.12.2
$ perlbrew -v install perl-5.13.4

6. Setup 'cpanm' for each perl

This step appears to be the most important step. If you previously had cpanm installed with system perl you do NOT want to be using that at all. When cpanm is installed, the bin/ script hard-codes a path to the perl it was installed with, so using cpanm built with system perl will build installed modules using that system perl instead, and using its install paths and soforth, and you do not want this. So, you must install a cpanm for each perl using this bootstrap technique.
$ perlbrew switch perl-5.12.2
$ curl -L http://cpanmin.us | perl - App::cpanminus
$ perlbrew switch perl-5.13.4
$ curl -L http://cpanmin.us | perl - App::cpanminus

7. Configure local cpans

Strangely, I've found a few modules I try install tend to expect a working CPAN install, regardless of what tool I'm actually using. This should be fixed, but there is a practical work-around until then. Simply configure cpan!
$ perlbrew switch perl-5.12.2
$ cpan
# Answer all setup instructions
» o conf commit
» q
$ perlbrew switch perl-5.13.4
$ cpan
# Answer all setup instructions
» o conf commit
» q

8. Test your installs

This is a list of things I've found to trip up various corner cases and indicate you've built it wrong.
$ perlbrew switch perl-5.12.2
$ cpanm --interactive -v App::cpanoutdated
$ cpan-outdated
$ cpanm --interactive -v App::CPAN::Fresh

$ perlbrew switch perl-5.13.4
$ cpanm --interactive -v App::cpanoutdated
$ cpan-outdated
$ cpanm --interactive -v App::CPAN::Fresh
With all things going to plan, those 2 things at least should build and be runnable. cpan-outdated and cpanf should both be runnable in both perls without complaining it cant find their modules, and CPAN::Inject and Compress::BZip2 should install without strange failures. ( those 2 modules lead me in prior cases to discover broken setups that needed fixing to work, so hopefully, going to plan, following the instructions above will avoid this havoc. )

9. Profit!

Thats all there is to it. Note we do NOT use local::lib for this setup. Using each Perls default local module installation directory should be perfectly satisfactory, and as long as you're in a properly configured ENV and you're using 'perlbrew' to select perl's that are not system perl, everything should be sweet =).
Ok, lots of things on my machine fail to build still, but those peskynesses I'm convinced are unrelated to the Perl setup.

10. Credit

Props to the people who helped me out with working out this configuration ( brian d foy, miyagawa, John Napiorkowski ) and to the authors of cpanm ( miyagawa ) and perlbrew ( gugod ). These are awesome tools, and once you learn them, they really can make working with Perl a much more pleasureable experience!. And also props and ♥ to the Perl Community for simply existing, and fostering this development path.

11 comments:

  1. Awesome, I'm going to share this around since you summarize it very well.

    The only thing I do differently is I still use local::lib even with perlbrew, that way I can have a separate lib of cpan dependencies for each project I work on. Otherwise if you want to make sure your dependencies are good you need to blow away and restore the entire perlbrew installed Perl. But I know lots of people are doing it just that way, so do whichever works best for you.

    ReplyDelete
  2. oh, btw I think you can just do 'self-upgrade' with cpanminus,

    curl -L http://cpanmin.us | perl - --self-upgrade

    which is essentially the same as your step, just another way to do it that you might see floating around

    ReplyDelete
  3. Nice! I'm looking to do this in the coming weeks. Thoughts on using local::lib? My only inclination to use local::lib is to break my habit of using sudo cpan install.

    ReplyDelete
  4. @Bob : If you only normally use local::lib to avoid the need to sudo to install things, then you don't need local::lib with this configuration.

    Things that get installed will simply be installed in your user-spaced copies of Perl.

    However, if you want to add an extra layer, you can use local::lib and have "per-project" module install directories, which may be better or worse depending on your tastes.

    ReplyDelete
  5. jnap wrote:
    > The only thing I do differently is I still use local::lib even with perlbrew, that way I can have a separate lib of cpan dependencies for each project I work on.

    I usually use perlbrew perl and install modules to its own site_perl without local::lib since it's much easier for the "daily use" of my perl code.

    For more serious, probably work related code or the things i deploy to servers, I use cpanm's -L option, basically local::lib's lib::core::only equivalent to install all dependencies into local::lib compatible library path, like you do.

    > Otherwise if you want to make sure your dependencies are good you need to blow away and restore the entire perlbrew installed Perl.

    Not really. You can use lib::core::only to easily make sure your dependencies are good, even if you have bunch of extra stuff in your site_perl since lib::core::only "blows it up" for you in process.

    And even if you have to really scratch perlbrew perl's site modules, all you have to is just to run rm -r the site_perl directory.

    ReplyDelete
  6. A note: I have to run

    $ ${PERLBREW_ROOT}/${PERLBREW_PERL}/bin/cpanm

    instead of just 'cpanm' from the command line, or else the system wide one will be used.

    ReplyDelete
  7. Step 5 is success
    Step 6 is failed


    [shev_ay@pandora 20120203]$ curl -L http://cpanmin.us | perl - App::cpanminus
    % Total % Received % Xferd Average Speed Time Time Time Current
    Dload Upload Total Spent Left Speed
    100 319k 100 319k 0 0 107k 0 0:00:02 0:00:02 --:--:-- 288k
    perl: symbol lookup error: /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Compress/Raw/Zlib/Zlib.so: undefined symbol: Perl_Gthr_key_ptr


    Why? What can i do?

    ReplyDelete
    Replies
    1. Sorry, looks like your system Perl is broken. I'm not sure what you can do there, other than reinstall your system Perl.

      Its also possible you've polluted your system Perl by running CPAN as root, and/or have legacy modules in scope which might be getting loaded.

      Essentially, you need a clean Perl set-up, because your present one is somehow broken at a fundamental level.

      Delete
  8. Thanks a million for this. I've come in off the ledge....

    One comment, and not to second-guess your intent....but where you have cpan-outdated, you might want to have that list piped to cpanm to update:

    cpan-outdated -p | cpanm

    I've been trying to get this all working for weeks; your solution was spot-on and perfect. Thanks again.

    ReplyDelete
  9. In order to successfully build perl, I had to first install the build dependencies for it like so:

    apt-get build-dep perl

    ReplyDelete
  10. Awesome. Definitely a big help! Kudos on the clear explanation.

    ReplyDelete