=head1 NAME

HACKERS - Devel::PPPort internals for hackers

=head1 SYNOPSIS

So you probably want to hack C<Devel::PPPort>?

Well, here's some information to get you started with what's
lying around in this distro.

=head1 DESCRIPTION

=head2 How to build 87 versions of perl

C<Devel::PPPort> supports Perl versions between 5.003 and bleadperl.
To guarantee this support, I need some of these versions on my
machine. I currently have 87 different Perl version/configuration
combinations installed on my laptop.

As many of the old Perl distributions need patching to compile
cleanly on newer systems (and because building 87 perls by hand
just isn't fun), I wrote a tool to build all the different
versions and configurations. You can find it in F<devel/buildperl.pl>.

=head2 Fully automatic API checks

Knowing which parts of the API are not backwards compatible and
probably need C<Devel::PPPort> support is another problem that's
not easy to deal with manually. If you run

    perl Makefile.PL --with-apicheck

a C file is generated by F<parts/apicheck.pl> that is compiled
and linked with C<Devel::PPPort>. This C file has the purpose of
using each of the public API functions/macros once.

The required information is derived from C<parts/embed.fnc> (just
a copy of bleadperl's C<embed.fnc>) and C<parts/apidoc.fnc> (which
is generated by F<devel/mkapidoc.sh> and simply collects the rest
of the apidoc entries spread over the Perl source code).
The generated C file C<apicheck.c> is currently about 500k in size
and takes quite a while to compile.

Usually, C<apicheck.c> won't compile with older perls. And even if
it compiles, there's still a good chance of the dynamic linker
failing at C<make test> time. But that's on purpose!

We can use these failures to find changes in the API automatically.
The two Perl scripts F<devel/mktodo> and F<devel/mktodo.pl>
repeatedly run C<Devel::PPPort> with the apicheck code through
all different versions of perl. Scanning the output of the compiler
and the dynamic linker for errors, the files in F<parts/todo/> are
generated. These files list all parts of the public API that don't
work with less than a certain version of Perl.

This information is in turn used by F<parts/apicheck.pl> to mask
API calls in the generated C file for these versions, so the
process can be stopped by the time F<apicheck.c> compiles cleanly
and the dynamic linker is happy. (Actually, this process generates
false positives, so each API call is checked once more afterwards.)

Running C<devel/mktodo> takes a couple of hours.

=head2 Implementation

Residing in F<parts/inc/> is the "heart" of C<Devel::PPPort>.  Each
of the files implements a part of the supported API, along with
hints, dependency information, XS code and tests.
The files are in a POD-like format that is parsed using the
functions in F<parts/ppptools.pl>.

The scripts F<PPPort_pm.PL>, F<PPPort_xs.PL> and F<mktests.PL> all
use the information in F<parts/inc/> to generate the main module
F<PPPort.pm>, the XS code in F<PPPort.xs> and various test files
in F<t/>.

All of these files could be generated on the fly while building
C<Devel::PPPort>, but not having the tests in C<t/> and not having
F<PPPort.xs> will confuse Configure and TEST/harness in the core.
Not having F<PPPort.pm> will be bad for viewing the docs on
C<search.cpan.org>. So unfortunately, it's unavoidable to put
some redundancy into the package.

=head2 Adding stuff to Devel::PPPort

First, check if the code you plan to add fits into one of the
existing files in F<parts/inc/>. If not, just start a new one and
remember to include it from within F<PPPort_pm.PL>.

Each file holds all relevant data for implementing a certain part
of the API:

=over 2

=item *

A list of the provided API in the C<=provides> section.

=item *

The implementation to add to F<ppport.h> in the C<=implementation>
section.

=item *

The code required to add to PPPort.xs for testing the implementation.
This code goes into the C<=xshead>, C<=xsinit>, C<=xsmisc>, C<=xsboot>
and C<=xsubs> section. Have a look at the template in F<PPPort_xs.PL>
to see where the code ends up.

=item *

The tests in the C<=tests> section. Remember not to use any fancy
modules or syntax elements, as the test code should be able to run
with Perl 5.003, which, for example, doesn't support C<my> in
C<for>-loops:

    for my $x (1, 2, 3) { }    # won't work

You can use C<ok()> to report success or failure.

=back

It's usually the best approach to just copy an existing file and
use it as a template.

=head2 Special Makefile targets.

You can use 

    make regen

to regenerate all of the autogenerated files. To get rid of
all generated files (except for parts/todo/*), use

    make purge_all

That's it.

=head1 COPYRIGHT

Version 3.x, Copyright (C) 2004, Marcus Holland-Moritz.

Version 2.x, Copyright (C) 2001, Paul Marquess.

Version 1.x, Copyright (C) 1999, Kenneth Albanowski.

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

=head1 SEE ALSO

See L<ppport.h>.

=cut

