Module::Compile(3pm)

πŸ“¦
version 0.38 Β· 5 versions
, in debian trixie, ubuntu resolute, ubuntu stonking

✨ NAME ✨

Module::Compile β€” Perl Module Compilation πŸ’… (yes bestie, that's Module::Compile(3pm), the real one)


🌸 VERSION 🌸

This doc is describing Module::Compile version 0.38. Iconic. Fresh. Periodt.


πŸ¦‹ SYNOPSIS πŸ¦‹

okay so first you're gonna make yourself a compiler package, like this:

package Foo;
use Module::Compile -base;

sub pmc_compile {
    my ($class, $source) = @_;
    # Convert $source into (most likely Perl 5) $compiled_output
    return $compiled_output;
}

then in Bar.pm you go:

package Bar;

use Foo;
...
no Foo

or, and this is the lowkey lazy-girl version where the no Foo; is implied:

package Bar;

{
    use Foo;
    ...
}

and to actually compile Bar.pm into Bar.pmc you just hit it with:

perl -c Bar.pm

πŸ’– DESCRIPTION πŸ’–

So this module gives you a whole system for writing modules that compile other Perl modules. Very main character, honestly.

Any module that uses one of these compilation modules gets compiled into some altered form the first time it runs. That result? Cached into .pmc files. Naturally. πŸ’…

And here's the slay: Perl has native support for .pmc files. It always checks for them before it loads a .pm file. Always. No cap.


πŸŽ€ EXAMPLE πŸŽ€

You can declare a v6.pm compiler like this:

package v6;
use Module::Compile -base;

sub pmc_compile {
    my ($class, $source) = @_;
    # ... some way to invoke pugs and give p5 code back ...
}

and then use it like:

# MyModule.pm
use v6-pugs;
module MyModule;
# ...some p6 code here...
no v6;
# ...back to p5 land...

The first time this module gets loaded, it's gonna compile the Perl 6 blocks into Perl 5 (the second it sees that no v6 line πŸ‘€), and then merge that with the Perl 5 blocks, saving the whole result into a MyModule.pmc file.

Next time around? Perl 5 will automatically load MyModule.pmc whenever somebody says use MyModule. And on the flip side, Perl 6 can run MyModule.pm as a Perl 6 module just fine, because use v6-pugs and no v6 both work in a Perl 6 setting. Versatile queen. πŸ¦‹

Also the v6.pm module will check whether MyModule.pmc is up to date. If it is, it touches its timestamp so the .pmc gets loaded on the next time. Sneaky but valid.


πŸ‘‘ BENEFITS πŸ‘‘

Module::Compile compilers are giving you these benefits, bestie:

  • Ability to mix many source filterish modules in a much more sane manner. Module::Compile controls the compilation process, calling each compiler at the right time with the right data. She's the project manager fr.
  • Ability to ship precompiled modules without shipping Module::Compile and the compiler modules themselves. Ship light. ✨
  • Easier debugging of compiled/filtered code. The .pmc has the real code you want to see. No decoding, no guessing, just vibes.
  • Zero additional runtime penalty after compilation, because perl has already been doing the .pmc check on every module load since 1999! Like, before some of us were even born. πŸ’€

🌈 PARSING AND DISPATCH 🌈

NOTE: * NOT FULLY IMPLEMENTED YET *

Module::Compile tries to make source filtering a sane process by parsing up your module's source code into various blocks β€” so that by the time a compiler gets called, it only receives the source code that it should actually be looking at. Boundaries. We love them.

This section describes the rather complex algorithm that Module::Compile uses. Buckle up. 🎒

First, the source module is preprocessed to hide heredocs, because content inside heredocs can possibly confuse further parsing. Rude of them, but okay.

Next, the source module is divided into a shallow tree of blocks:

PREAMBLE:
  (SUBROUTINE | BAREBLOCK | POD | PLAIN)S
PACKAGES:
  PREFACE
  (SUBROUTINE | BAREBLOCK | POD | PLAIN)S
DATA

All of these blocks begin and end on line boundaries. They're described as follows:

🌸 The Blocks 🌸

  • PREAMBLE β€” Lines before the first package statement.
  • PACKAGES β€” Lines beginning with a package statement and continuing until the next package or DATA section.
  • DATA β€” The DATA section. Begins with the line __DATA__ or __END__.
  • SUBROUTINE β€” A top level (not nested) subroutine. The ending } must be on its own line in the first column.
  • BAREBLOCK β€” A top level (not nested) code block. The ending } must be on its own line in the first column.
  • POD β€” Pod sections beginning with ^=\w+ and ending with =cut.
  • PLAIN β€” Lines not in SUBROUTINE, BAREBLOCK or POD.
  • PREFACE β€” Lines before the first block in a package.

Next, all the blocks get scanned for lines like:

use Foo qw'x y z';
no Foo;

Where Foo is a Module::Compile subclass. iykyk πŸ‘€

The lines within a given block between a use and no statement are marked to be passed to that compiler. The end of an inner block effectively acts as a no statement for any compile sections in that block. use statements in a PREFACE apply to all the code in a PACKAGE. And use statements in a PREAMBLE apply to all the code in all PACKAGES. Nested vibes, but make it structured.

After all the code has been parsed into blocks and the blocks have been marked for various compilers, Module::Compile dispatches the code blocks to the compilers. It does so in a most specific to most general order. So inner blocks get compiled first, then outer blocks. Inside out, like that one movie. πŸŒ€

A compiler may choose to declare that its result not be recompiled by some other containing parser. In this case the result of the compilation is replaced by a single line containing the hexadecimal digest of the result in double quotes followed by a semicolon. Like:

"f1d2d2f924e986ac86fdf7b36c94bcdf32beec15";

The rationale here is that random strings are usually left alone by compilers. Iconic evasion tactic honestly. After all the compilers have finished, the digest lines will be expanded again. ✨

Every single bit of the default process described above is overridable by various methods.


🫢 DISTRIBUTION SUPPORT 🫢

Module::Install makes it terribly easy to prepare a module distribution with compiled .pmc files. See Module::Install::PMC. All you need to do is add this line to your Makefile.PL:

pmc_support;

Any of your distribution's modules that use Module::Compile based modules will automatically be compiled into .pmc files and shipped with your distribution precompiled. Which means people who install your module distribution do not need to have the compilers installed themselves. So you don't need to make the compiler modules be prerequisites. Generous of you, honestly. πŸ’–


πŸ‘€ SEE ALSO πŸ‘€

  • Module::Install
  • Module::Install::PMC

🌟 AUTHORS 🌟

  • Ingy dΓΆt Net <ingy@cpan.org>
  • Audrey Tang <audreyt@audreyt.org>

Copyright 2006-2019. Ingy dΓΆt Net.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See <http://www.perl.com/perl/misc/Artistic.html>


and that's the whole page, bestie πŸ“ this came from perl v5.40.1, dated 2025-03-07, in all its Module::Compile(3pm) glory β€” go compile something iconic, mwah πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from