What is the Perl Core?

When I use the term “Perl Core” I mean the standard library of modules (distributions actually) that ship with the perl interpreter, and I think that’s what most people mean when they use that term. Knowing which modules are in the Perl Core is useful; it enables developers to build programs without external dependencies over which the developer has little control. The perldoc site has a handy alphabetized list of core modules and I generally check there first to browse which modules are in core. The problem though, is that it can be wrong.

What modules are included in the Perl Core?

Did you know that HTTP::Tiny has shipped with Perl since 2011 (version 5.14.0)? It’s not listed on perldoc (although that is on the list to be fixed at the next QA Hackathon). Luckily there is a better solution: the corelist program. This is supplied with Module::CoreList. Let’s see when Module::CoreList first shipped with Perl:

$ corelist -a Module::CoreList Data for 2015-06-01 Module::CoreList was first released with perl v5.8.9 v5.8.9 2.17 v5.9.2 1.99 v5.9.3 2.02 v5.9.4 2.08 v5.9.5 2.12 v5.10.0 2.13 ...

I’ve truncated the output and kept the key details. It shows that Module::CoreList has been included since Perl version 5.8.9. At home I run Fedora 23, which comes with Perl version 5.22.1. Running the system Perl corelist :

$ sudo corelist -a Module::CoreList sudo: corelist: command not found

The program doesn’t exist; the Fedora team didn’t include it for some reason. Not only that, but great core modules like Time::Piece aren’t included either!

If you don’t have corelist , but want to view a list of distributions that should have been bundled with your version of Perl, you can read perldoc perlmodlib .

Which modules do I have?

Sometimes instead of asking which modules are in the Perl Core what we really mean is: “which modules do I have installed?” For non-core modules, I use perldoc.

perldoc won’t show us the core modules that we already have, and in the case of missing core modules, Module::CoreList can’t help either (its results are based on internal lists of modules that should be there, not which files are actually present). A simple way I handle this is to use the following script to search the contents of @INC ; the directories which perl searches for modules:

#!/usr/bin/env perl use 5.10.3; use Path::Tiny 'path'; use Getopt::Long 'GetOptions'; GetOptions( 'dir=s' => \my $dirpath, ) or die "Unrecognized option

"; die "--dir is required

" unless $dirpath && -d $dirpath; # append a slash if missing $dirpath .= '/' unless substr($dirpath, -1) eq '/'; my $iter = path($dirpath)->iterator({recurse => 1}); while (my $path = $iter->()) { next unless "$path" =~ qr/.pm$/; # remove the parent dir and trailing .pm from filename my $module = substr("$path", length($dirpath), length("$path")-length($dirpath)-3); $module =~ s/\//::/g; say $module; }

I run it like this:

$ chmod 755 list_modules $ /usr/bin/perl -e 'for(@INC){ system "./list_modules -d $_" }'

I’m using the absolute path /usr/bin/perl to ensure I get my system’s perl and not the local one I manage with plenv. One downside of this approach is it lists every module ( .pm file) rather than every distribution, (see this explanation if you’re not familiar with the distinction). Another issue is it will list duplicate modules when the system uses symlinks. So the program output needs to be tidied up in a text editor.

What about programs? To search for Perl programs I prepared a list of Perl programs from the source for Perl 5.22, called perl522_programs :

c2ph corelist cpan enc2xs encguess h2ph h2xs instmodsh json_pp libnetcfg perl perl5.22.1 perlbug perldoc perlivp perlthanks piconv pl2pm pod2html pod2man pod2text pod2usage podchecker podselect prove pstruct ptar ptardiff ptargrep shasum splain xsubpp zipdetails

Then I used the following script, called find_binary to check for the programs:

#!/usr/bin/perl my $bin = shift or die "You must provide a binary name to search for

"; for ( qw(/sbin /bin /usr/sbin /usr/bin) ) { my $path = "$_/$bin"; print "$path

" if -e $path; }

I run it like this:

$ chmod 755 find_binary $ perl -ne 'chomp;system "./find_binary $_"' perl522_programs

This line calls the find_binary script on every program listed in the file perl522_programs . I chomp the line before searching for it to remove the trailing newline character. This method isn’t perfect though; sneaky Ubuntu ships with a program called perldoc but if you run it the system prints:

You need to install the perl-doc package to use this program.

Core modules and programs missing from system perls

Using the code above I did a comparison of the modules and programs shipped with Perl and those shipped with the following systems. Here’s what missing:

Fedora 23 Ubuntu 14.04 LTS OSX Yosemite 10.10.5 B::Debug CGI::Fast GDBM_File Config::Perl::V ODBM_File CPANPLUS perldoc DB_File Devel::PPPort ExtUtils::Embed ExtUtils::MakeMaker::Locale ExtUtils::Miniperl File::Fetch File::Spec::VMS Filter::Simple IO::Compress::Adapter::Bzip2 IO::Uncompress::Adapter::Bunzip2 Math::BigFloat Math::BigInt Math::BigRat Math::Complex Math::Trig Module::Loaded PerlIO Text::Balanced Time::Piece Time::Seconds Unicode::Collate autodie bigint bignum bigrat experimental perlfaq corelist enc2xs libnetcfg

Ubuntu and OSX ship with Perl 5.18 so I looked for missing programs and modules against the 5.18 source code. For Fedora I compared the system perl against the 5.22 source. These results show that Fedora is missing quite a few modules and programs: experimental, corelist, autodie, the Math:: modules and Time::Piece strike me as significant omissions (they are supplied by the perl-core package, which is must be installed separately). For Ubuntu, excluding perldoc is a real shame. OSX came away gleaming though: nearly all core modules and programs were present.

Conclusion

When writing programs that use core Perl modules be careful, especially if you’re using any of the modules or programs found to be missing earlier. One way around this is the use App::FatPacker to compile all the modules used into a single file. Another way would be to use pp to create a compiled binary. Finally for modules like Time::Piece, you could always consider wrapping Perl’s built-in functions like gmtime and localtime in subroutines that give the behavior you need, rather than using the module.

Of course it’s always easier to work with a locally-installed perl than the system version. The local Perls provided by perlbrew and plenv contain all the core modules and utilities. You can always compile your own Perl too, it’s easy. Strawberry Perl for Windows even comes with some useful extra modules and C libraries. If you do have to rely on the system Perl, you may find a core module isn’t there at all.

Updates Added reference to perl-core Fedora package, thanks to Grant McLean. 2016-03-21