1=head1 NAME 2 3HACKERS - Devel::PPPort internals for hackers 4 5=head1 SYNOPSIS 6 7So you probably want to hack C<Devel::PPPort>? 8 9Well, here's some information to get you started with what's 10lying around in this distribution. 11 12=head1 DESCRIPTION 13 14=head2 How to build 98 versions of Perl 15 16C<Devel::PPPort> supports Perl versions between 5.003 and bleadperl. 17To guarantee this support, I need some of these versions on my 18machine. I currently have 98 different Perl version/configuration 19combinations installed on my laptop. 20 21As many of the old Perl distributions need patching to compile 22cleanly on newer systems (and because building 98 Perls by hand 23just isn't fun), I wrote a tool to build all the different 24versions and configurations. You can find it in F<devel/buildperl.pl>. 25It can currently build the following Perl releases: 26 27 5.003 28 5.004 - 5.004_05 29 5.005 - 5.005_04 30 5.6.x 31 5.7.x 32 5.8.x 33 5.9.x 34 35=head2 Fully automatic API checks 36 37Knowing which parts of the API are not backwards compatible and 38probably need C<Devel::PPPort> support is another problem that's 39not easy to deal with manually. If you run 40 41 perl Makefile.PL --with-apicheck 42 43a C file is generated by F<parts/apicheck.pl> that is compiled 44and linked with C<Devel::PPPort>. This C file has the purpose of 45using each of the public API functions/macros once. 46 47The required information is derived from C<parts/embed.fnc> (just 48a copy of bleadperl's C<embed.fnc>) and C<parts/apidoc.fnc> (which 49is generated by F<devel/mkapidoc.sh> and simply collects the rest 50of the apidoc entries spread over the Perl source code). 51The generated C file C<apicheck.c> is currently about 500k in size 52and takes quite a while to compile. 53 54Usually, C<apicheck.c> won't compile with older perls. And even if 55it compiles, there's still a good chance of the dynamic linker 56failing at C<make test> time. But that's on purpose! 57 58We can use these failures to find changes in the API automatically. 59The two Perl scripts F<devel/mktodo> and F<devel/mktodo.pl> 60repeatedly run C<Devel::PPPort> with the apicheck code through 61all different versions of perl. Scanning the output of the compiler 62and the dynamic linker for errors, the files in F<parts/todo/> are 63generated. These files list all parts of the public API that don't 64work with less than a certain version of Perl. 65 66This information is in turn used by F<parts/apicheck.pl> to mask 67API calls in the generated C file for these versions, so the 68process can be stopped by the time F<apicheck.c> compiles cleanly 69and the dynamic linker is happy. (Actually, this process generates 70false positives, so each API call is checked once more afterwards.) 71 72Running C<devel/mktodo> takes a couple of hours. 73 74When running C<devel/mktodo> with the C<--base> option, it will 75generate the I<baseline> todo files by disabling all functionality 76provided by C<Devel::PPPort>. These are required for implementing 77the C<--compat-version> option of the C<ppport.h> script. The 78baseline todo files hold the information about which version of 79Perl lacks a certain part of the API. 80 81However, only the documented public API can be checked this way. 82And since C<Devel::PPPort> provides more macros, these would not be 83affected by C<--compat-version>. It's the job of F<devel/scanprov> 84to figure out the baseline information for all remaining provided 85macros by scanning the include files in the F<CORE> directory of 86various Perl versions. 87 88It's not very often that one has to regenerate the baseline and 89todo files, and the process hasn't been automated yet, but it's 90basically only the following steps: 91 92=over 4 93 94=item * 95 96You need a whole bunch of different Perls. The more, the better. 97You can use F<devel/buildperl.pl> to build them. I keep my perls 98in F</tmp/perl>, so most of the tools take this as a default. 99 100=item * 101 102Remove all existing todo files in the F<parts/base> and 103F<parts/todo> directories. 104 105=item * 106 107Update the API information. Copy the latest F<embed.fnc> file from 108bleadperl to the F<parts> directory and run F<devel/mkapidoc.sh> to 109collect the remaining information in F<parts/apidoc.fnc>. 110 111=item * 112 113Build the new baseline by running 114 115 perl devel/mktodo --base 116 117in the root directory of the distribution. When it's finished, 118move all files from the F<parts/todo> directory to F<parts/base>. 119 120=item * 121 122Build the new todo files by running 123 124 perl devel/mktodo 125 126in the root directory of the distribution. 127 128=item * 129 130Finally, add the remaining baseline information by running 131 132 perl Makefile.PL && make 133 perl devel/scanprov write 134 135=back 136 137=head2 Implementation 138 139Residing in F<parts/inc/> is the "heart" of C<Devel::PPPort>. Each 140of the files implements a part of the supported API, along with 141hints, dependency information, XS code and tests. 142The files are in a POD-like format that is parsed using the 143functions in F<parts/ppptools.pl>. 144 145The scripts F<PPPort_pm.PL>, F<PPPort_xs.PL> and F<mktests.PL> all 146use the information in F<parts/inc/> to generate the main module 147F<PPPort.pm>, the XS code in F<PPPort.xs> and various test files 148in F<t/>. 149 150All of these files could be generated on the fly while building 151C<Devel::PPPort>, but not having the tests in C<t/> and not having 152F<PPPort.xs> will confuse Configure and TEST/harness in the core. 153Not having F<PPPort.pm> will be bad for viewing the docs on 154C<search.cpan.org>. So unfortunately, it's unavoidable to put 155some redundancy into the package. 156 157=head2 Adding stuff to Devel::PPPort 158 159First, check if the code you plan to add fits into one of the 160existing files in F<parts/inc/>. If not, just start a new one and 161remember to include it from within F<PPPort_pm.PL>. 162 163Each file holds all relevant data for implementing a certain part 164of the API: 165 166=over 2 167 168=item * 169 170A list of the provided API in the C<=provides> section. 171 172=item * 173 174The implementation to add to F<ppport.h> in the C<=implementation> 175section. 176 177=item * 178 179The code required to add to PPPort.xs for testing the implementation. 180This code goes into the C<=xshead>, C<=xsinit>, C<=xsmisc>, C<=xsboot> 181and C<=xsubs> section. Have a look at the template in F<PPPort_xs.PL> 182to see where the code ends up. 183 184=item * 185 186The tests in the C<=tests> section. Remember not to use any fancy 187modules or syntax elements, as the test code should be able to run 188with Perl 5.003, which, for example, doesn't support C<my> in 189C<for>-loops: 190 191 for my $x (1, 2, 3) { } # won't work 192 193You can use C<ok()> to report success or failure. 194 195=back 196 197It's usually the best approach to just copy an existing file and 198use it as a template. 199 200=head2 Testing 201 202To automatically test C<Devel::PPPort> with lots of different Perl 203versions, you can use the F<soak> script. Just pass it a list of 204all Perl binaries you want to test. 205 206=head2 Special Makefile targets 207 208You can use 209 210 make regen 211 212to regenerate all of the autogenerated files. To get rid of all 213generated files (except for F<parts/todo/*> and F<parts/base/*>), 214use 215 216 make purge_all 217 218That's it. 219 220=head1 COPYRIGHT 221 222Version 3.x, Copyright (C) 2004-2005, Marcus Holland-Moritz. 223 224Version 2.x, Copyright (C) 2001, Paul Marquess. 225 226Version 1.x, Copyright (C) 1999, Kenneth Albanowski. 227 228This program is free software; you can redistribute it and/or 229modify it under the same terms as Perl itself. 230 231=head1 SEE ALSO 232 233See L<ppport.h>. 234 235=cut 236 237