Using perlbrew to build a perl with debugging symbols - perl

I'm trying to track down a segmentation fault that I've been able to isolate to just a few lines of code on different versions of Perl. I use perlbrew to manage my various versions for development and testing, but it doesn't build perl with debugging symbols, so using gdb to analyse the core dump file is pretty useless.
So what's the best way to have perlbrew build with debugging symbols enabled. And if possible I'd like to be able to have it be a separate perl that I could switch to instead of overriding the standard one for the same version.

perlbrew install -v 5.14.2 --as=5.14.2d -DEBUGGING=-g
(--as puts it under a different name, so you can keep your existing builds.)
There's also the following which includes the above and stuff you surely don't need:
perlbrew install -v 5.14.2 --as=5.14.2d -DEBUGGING=both
See INSTALL in the root dir of the Perl distro.

Related

Why do official perl docker images have two version of perl?

I'm working on a legacy product which uses the Docker perl:5.10-threaded image and ran into an issue trying to debug things when I discovered there are two version of perl - one in /usr/local/bin/perl and one in /usr/bin/perl. In this particular image, they are actually different versions
/usr/local/bin/perl -> 5.10.1
/usr/bin/perl -> 5.20.2
The issue it was causing is that each has a different #INC path.
$ /usr/local/bin/perl -V
[snip]
/usr/local/lib/perl5/5.10.1/x86_64-linux-thread-multi
/usr/local/lib/perl5/5.10.1
/usr/local/lib/perl5/site_perl/5.10.1/x86_64-linux-thread-multi
/usr/local/lib/perl5/site_perl/5.10.1
$ /usr/bin/perl -V
[snip]
/etc/perl
/usr/local/lib/x86_64-linux-gnu/perl/5.20.2
/usr/local/share/perl/5.20.2
/usr/lib/x86_64-linux-gnu/perl5/5.20
/usr/share/perl5
/usr/lib/x86_64-linux-gnu/perl/5.20
/usr/share/perl/5.20
/usr/local/lib/site_perl
.
The latest versions, like perl:5.30-threaded also have two versions and different #INC paths as well.
/usr/local/bin/perl -> 5.30.0
/usr/bin/perl -> 5.28.1
It turns out my legacy app uses #!/usr/bin/perl, which was very confusing to me when perl foo.pl didn't work the same as foo.pl (it complained about missing libraries).
To add a bit more color, this legacy app also installs a bunch of perl libraries via apt-get. E.g.,
libcpanel-json-xs-perl libxml-libxml-perl libcgi-pm-perl
libtie-ixhash-perl
libswitch-perl libmime-lite-perl liblist-moreutils-perl
libdate-calc-perl libnet-sftp-foreign-perl
libxml-libxslt-perl liburi-escape-xs-perl
libdatetime-perl
These seem to install things accessible by /usr/bin/perl, which is perhaps why the app uses it in the shebang lines.
The other thing this app does is install some cpanm items and then copy them over, so they are accessible to /usr/bin/perl
RUN cpanm XML::XML2JSON
RUN cpanm JSON
RUN cp /usr/local/lib/perl5/site_perl/5.10.1/XML/XML2JSON.pm /usr/lib/x86_64-linux-gnu/perl5/5.20/XML
RUN cp /usr/local/lib/perl5/site_perl/5.10.1/JSON.pm /usr/lib/x86_64-linux-gnu/perl5/5.20
This seems like a hack to me, but I'm new to perl development, so who knows?
All this leads up to my questions:
why are there two version of perl in the Docker images?
are apt-get and cpanm incompatible with each other?
is there a better way to install these perl libs?
Perl is an essential part of many Linux distributions, and has to come pre-installed. The system perl that is used by the operating system is usually installed as /usr/bin/perl. Modules for it are managed through the package manager (e.g. apt) and not via cpan/cpanm. If you were to install modules for the system perl yourself, this might conflict with modules expected by the operating system. Worse, installing the wrong module version could break parts of the OS. Similarly, replacing the system perl is a bad idea. That's why those Docker images install the different perl alongside.
For your apps, you should avoid the system perl. If you want to install extra modules for use with the system perl, consider using local::lib. In some cases you might install dependencies such as C libraries or external tools via apt, but you wouldn't use apt-provided Perl modules.
Unless you are targeting a specific operating system, do not hardcode the #!/usr/bin/perl shebang. Instead, prefer #!/usr/bin/env perl so that the script will use the perl that is first in the PATH. Alternatively, use wrapper scripts to explicitly invoke the correct perl installation. For example:
#!/bin/sh
exec /usr/local/bin/perl -I/path/to/extra/modules /path/to/my/script "$#"
Note that you cannot share modules between different versions of Perl. During installation of XS modules they are compiled for a specific version, and will fail to load with a different Perl version. For your local perl, just install dependencies via cpanm and ignore modules that were installed for the system perl.

Using local Perl module instead of one installed by CPAN

I have found it necessary to expand upon a CPAN module. (Unicode::CharName goes up to Unicode 4.1; I need some characters from Unicode 5.0 & 5.1).
I've made the changes needed and have my own CharName.pm module.
I now would like to use it with my various Perls. I currently use:
Strawberry Perl for Windows
git for Windows MINGW64; My .bashrc sets
$PATH to Strawberry perl and $PERL5LIB=/c/Strawberry/perl/vendor/lib:/c/Strawberry/perl/site/lib
WSL Ubuntu
Where should I put my version of Unicode::CharName, so that it over-rides the ones installed by CPAN?
I don't want to have to change any scripts that currently
use Unicode::CharName;
Using cpanm you could download the module, patch it, and install it as normal:
$ cpanm --look Unicode::CharName
# new shell opens
$ patch lib/Unicode/CharName.pm custom.patch # or whatever process
$ perl Makefile.PL
$ make install
$ exit
You can also install it to a local::lib to avoid overwriting it globally, by adding the -l local/ option to the cpanm command. Then you can add the absolute path of this local::lib to your PERL5LIB or via -I or use lib. If you specified /path/to/local for the -l option, it would be /path/to/local/lib/perl5.
Manually copying files rather than going through the normal installation process is likely to lead to problems. Many distributions depend on the installation process to build the modules correctly. Also, you will need to install the module separately for each Perl you want to use it for; installed Perl modules are not generally cross-compatible between Perl versions or architectures. (A strictly simple pure-Perl module can be an exception to these rules, but the only module I feel comfortable abusing this way is App::cpanminus, because it was designed to do this.)

Does perlbrew work with cygwin?

Searching the web, I have found almost no evidence that perlbrew works on cygwin. The specifics of my current issue are:
With the latest install of cygwin (which includes perl 5.14.2), I'm trying to install perl-5.14.2 using the latest perlbrew, installed from the web (not CPAN). I get a hang just after ../dist/threads-shared/t/shared_attr.t...ok is printed to build.log. This is on WinXP Pro 2002 SP3. Previous tries at using perlbrew on other builds of cygwin (which include perl 5.10.1) have also failed, but in other places.
I have posted a comment on Reini Urban's blog on blogs.perl.org and an issue/bug on github for App-perlbrew, but with no responses yet.
Is there any hope that I can get perl to build on cygwin? If not, what can I do to work around it and still use perlbrew (to unify my environments so that my cygwin environment uses perlbrew, just like my linux environment does)?
perlbrew works and perl can be built on Cygwin, with the minor annoyance that some of the unit tests hang (as you have discovered). Keep one eye on the build process output and kill the tests (usually thread related) that don't do anything for a couple of minutes using ps and kill. perlbrew should (knock on wood) run make install even if a handful of tests did not pass.
I never got perlbrew run under cygwin. But as a workaround perhaps try plenv. When I last tried it, it worked out of the box under cygwin.
A 2018 update - perlbrew works fine for me on Cygwin. However, perlbrew-installed perls will not have the patches that a system Perl has. I have a sample repo at https://github.com/cxw42/perlbrew-on-cygwin showing how I built the latest Cygwin system perl and installed it as a perlbrew perl.
In short, building Perl with prefix, site prefix, and vendor prefix set to ~/perl5/perlbrew/perls/perl-<version> will generate a Perl tree. You can drop that Perl tree into ~/perl5/perlbrew/perls/, and perlbrew will pick it up as an available Perl.

How do I install Perl libraries in Cygwin?

I'm a C/C++/Java/Unix geek by trade, but now I have to write a Perl program in Windows. So I've got Cygwin, Eclipse with EPIC installed, and simple test programs run. I do not have a Unix machine available to me that I can run Eclipse on.
But I need to use Net::TCP::Server and I can't figure out how to install it. It doesn't appear to be part of the Cygwin Perl install, and I don't want to spend 5 days learning the world of Perl and CPAN and Perl configuration. I just want to write my program.
Any simple ways of installing a Perl module in Cygwin? I'm thinking something like apt-get install would be nice, but I expect that's too much to hope for.
Thanks
$ perl -MCPAN -e shell
cpan shell -- CPAN exploration and modules installation (v1.9402)
Enter 'h' for help.
cpan[1]> install Net::TCP::Server
And it's instructive to list the configuration with the o conf command.
Seeing that some of the info here is a bit outdated and too complicated, I'd rather suggest the following. There are a few different Perl package managers in use. They are all installed with cpan (which is already part of the Cygwin Perl installation), like this:
# Install ppm (outdated)
cpan PPM
# Install cpanp (still used)
cpan CPANPLUS
# Install cpanm (most recent)
cpan App::cpanminus
Then you can install any Perl package you like, as for example in the OP, using cpanm:
cpanm Net::TCP::Server
Sometimes (as noted above) Cygwin may fail certain tests. For example, when using IPv6 on a machine only configured with IPv4, or when your windows firewall is blocking some tests, etc. To attempt to install anyway, try to use the force flag; -f.
cpanm -f Net::TCP::Server
I'm a C/C++/java unix geek by trade, but now I have to write a perl program in windows. So I've got cygwin, eclipse with EPIC installed, and simple test programs run. I do not have a unix machine available to me that I can run eclipse on.
You should be able to run Eclipse with EPIC right under Windows without Cygwin. I like Cygwin for many things, but it isn't exactly a very stable platform. Eclipse runs as a Java program, so all you have to do is make sure Java is installed on your PC. There is even a pre-built Eclipse package.
You can also get a decent Perl that runs right under Windows. Either ActivePerl or Strawberry Perl. Either one will work although many Unix heads prefer Strawberry Perl because it comes with the same MIGW environment that Cygwin has and many feel it's more compatible with the Unix Perl brethren. However, ActiveState Perl can use the Perl Package Manager (PPM) that contains pre-built modules. Unfortunately, the module you want isn't available via PPM.
But I need to use Net::TCP::Server and I can't figure out how to install it. It doesn't appear to be part of the cygwin perl install, and I don't want to spend 5 days learning the world of perl and cpan and perl configuration. I just want to write my program.
Installing from CPAN is really quite simple. The first time you run CPAN, it should pretty much configure itself. Then, to do an install, you run cpan install Net::TCP::Server and that should be it. However, I've tried on several Mac, Unix, and Linux machines, and I can't get it to work. So, this isn't a Windows problem as much as a problem with this module. It is fairly old, and might not work well in newer versions of Perl. You might have to force the install over test's objections.
Maybe you can use one of the already installed IO modules that come with Perl instead. That'll save you a boatload of trouble because the required modules are part of Perl's existing package.
Despite Cygwin's "problems," I use it regularly whenever I have to use Windows. I would recommend first installing a separate installation of Perl using perlbrew so that you won't interfere with Cygwin's copy of Perl in case something bad happens since Cygwin does not enforce root-user policy. In cygwin shell, type
\curl -L http://install.perlbrew.pl | bash
This should walk through the installation for perlbrew and set it up in one of your executable path. Next type
perlbrew init
perlbrew install --force stable
perlbrew switch stable
Wait a bit while a mint Perl is compiled. For unknown reason, Perl can only pass 99.23% of the core module tests on Cygwin (at least on my machine),hence the --force flag). My experience is that it mostly have something to do with handling of device files, like ports and pipes. I am unaware of people trying to resolve the issue as it seems like a Cygwin problem. Although it has not presented much problem for me with general system and web programming tasks. The module testing routines will fail if any problem exists so I am not fretting over it.
Next step is to install cpanm (cpanminus), type
perlbrew install-cpanm
From here on out, to install any library from CPAN, just type
cpanm [library::name1] [library::name2]
cpanm makes it trivial to install any Perl modules. You can even install from your local directory instead of CPAN.
Your mileage may vary, but I had a lot of trouble until I realized that Strawberry perl had a lot of bin folders in my PATH, and when I changed my .bashrc to export only a very simple PATH=/bin:/usr/bin:/usr/local/bin, Cygwin's perl installation's cpan started working beautifully. I used local:lib as Cygwin doesn't support sudo. Before it got into a bad loop saying "Press SPACE and ENTER to exit Patch" over and over.

How do I use perlbrew to manage perl installations aimed at web applications?

I have been using perlbrew to manage multiple versions of perl on a Linux Fedora notebook. I have used it with great benefit to run command-line scripts mostly using App::cmd.
I now want to move to running web applications written using CGI::Application using different perls installed in my $HOME. I am familiar with running Perl web applications in $HOMEs using Apache's user_dir or creating Virtual Hosts but I am unable to come up with a clean way of integrating this and the perlbrew managed perls. Specifically I need help in understanding and finding answers to these questions:
How do install mod_perl under perlbrew?
Assuming this is done, how do I configure my VirtualHost so that it picks up the correct perl that is current?
If this is not possible, (which I doubt) can I at least use local installations to run vanilla CGI?
Thank you for your attention.
I don't think this is a good use for perlbrew, which moves around symlinks under its own directory. The trick is switching the mod_perl module around. Remember, mod_perl is going to be binary-incompatible between major versions of perl, and that you will have to compile it against apache for each version of perl (and apache) you want to use.
perlbrew really does two big things for you:
Installs perl, which is trivially easy to do on your own.
Switches around symlinks so perl is whatever version you want.
If you give up on that last one, perlbrew isn't really doing that much for you. I don't think the symlink feature is particularly valuable.
I think perlbrew is fine for what it is, but when you start doing things outside of its limited scope, it's time to not use it. It's supposed to be a tool to save you some time and headache, so if it's not accomplishing that goal, it's not the right tool for your situation.
In this situation, where I'm supporting a single, big web application, I give it its own perl installation that I don't let anything else use.
For your other questions:
markdown placeholder
You shouldn't have to configure any VirtualHost stuff. If you are using mod_perl, perl is already in there and you don't get to choose a perl. If you're using CGI stuff, you specify the perl on the shebang line. You will have to ensure apache picks up the right library directories, but I think perlbrew handles that. You might have to use SetEnv or something similar in your httpd.conf.
For vanilla CGI, just point to the right (symlink) path for whatever the default perlbrew version is. The CGI program will just use whatever perl that path points to.
See brian d foy's answer for why not to expect to use perlbrew to switch between versions of mod_perl. I also expect that you will need to run multiple Apache servers, if you need multiple different Perl versions under mod_perl.
However, using perlbrew as an easy way to build Perl is IMHO a valid thing to do, and there are few instructions available for how to run mod_perl under perlbrew.
First ensure perl is built with shared library support, by passing the -Duseshrplib flag (otherwise on 64-bit systems you will get a confusing build failure about -fPIC):
perlbrew install perl-5.16.3 -Duseshrplib
Install the development Apache libraries for your system. On Debian, this differs depending on the Apache MPM that you are using. For the prefork MPM:
sudo apt-get install apache2-prefork-dev
Or for the worker MPM:
sudo apt-get install apache2-threaded-dev
Then you need some options to build and install mod_perl2 into the right place. Note that this means cpanm will fail to build it, but you could use it to get hold of the source:
cpanm mod_perl2 # fails
cd ~/.cpanm/latest-build/mod_perl-2.0.8/ # adjust mod_perl version
Adjust the version of Perl below accordingly. (The MP_APXS option is to give the right path for Debian-based systems, which you might not need.)
perl Makefile.PL MP_APXS=/usr/bin/apxs2 \
MP_AP_DESTDIR=$HOME/perl5/perlbrew/perls/perl-5.16.3/
make
make install
Finally, change the LoadModule line in your Apache configuration file (adjusting paths accordingly):
LoadModule perl_module <your homedir>/perl5/perlbrew/perls/<your perl>/usr/lib/apache2/modules/mod_perl.so
Your mod_perl installation will now be running the version of Perl that you want. Install all your required CPAN modules and get going.