Home > Software engineering >  How is local::lib supposed to handle XS and different versions of Perl?
How is local::lib supposed to handle XS and different versions of Perl?

Time:12-08

I love the idea of local::lib. At least, I find it preferable to the default system-wide installs that cpan/perl defualts to in most every way. However, I'm having difficulties with modules that install XS and distribution upgrades to newer Perls. The instructions for local::lib call for adding this line to your .bashrc (or like file)

eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)"

That executes arbitrary shell code, which is fine. You can see the code it executes by running

perl -I$HOME/perl5/lib/perl5 -Mlocal::lib

In my case it returns this code,

PATH="/home/ecarroll/perl5/bin${PATH: :${PATH}}"; export PATH;
PERL5LIB="/home/ecarroll/perl5/lib/perl5${PERL5LIB: :${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/ecarroll/perl5${PERL_LOCAL_LIB_ROOT: :${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/ecarroll/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/ecarroll/perl5"; export PERL_MM_OPT;

In the above, we're setting the default options for the two most widely used module build systems,

We're telling those system to install to /home/ecarroll/perl5. The rest of the command sets

  • PERL5LIB which is used in setting @INC. The @INC variable in Perl is used to resolve calls with use.
  • and, PATH which prepends the bin/ directory that local::lib installs to.

So basically, install perl modules in your home directory, and look first for files installed in your home directory.

My question is what happens when you install something that has XS? In my case, I have an XS file,

/home/ecarroll/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/auto/Class/Load/XS/XS.so

This was installed, with local::lib using an earlier version of Perl. I've since ran a Debian dist-upgrade and got a newer version of Perl (v5.36). Now a lot of utilities produce an obtuse error about this, including ones installed through the distro itself like in my case Dist::Zilla dzil which I installed with Debian's libdist-zilla-perl package.

$ dzil
XS.c: loadable library and perl binaries are mismatched (got first handshake key 0xeb00080, needed 0xeb80080)

Which is all a result of this module's XS,

perl -MClass::Load::XS -e1
XS.c: loadable library and perl binaries are mismatched (got first handshake key 0xeb00080, needed 0xeb80080)

This seems like very routine use of local::lib:

  • Am I using local::lib in the way intended? What else should I be doing?
  • How is local::lib supposed to handle XS?
  • Is there a way to make local::lib support multiple versions of Perl? My distro reads and writes the XS it manages to /usr/share/perl/$PERL_VERSION. This means a dist-upgrade leaves all the XS from the old version behind. It would be nice to have local::lib install not to /home/ecarroll/perl5/lib/perl5/ but instead to /home/ecarroll/perl5/lib/perl5.30/? Note the added minor version. Then at least a dist-upgrade wouldn't break the distribution.

CodePudding user response:

Perl doesn't maintain ABI compatibility between versions. (5.34.x -> 5.36.y, for example.) After installing a new version of Perl, you will need to re-install modules that install themselves in arch dirs (XS modules and a few others). Might be easiest and safest to remove (rename) the local lib directory (/home/ecarroll/perl5) and start from scratch.

That's why I avoid using anything but distro-provided modules with distro-provided perl. The package manager ensures you always have compatible builds of the modules.

If that's not good enough, I recommend installing your own builds of perl instead of using local::lib. Tools like perlbrew makes this easy. You'll still have to re-install all the modules when you install a new perl, but you'll get the cleaner "Can't locate" error message if you forget one.

CodePudding user response:

This is a shortcoming of local::lib

The local::lib system currently suffers in only supporting one version of perl at a time. Things are local to the user, not the user and perl version. That means

  • If your system has two different versions of perl, the instructions and configuration for setting this in .profile will not work. Because they'll both save to and read from the same directory which is read from the user's environment.
  • If your system upgrades from one version of perl, to a different version of perl you'll have to manually clear out your local::lib directory (defaults to ~/perl). Otherwise, your newer perl version will read from code compiled against your older perl. This won't work as XS ABI is different. Deleting ~/perl is what mst does to solve this problem, and he wrote local::lib.

The author of local::lib, mst, has tried to remedy some of these problems with plx however I'm not sure if the problem is fixed there either.

  • Related