Coming soon in Perl: CPAN local::lib bootstrap

Reading time: 5 minutes

I’ve written about my efforts to get CPAN.pm to bootstrap local::lib and about a new HTTP client for CPAN.pm. I’m pleased to say that both have been merged into the development branch of the Perl core.

Barring any show-stopping bugs, the forthcoming Perl 5.13.9 will let a non-privileged user bootstrap access to CPAN, even if FTP is blocked and they have no command line HTTP clients installed. That means that if you can run perl, and you can use port 80, then you can use CPAN.

Imagine someday when Perl 5.14 becomes standard in linux distributions. Log-in to a new machine (or perhaps a shared host), type “cpan”, and start installing stuff from CPAN. Easy!

To show you how it works, I installed a snapshot of Perl from the git repository and then switched to a clean, unprivileged user account to try installing something. All I typed at the keyboard was this:

/opt/perl/fromgit/bin/cpan5.13.8[ENTER]
[ENTER]
[ENTER]
[ENTER]
[ENTER]
install File::Marker[ENTER]

The log below is long and verbose (the way CPAN.pm just is, unfortunately) but you can see how it uses HTTP::Tiny, bootstraps local::lib, updates my .bashrc, installs File::Marker in the local library and even reminds me to restart my shell. Isn’t that user-friendly?

$ /opt/perl/fromgit/bin/cpan5.13.8 

CPAN is the world-wide archive of perl resources. It consists of about
300 sites that all replicate the same contents around the globe. Many
countries have at least one CPAN site already. The resources found on
CPAN are easily accessible with the CPAN.pm module. If you want to use
CPAN.pm, lots of things have to be configured. Fortunately, most of
them can be determined automatically. If you prefer the automatic
configuration, answer 'yes' below.

If you prefer to enter a dialog instead, you can answer 'no' to this
question and I'll let you configure in small steps one thing after the
other. (Note: you can revisit this dialog anytime later by typing 'o
conf init' at the cpan prompt.)

Would you like me to configure as much as possible automatically? [yes] 

 <install_help>

Warning: You do not have write permission for Perl library directories.

To install modules, you need to configure a local Perl library directory or
escalate your privileges.  CPAN can help you by bootstrapping the local::lib
module or by configuring itself to use 'sudo' (if available).  You may also
resolve this problem manually if you need to customize your setup.

What approach do you want?  (Choose 'local::lib', 'sudo' or 'manual')
 [local::lib] 

Autoconfigured everything but 'urllist'.

Now you need to choose your CPAN mirror sites.  You can let me
pick mirrors for you, you can select them from a list or you
can enter them by hand.

Would you like me to automatically choose some CPAN mirror
sites for you? (This means connecting to the Internet) [yes] 

Trying to fetch a mirror list from the Internet
Fetching with HTTP::Tiny:
http://www.perl.org/CPAN/MIRRORED.BY

Looking for CPAN mirrors near you (please be patient)
..............................................................
..............................................................
..............................................................
..................................... done!

New urllist
  http://cpan.erlbaum.net/
  http://cpan.mirror.clemson.edu/
  http://mirrors.servercentral.net/CPAN/

Autoconfiguration complete.

Attempting to bootstrap local::lib...

Writing /home/cleanroom/.cpan/CPAN/MyConfig.pm for bootstrap...
commit: wrote '/home/cleanroom/.cpan/CPAN/MyConfig.pm'
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/authors/01mailrc.txt.gz
Going to read '/home/cleanroom/.cpan/sources/authors/01mailrc.txt.gz'
............................................................................DONE
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/modules/02packages.details.txt.gz
Going to read '/home/cleanroom/.cpan/sources/modules/02packages.details.txt.gz'
  Database was generated on Sat, 15 Jan 2011 20:57:19 GMT
  HTTP::Date not available
............................................................................DONE
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/modules/03modlist.data.gz
Going to read '/home/cleanroom/.cpan/sources/modules/03modlist.data.gz'
............................................................................DONE
Going to write /home/cleanroom/.cpan/Metadata
Running make for A/AP/APEIRON/local-lib-1.008001.tar.gz
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/authors/id/A/AP/APEIRON/local-lib-1.008001.tar.gz
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/authors/id/A/AP/APEIRON/CHECKSUMS
Checksum for /home/cleanroom/.cpan/sources/authors/id/A/AP/APEIRON/local-lib-1.008001.tar.gz ok

  CPAN.pm: Going to build A/AP/APEIRON/local-lib-1.008001.tar.gz

Attempting to create directory /home/cleanroom/perl5


*** Module::AutoInstall version 1.03
*** Checking for Perl dependencies...
*** Since we're running under CPAN, I'll just let it take care
    of the dependency's installation later.
[Core Features]
- ExtUtils::MakeMaker ...loaded. (6.57_05 >= 6.31)
- ExtUtils::Install   ...loaded. (1.55 >= 1.43)
- Module::Build       ...loaded. (0.3607 >= 0.36)
- CPAN                ...loaded. (1.9463 >= 1.82)
*** Module::AutoInstall configuration finished.
Checking if your kit is complete...
Looks good
Writing Makefile for local::lib
Writing MYMETA.yml
cp lib/POD2/PT_BR/local/lib.pod blib/lib/POD2/PT_BR/local/lib.pod
cp lib/lib/core/only.pm blib/lib/lib/core/only.pm
cp lib/local/lib.pm blib/lib/local/lib.pm
cp lib/POD2/DE/local/lib.pod blib/lib/POD2/DE/local/lib.pod
Manifying blib/man3/POD2::PT_BR::local::lib.3
Manifying blib/man3/lib::core::only.3
Manifying blib/man3/local::lib.3
Manifying blib/man3/POD2::DE::local::lib.3
  APEIRON/local-lib-1.008001.tar.gz
  /usr/bin/make -- OK
'YAML' not installed, will not store persistent state
Running make test
PERL_DL_NONLAZY=1 /opt/perl/fromgit/bin/perl5.13.8 -I/home/cleanroom/perl5/lib/perl5/x86_64-linux-thread-multi -I/home/cleanroom/perl5/lib/perl5 "-MExtUtils::Command::MM" "-e" "test_harness(0, 'inc', 'blib/lib', 'blib/arch')" t/classmethod.t t/coderefs_in_inc.t t/de-dup.t t/install.t t/lib-core-only.t t/pipeline.t
t/classmethod.t ...... Name "File::Spec::rel2abs" used only once: possible typo at t/classmethod.t line 20.
t/classmethod.t ...... 1/? Attempting to create directory t/var/splat
t/classmethod.t ...... ok   
t/coderefs_in_inc.t .. ok   
t/de-dup.t ........... ok   
t/install.t .......... skipped: Install Capture::Tiny to test installation
t/lib-core-only.t .... ok   
t/pipeline.t ......... ok   
All tests successful.
Files=6, Tests=10,  1 wallclock secs ( 0.04 usr  0.01 sys +  0.19 cusr  0.01 csys =  0.25 CPU)
Result: PASS
  APEIRON/local-lib-1.008001.tar.gz
  /usr/bin/make test -- OK
Running make install
Manifying blib/man3/POD2::PT_BR::local::lib.3
Manifying blib/man3/lib::core::only.3
Manifying blib/man3/local::lib.3
Manifying blib/man3/POD2::DE::local::lib.3
Installing /home/cleanroom/perl5/lib/perl5/local/lib.pm
Installing /home/cleanroom/perl5/lib/perl5/POD2/PT_BR/local/lib.pod
Installing /home/cleanroom/perl5/lib/perl5/POD2/DE/local/lib.pod
Installing /home/cleanroom/perl5/lib/perl5/lib/core/only.pm
Installing /home/cleanroom/perl5/man/man3/POD2::PT_BR::local::lib.3
Installing /home/cleanroom/perl5/man/man3/lib::core::only.3
Installing /home/cleanroom/perl5/man/man3/local::lib.3
Installing /home/cleanroom/perl5/man/man3/POD2::DE::local::lib.3
Appending installation info to /home/cleanroom/perl5/lib/perl5/x86_64-linux-thread-multi/perllocal.pod
  APEIRON/local-lib-1.008001.tar.gz
  /usr/bin/make install  -- OK

local::lib is installed. You must now add the following environment variables
to your shell configuration files (or registry, if you are on Windows) and
then restart your command line shell and CPAN before installing modules:

export PERL_LOCAL_LIB_ROOT="/home/cleanroom/perl5"
export PERL_MB_OPT="--install_base /home/cleanroom/perl5"
export PERL_MM_OPT="INSTALL_BASE=/home/cleanroom/perl5"
export PERL5LIB="/home/cleanroom/perl5/lib/perl5/x86_64-linux-thread-multi:/home/cleanroom/perl5/lib/perl5:$PERL5LIB"
export PATH="/home/cleanroom/perl5/bin:$PATH"

Would you like me to append that to /home/cleanroom/.bashrc now? [yes] 


commit: wrote '/home/cleanroom/.cpan/CPAN/MyConfig.pm'
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v1.9463)
Enter 'h' for help.

cpan[1]> install File::Marker
Running install for module 'File::Marker'
Running make for D/DA/DAGOLDEN/File-Marker-0.13.tar.gz
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/authors/id/D/DA/DAGOLDEN/File-Marker-0.13.tar.gz
Fetching with HTTP::Tiny:
http://cpan.erlbaum.net/authors/id/D/DA/DAGOLDEN/CHECKSUMS
Checksum for /home/cleanroom/.cpan/sources/authors/id/D/DA/DAGOLDEN/File-Marker-0.13.tar.gz ok

  CPAN.pm: Going to build D/DA/DAGOLDEN/File-Marker-0.13.tar.gz

Creating new 'MYMETA.yml' with configuration results
Creating new 'Build' script for 'File-Marker' version '0.13'
Building File-Marker
  DAGOLDEN/File-Marker-0.13.tar.gz
  ./Build -- OK
Running Build test
t/01_File_Marker.t ... ok    
t/02_fork.t .......... ok   
t/03_thread.t ........ ok   
t/04_save_load.t ..... ok    
t/98_pod.t ........... skipped: Skipping author tests
t/99_pod_coverage.t .. skipped: Skipping author tests
All tests successful.
Files=6, Tests=58,  1 wallclock secs ( 0.04 usr  0.02 sys +  0.22 cusr  0.02 csys =  0.30 CPU)
Result: PASS
  DAGOLDEN/File-Marker-0.13.tar.gz
  ./Build test -- OK
Running Build install
Building File-Marker
Installing /home/cleanroom/perl5/lib/perl5/File/Marker.pm
Installing /home/cleanroom/perl5/man/man3/File::Marker.3
  DAGOLDEN/File-Marker-0.13.tar.gz
  ./Build install  -- OK

cpan[2]> q
Terminal does not support GetHistory.
Lockfile removed.

*** Remember to restart your shell before running cpan again ***

I want to thank Andreas Koenig (CPAN.pm) and Chris Nehren (local::lib) for quickly turning around new releases of their modules to make this work.

•      •      •

If you enjoyed this or have feedback, please let me know by or