Find Your Way Around the Perl Core Source Tree
The Perl source tree looks like chaos until you know the rule: ownership decides where a file lives, not file type. This guide gives you that map, a way to locate the right kind of file, and a small command for checking the top-level manifest. It follows the installed perlsource(1) manual from Perl 5.38.2, supplied here by perl-doc version 5.38.2-3.2ubuntu0.6. Allow about fifteen minutes to read it and another fifteen to explore a checkout.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a Perl source checkout and an ordinary shell. You do not need root privileges, and none of the commands below edits, configures or builds Perl. Keep a clean checkout when you are only investigating: it makes later changes easier to review.
1. Confirm the installed reference
Start by checking that the documentation package and interpreter are the versions you expect. These are read-only commands:
$ dpkg-query -W -f='${Package} ${Version}\n' perl perl-doc
perl 5.38.2-3.2ubuntu0.6
perl-doc 5.38.2-3.2ubuntu0.6
$ perl -v
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-gnu-thread-multi
The exact package revision and architecture can differ on your machine. What matters is that perlsource describes the layout of the Perl core source tree, not a command that searches an arbitrary installed Perl library tree. Read its version-specific description when working on another Perl release.
Checkpoint
You have a source checkout and know which Perl documentation describes it.
2. Identify the top-level areas
Most C source and headers live in the root of the checkout, alongside platform-specific directories and a handful of bundled modules with their own C or XS code. So the root is the right first stop for interpreter work, but do not expect every implementation file to sit beside perl.c.
Core modules split into four areas, and the split is about ownership and release expectations, not just file type:
lib/holds pure-Perl modules released only as part of the core, tests kept right next to the modules.ext/holds core-only modules in a CPAN-style layout, usually with their ownMakefile.PL. They may use development-version improvements and are not expected to support earlier Perl 5 releases.dist/holds dual-life modules where the Perl development tree is canonical. Some have no separate CPAN release yet.cpan/holds dual-life modules where the CPAN distribution is canonical.
Safety boundary
Do not patch a module in cpan/ as though the core tree owns it. Send the change to that module's CPAN maintainer instead; a later released version is what gets pulled into Perl.
3. Find the tests that match your change
Tests are not all in one directory. A module under lib/ normally has its test right beside it, such as lib/strict.pm and lib/strict.t. Modules under ext/, dist/ and cpan/ generally use a t/ subdirectory in their own distribution layout.
The top-level t/ tree groups tests by language or runtime concern:
t/base/covers fundamental operations and runs first.t/cmd/covers control structures and subroutines;t/comp/covers parsing and compilation.t/io/covers built-in IO and command-line arguments.t/mro/covers method resolution order, andt/op/covers built-in functions without a more specific home.t/opbasic/tests built-ins that cannot uset/test.pl, because that helper depends on the functionality under test.t/re/covers regular-expression behaviour,t/run/covers execution andPERL*environment variables, andt/uni/covers Unicode.t/win32/holds Windows-specific tests;t/porting/checks source-tree conventions and common errors.
t/lib/ is the old home for module tests. Existing tests stay there, but a new module test should follow the current layout for the module it covers.
Use the checkout itself to verify what is actually present, rather than assuming every release matches:
$ cd /path/to/perl-source
$ find lib ext dist cpan -maxdepth 2 -name 'strict.pm' -o -name 'strict.t' 2>/dev/null
$ find t -maxdepth 2 -type d | sort | sed -n '1,20p'
That first command is only a quick orientation search. For a real patch, inspect the module's own directory and its neighbouring tests before choosing a location.
4. Separate user documentation from developer notes
Documentation for Perl users lives in pod/. A module can also carry documentation in its Module.pm file, or in a matching Module.pod under lib/, ext/, dist/ or cpan/.
Documentation for people working on the core belongs in Porting/, which also holds maintenance tools and notes. Porting/Maintainers, Porting/Maintainers.pl and Porting/Maintainers.pm describe module ownership, and for a dual-life module the manual gives this lookup:
$ perl Porting/Maintainers -M Module::Name
Replace Module::Name with the module you are investigating: the command is purely informational and changes nothing. Porting/podtidy can tidy a POD file after a patch, and the Porting/check* scripts check things like C style and POD encoding.
5. Trace how a Perl build is assembled
On Unix-like systems the build starts with Configure in the source-tree root, which generates a Makefile from Makefile.SH. Platform-specific build pieces live in directories such as win32/ and vms/, each with its own Configure-like scripts.
The system behind these scripts is called metaconfig, maintained separately from the Perl core. If your work touches cross-compilation, read Cross/README and the rest of Cross/ before changing build logic. Never edit a generated Makefile as a durable fix: find the source template or configuration step that produced it.
6. Use the manifest when a filename is unclear
The root-level MANIFEST lists every file in the Perl core with a short description. The manual gives a compact way to pull top-level C and header entries out of it:
$ perl -lne 'print if /^[^\/]+\.[ch]\s+/' MANIFEST
The pattern matches entries with no slash in the path and a filename ending in .c or .h. It is an overview, not a full index of module or platform-specific code. Verify a candidate before editing:
$ test -f MANIFEST && echo 'manifest found'
manifest found
$ git status --short
An empty git status --short means the checkout has no uncommitted changes. If it prints paths, stop and understand those before adding anything of your own. None of this needs an elevated shell; do not reach for sudo to inspect a source tree.
Common traps
- Treating every module as core-owned.
cpan/has a different upstream authority than the rest of the tree. - Dumping every test under top-level
t/. Check for adjacent tests first. - Inferring build ownership from a generated
Makefile. Trace it back throughConfigureandMakefile.SHinstead. - Assuming a directory exists in every release. Check the checkout and its
MANIFESTfor the version you are changing.
Done means
- You can tell apart root C code, core modules, dual-life modules and platform-specific areas.
- You know where the relevant module tests belong and which
t/category fits a runtime change. - You can separate user POD from core-developer material in
Porting/. - You trace Unix build changes through
ConfigureandMakefile.SH, never a generated Makefile. - You checked
MANIFESTandgit status --shortbefore editing anything.