Upgrade to Devel::PPPort 3.07
[p5sagit/p5-mst-13.2.git] / ext / Devel / PPPort / HACKERS
CommitLineData
adfe19db 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
4a582685 14=head2 How to build 98 versions of Perl
adfe19db 15
16C<Devel::PPPort> supports Perl versions between 5.003 and bleadperl.
17To guarantee this support, I need some of these versions on my
4a582685 18machine. I currently have 98 different Perl version/configuration
adfe19db 19combinations installed on my laptop.
20
21As many of the old Perl distributions need patching to compile
4a582685 22cleanly on newer systems (and because building 98 Perls by hand
adfe19db 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
4a582685 132 perl Makefile.PL && make
133 perl devel/scanprov write
adfe19db 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>
0d0f8426 181and C<=xsubs> section. Have a look at the template at the bottom
182of F<PPPort_xs.PL> to see where the code ends up.
adfe19db 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
0d0f8426 191 for my $x (1, 2, 3) { } # won't work with 5.003
adfe19db 192
0d0f8426 193You can use C<ok()> to report success or failure:
194
195 ok($got == 42);
196 ok($got, $expected);
197
198Regular expressions are not supported as the second argument to C<ok>,
199because older perls do not support the C<qr> operator.
adfe19db 200
201=back
202
203It's usually the best approach to just copy an existing file and
204use it as a template.
205
0d0f8426 206=head2 Implementation Hints
207
208In the C<=implementation> section, you can use
209
210 __UNDEFINED__ macro some definition
211
212instead of
213
214 #ifndef macro
215 # define macro some definition
216 #endif
217
218The macro can have optional arguments and the definition can even
219span multiple lines, like in
220
221 __UNDEFINED__ SvMAGIC_set(sv, val) \
222 STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
223 (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END
224
225This usually makes the code more compact and readable. And you
226only have to add C<__UNDEFINED__> to the C<=provided> section.
227
228Version checking can be tricky if you want to do it correct.
229You can use
230
231 #if { VERSION < 5.9.3 }
232
233instead of
234
235 #if ((PERL_VERSION < 9) || (PERL_VERSION == 9 && PERL_SUBVERSION < 3))
236
237The version number can be either of the new form C<5.x.x> or of the older
238form C<5.00x_yy>. Both are translated into the correct preprocessor
239statements. It is also possible to combine this with other statements:
240
241 #if { VERSION >= 5.004 } && !defined(sv_vcatpvf)
242 /* a */
243 #elif { VERSION < 5.004_63 } && { VERSION != 5.004_05 }
244 /* b */
245 #endif
246
247This not only works in the C<=implementation> section, but also in
248the C<=xsubs>, C<=xsinit>, C<=xsmisc>, C<=xshead> and C<=xsboot> sections.
249
adfe19db 250=head2 Testing
251
252To automatically test C<Devel::PPPort> with lots of different Perl
253versions, you can use the F<soak> script. Just pass it a list of
254all Perl binaries you want to test.
255
256=head2 Special Makefile targets
257
4a582685 258You can use
adfe19db 259
260 make regen
261
4a582685 262to regenerate all of the autogenerated files. To get rid of all
263generated files (except for F<parts/todo/*> and F<parts/base/*>),
264use
adfe19db 265
266 make purge_all
267
268That's it.
269
0d0f8426 270=head2 Submitting Patches
271
272If you've added some functionality to C<Devel::PPPort>, please
273consider submitting a patch with your work to either the author
274(E<lt>mhx@cpan.orgE<gt>) or to the CPAN Request Tracker at
275L<http://rt.cpan.org>.
276
277When submitting patches, please only add the relevant changes
278and don't include the differences of the generated files. You
279can use the C<purge_all> target to delete all autogenerated
280files.
281
adfe19db 282=head1 COPYRIGHT
283
0d0f8426 284Version 3.x, Copyright (C) 2004-2006, Marcus Holland-Moritz.
adfe19db 285
286Version 2.x, Copyright (C) 2001, Paul Marquess.
287
288Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
289
290This program is free software; you can redistribute it and/or
291modify it under the same terms as Perl itself.
292
293=head1 SEE ALSO
294
295See L<ppport.h>.
296
297=cut
298