4

perlbrew fails with Can't locate Devel/PatchPerl.pm.

More precisely, what fails is a run of patchperl that is spawned off by perlbrew.

There is in fact a Devel/PatchPerl.pm accessible via the paths in the environment variable PERL5LIB, but perlbrew unconditionally deletes this variable before it runs perlpatch:

delete $ENV{$_} for qw(PERL5LIB PERL5OPT);

I can't find anything in the perlbrew documentation justifying this maneuver.

Can someone explain why perlbrew does this?

EDIT:

Below is a bash script that reproduces the problem. I run it like this (with some suitable <PATH_TO_SCRIPT>):

% env -i HOME=$HOME SHELL=/bin/bash /bin/bash --noprofile --norc
bash-3.2$ /bin/bash --norc --noprofile <PATH_TO_SCRIPT>

The script's running time is about 4 minutes on my machine. The last few lines of output, including the lines showing the error are below:

(cd /tmp/perlbrew_root/build/perl-5.16.3 && rm -f config.sh Policy.sh && patchperl && sh Configure -de '-Dprefix=/tmp/perlbrew_root/perls/perl-5.16.3' '-A'eval:scriptdir=/tmp/perlbrew_root/perls/perl-5.16.3/bin'' && make  && make test_harness && make install) 2>&1 | tee /tmp/perlbrew_root/build.perl-5.16.3.log
Can't locate Devel/PatchPerl.pm in @INC (@INC contains: /Library/Perl/5.12/darwin-thread-multi-2level /Library/Perl/5.12 /Network/Library/Perl/5.12/darwin-thread-multi-2level /Network/Library/Perl/5.12 /Library/Perl/Updates/5.12.3 /System/Library/Perl/5.12/darwin-thread-multi-2level /System/Library/Perl/5.12 /System/Library/Perl/Extras/5.12/darwin-thread-multi-2level /System/Library/Perl/Extras/5.12 .) at /tmp/testperl/bin/patchperl line 12.
BEGIN failed--compilation aborted at /tmp/testperl/bin/patchperl line 12.
perl-5.16.3 is successfully installed.

The last line of the output above (perl-5.16.3 is successfully installed.) is nonsense: a real build and installation of perl-5.16.3 would take roughly one order of magnitude longer than this script's running time, which, as already stated, is about 4 minutes on my machine.

Note the @INC in the error. I don't see how patchperl could possibly find Devel/PatchPerl.pm, which is under /tmp/testperl/lib/perl5, given that @INC.

PERLDIR=/tmp/testperl
/bin/rm -rf "$PERLDIR"

/bin/rm -rf /tmp/build
/bin/mkdir -p /tmp/build
cd /tmp/build

/usr/bin/curl -s http://www.cpan.org/authors/id/A/AP/APEIRON/local-lib-1.008009.tar.gz | tar xzf -

pushd local-lib-1.008009
  /usr/bin/perl Makefile.PL "--bootstrap=$PERLDIR"
  /usr/bin/make install
popd

eval "$( /usr/bin/perl -I$PERLDIR/lib/perl5 -Mlocal::lib=$PERLDIR )"

/usr/bin/cpan App::cpanminus

export PERLBREW_ROOT=/tmp/perlbrew_root
export PERLBREW_HOME=/tmp/perlbrew_home
/bin/rm -rf "$PERLBREW_ROOT" "$PERLBREW_HOME"

$PERLDIR/bin/cpanm App::perlbrew
$PERLDIR/bin/perlbrew init
source "$PERLBREW_ROOT/etc/bashrc"

$PERLDIR/bin/perlbrew install -v perl-5.16.3
kjo
  • 33,683
  • 52
  • 148
  • 265

3 Answers3

3

Upgrade perlbrew (perlbrew self-upgrade or the shell bootstrap incantation from http://perlbrew.pl/).

Recent versions install patchperl into $PERLBREW_ROOT/bin through perlbrew install-patchperl.

daxim
  • 39,270
  • 4
  • 65
  • 132
1

I ran into this after trying a fresh (only) install of perlbrew, after installing local::lib. When installing perlbrew via CPAN (not the only way, I've used curl -kL http://install.perlbrew.pl | bash before, with local::lib disabled), the Devel::PatchPerl module was properly installed into ~/perl5/lib/perl5, but as we both found out, perlbrew won't look there. Running perlbrew install-patchperl installs a standalone version of patchperl — built with App::FatPacker — into ~/perl5/perlbrew/bin.

This allows me to have a local "system" perl, with customized libraries and tools provided by local::lib, for ordinary and experimental work. But I can switch to using a perlbrew'ed perl for special projects or applications, for an even more controlled environment. The real system perl is almost never modified.

Caveat - when local::lib is enabled by default in your .bashrc, a simple perlbrew use perl-5.18.2 does NOT remove the local:lib-specific environment varialbles (PERL_MM_OPT and PERL_MM_OPT - you must do it yourself. One (somewhat cumbersome, but simple) trick is:

perlbrew lib create perl-5.18.2@none  # do this once after brewing a perl
perlbrew use perl-5.18.2@none
perlbrew use perl-5.18.2

This also means, that to switch off perlbrew, you can do this:

perlbrew off
eval $(perl -Mlocal::lib | grep -v PERL_LOCAL_LIB_ROOT)

And you are back to your default local::lib setup. Though better to close and reopen a new shell, to avoid extending your $PATH ad infinitum.

This is the simplest way I have found so far to get independent, custom perl environments, including the system perl with your default (local::lib) customizations.

dmaestro12
  • 883
  • 7
  • 15
-1

Can someone explain why perlbrew does this?

Devel::PatchPerl is found inside of patchperl. perlbrew surely clears those vars so you don't accidentally find the wrong modules (as it would have for you if perlbrew hadn't cleared those).

Something wrong if your install of perlbrew if patchperl can't find code that's suppose to be present in patchperl itself! Reinstall it from scratch.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • In the process of debugging this I've reinstalled `perlbrew` from scratch so many times I've lost count... I don't understand what you mean by "Devel::PatchPerl is found inside of `patchperl`". My fresh-installed copy is under `$LOCALPERL/lib/perl5`. See the latest `EDIT` in my post. – kjo Apr 21 '13 at 16:34
  • It's literally in the file `patchperl`. – ikegami Apr 24 '20 at 21:37