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\n";
die "--dir is required\n" 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\n";
for ( qw(/sbin /bin /usr/sbin /usr/bin) )
{
my $path = "$_/$bin";
print "$path\n" 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
This article was originally posted on PerlTricks.com.
Tags
David Farrell
David is a professional programmer who regularly tweets and blogs about code and the art of programming.
Browse their articles
Feedback
Something wrong with this article? Help us out by opening an issue or pull request on GitHub