markong has asked for the wisdom of the Perl Monks concerning the following question:

Hello folks,

I am going to upgrade a GNU/Linux system Perl installation! :)

This could be variously exciting, probably depending on the mood and the subject :D, except that using heavily local::lib coupled with cpanm(1) for many modules installation I am going to find all the XS ones broken after the upgrade.

Because last time I had to carry out such an upgrade, I found myself in a strange (better say nightmare) situation in which a local installation of Scalar::Util (if I remember well) was one of the XS modules blocking practically the execution of 70% of the library , including the standard cpan(1) script from executing (which resulted in practically re-installing the whole library), I thought better ask this time and plan for the worst: is there any recommended/battle-tested way to proceed with XS modules rebuilding after an upgrade?

Somebody recommend to go for the whole library rebuild which I'd like to avoid (I usually have few XS modules compared to the Perl ones).
I did look at finding a way to reliably find all and only the XS modules in my local lib but I hadn't any luck. Any suggestions?

It seems also that while cpanm(1) has not some related "magic" (correct me if I'm wrong) good old cpan(1) instead has r which could really be what I'm looking for: recompile.
It also has CPAN::Nox which would untangle any problems related to broken XS modules.

BUT(!) I suspect that CPAN::Shell::recompile will proceed with rebuilding all the XS modules in the search path, not only the ones in my $PERL_LOCAL_LIB_ROOT search path which is a problem.
Any experience with cpan in this sense?

Replies are listed 'Best First'.
Re: Dealing with perl upgrade and local XS modules
by no longer just digit (Beadle) on Apr 01, 2021 at 07:39 UTC
    Because last time I had to carry out such an upgrade, I found myself in a strange (better say nightmare) situation in which a local installation of Scalar::Util (if I remember well) was one of the XS modules blocking practically the execution of 70% of the library , including the standard cpan(1) script from executing (which resulted in practically re-installing the whole library), I thought better ask this time and plan for the worst: is there any recommended/battle-tested way to proceed with XS modules rebuilding after an upgrade?

    Scalar::Util is a dual-life module which is in the Perl core as well as on CPAN. It should be installed together with Perl. I always install Perl from the source code, and I always install it into my user space. I'm not sure what kind of problems you might be having, but when I install Perl I don't allow it to use the old versions of libraries, that is when the configure script asks if it is OK to use the old libraries I say "no" (the default is to use the old libraries). That means I have to update every module from CPAN which I'm using, but it seems to work better that way.

    If the CPAN script stops working you can always download the tarfile from metacpan and then go into the directory and do "perl Makefile.PL;make;make test;make install" to install it yourself.

    I did look at finding a way to reliably find all and only the XS modules in my local lib but I hadn't any luck. Any suggestions?

    Yes, I have a suggestion since I frequently have to update just the XS modules on a web host when they change the version of Perl. To find the XS modules you have installed, go to your local library directory where Perl modules are installed, and run the following command:

    find . -name "*.so"
    

    That will produce a list of modules, for example like this:

    [ben@mikan] {16:33 45} site_perl 508 $ cd 5.32.1/ /home/ben/software/install/lib/perl5/site_perl/5.32.1 [ben@mikan] {16:33 50} 5.32.1 509 $ find . -name "*.so" ./i386-freebsd/auto/Test/Taint/Taint.so ./i386-freebsd/auto/Term/ReadKey/ReadKey.so ./i386-freebsd/auto/JSON/Create/Create.so ./i386-freebsd/auto/JSON/Parse/Parse.so ./i386-freebsd/auto/JSON/JQ/JQ.so ./i386-freebsd/auto/Gzip/Libdeflate/Libdeflate.so ./i386-freebsd/auto/Gzip/Zopfli/Zopfli.so ./i386-freebsd/auto/PadWalker/PadWalker.so ./i386-freebsd/auto/XString/XString.so ./i386-freebsd/auto/Variable/Magic/Magic.so ./i386-freebsd/auto/B/Hooks/OP/Check/Check.so ./i386-freebsd/auto/DateTime/DateTime.so ./i386-freebsd/auto/Ref/Util/XS/XS.so ./i386-freebsd/auto/Mouse/Mouse.so ./i386-freebsd/auto/Time/timegm/timegm.so ./i386-freebsd/auto/PerlIO/gzip/gzip.so ./i386-freebsd/auto/indirect/indirect.so ./i386-freebsd/auto/multidimensional/multidimensional.so ./i386-freebsd/auto/bareword/filehandles/filehandles.so ./i386-freebsd/auto/NetAddr/IP/Util/Util.so ./i386-freebsd/auto/Email/Address/XS/XS.so ./i386-freebsd/auto/IP/Whitelist/Whitelist.so ./i386-freebsd/auto/Syntax/Keyword/Try/Try.so

    Now here is a function which sorts out the output of that, as if the above text is all in $so. You will need to edit it to suit your situation:

    sub update_from_so { my ($site, $so, $verbose) = @_; my @so = split /\n/, $so; my %so2f; for my $so (@so) { $_ = $so; chomp; s!\./auto/!!; s!(/([^/]+))/\2\.so!$1!; s!/!-!; if ($verbose) { print "Looking for $_...\n"; } my ($dir, $file) = module_to_file ($_); if ($verbose) { print "Found $_ as '$dir/$file'\n"; } if (! -f $file) { my $cwd = getcwd (); chdir $dir or die $!; do_system ("./build.pl -d"); if (! -f $file) { die "Could not recreate file $file\n"; } chdir $cwd or die $!; } $so2f{$so} = [$dir, $file]; } for my $so (@so) { my ($dir, $file) = @{$so2f{$so}}; my $cwd = getcwd (); chdir $dir or die $!; if (! -f $file) { die "$dir: No $file"; } do_system ("$site-module-build.pl $file"); chdir $cwd or die $!; } }

    The above Perl code will not run "as-is" but should be a fairly useful basis for getting started.

      Thanks for your cues.

      Yes, I have a suggestion since I frequently have to update just the XS modules on a web host when they change the version of Perl. To find the XS modules you have installed, go to your local library directory where Perl modules are installed, and run the following command: find . -name "*.so"

      I had already thought of something similar, but it's generally quite hard to go back to the distribution name from a single .so file path.

      Further research has probably suggested a way to solve also this problem but I need to know if both ExtUtils::MakeMaker or Module::Build write a so called .packlist file when installing the modules. My guess would be yes, but maybe somebody has more on this.

Re: Dealing with perl upgrade and local XS modules
by perlfan (Parson) on Apr 01, 2021 at 02:09 UTC
    I can't answer your question. I can offer this, if you are using local::lib + App::cpanminus, perhaps go "all the way" and utilize perlbrew to create an installation along side of your current system perl + local set up to see if that suited your needs first? If so, then you don't even haave to touch your localized environment that has been built on top of system perl. Is it safe to assume you're really using system perl + a significant investment in modules installed as a non-privleged user? Are the XS modules darkpan (not on CPAN) or are they just the result of some heavy "tweaking"? It sounds like you want to recompile the XS modules "in place", maybe? The nice thing about perlbrew is that it allows you to achieve total isolation. cpanm also works with whatever perl is in PATH (or it can be fetched via perlbrew). Just some ideas there - don't know much detail about your set up or constraints.

      Is it safe to assume you're really using system perl + a significant investment in modules installed as a non-privleged user?
      Yes, I'm sorry if that wasn't clear enough in the description: XS modules are installed locally against system perl.
      Are the XS modules darkpan (not on CPAN) or are they just the result of some heavy "tweaking"?
      No they're all public XS modules. No tweaking.
      It sounds like you want to recompile the XS modules "in place", maybe?
      That would be the goal yes. Ideally I would "list" XS only distribution names in ~/local/perl/lib and then proceed again with the whole make/test/install cycle.

Re: Dealing with perl upgrade and local XS modules
by Anonymous Monk on Apr 01, 2021 at 06:56 UTC
    Apologies if you already knew that, but if you find yourself with a broken Perl installation because the modules in local::lib aren't compatible with /usr/bin/perl any more, just unset the PERL5LIB environment variable to let the system Perl modules take over (and let you run cpanm). (Unless you install as root into /usr/local/.... That's probably harder to fix.)