This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
HACKERS: Update
[perl5.git] / dist / Devel-PPPort / HACKERS
1 =head1 NAME
2
3 HACKERS - Devel::PPPort internals for hackers
4
5 =head1 SYNOPSIS
6
7 So you probably want to hack C<Devel::PPPort>?
8
9 Well, here's some information to get you started with what's
10 lying around in this distribution.
11
12 =head1 DESCRIPTION
13
14 =head2 How to build 366 versions of Perl
15
16 C<Devel::PPPort> supports Perl versions between 5.003 and bleadperl.
17 To guarantee this support, I need some of these versions on my
18 machine. I currently have 366 different Perl version/configuration
19 combinations installed on my laptop.
20
21 As many of the old Perl distributions need patching to compile
22 cleanly on newer systems (and because building 366 Perls by hand
23 just isn't fun), I wrote a tool to build all the different
24 versions and configurations. You can find it in F<devel/buildperl.pl>.
25 It 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     5.1x.x
35     5.2x.x
36     5.3x.x
37
38 =head2 Fully automatic API checks
39
40 Knowing which parts of the API are not backwards compatible and
41 probably need C<Devel::PPPort> support is another problem that's
42 not easy to deal with manually. If you run
43
44     perl Makefile.PL --with-apicheck
45
46 a C file is generated by F<parts/apicheck.pl> that is compiled
47 and linked with C<Devel::PPPort>. This C file has the purpose of
48 using each of the public API functions/macros once.
49
50 The required information is derived from F<parts/embed.fnc> (just
51 a copy of bleadperl's F<embed.fnc>), F<parts/apidoc.fnc> (which
52 is generated by F<devel/mkapidoc.sh> and simply collects the rest
53 of the apidoc entries spread over the Perl source code) and
54 F<parts/ppport.fnc> (which lists all API provided purely by
55 Devel::PPPort).
56 The generated C file F<apicheck.c> is currently about 500k in size
57 and takes quite a while to compile.
58
59 Usually, F<apicheck.c> won't compile with older perls. And even if
60 it compiles, there's still a good chance of the dynamic linker
61 failing at C<make test> time. But that's on purpose!
62
63 We can use these failures to find changes in the API automatically.
64 The two Perl scripts F<devel/mktodo> and F<devel/mktodo.pl>
65 repeatedly run C<Devel::PPPort> with the apicheck code through
66 all different versions of perl. Scanning the output of the compiler
67 and the dynamic linker for errors, the files in F<parts/todo/> are
68 generated. These files list all parts of the public API that don't
69 work with less than a certain version of Perl.
70
71 This information is in turn used by F<parts/apicheck.pl> to mask
72 API calls in the generated C file for these versions, so the
73 process can be stopped by the time F<apicheck.c> compiles cleanly
74 and the dynamic linker is happy. (Actually, this process may generate
75 false positives, so by default each API call is checked once more
76 afterwards.)
77
78 Running F<devel/mktodo> takes about an hour, depending of course
79 on the machine you're running it on. If you run it with
80 the C<--nocheck> option, it won't recheck the API calls that failed
81 in the compilation stage and it'll take significantly less time.
82 Running with C<--nocheck> should usually be safe.
83
84 When running F<devel/mktodo> with the C<--base> option, it will
85 generate the I<baseline> todo files by disabling all functionality
86 provided by C<Devel::PPPort>. These are required for implementing
87 the C<--compat-version> option of the F<ppport.h> script. The
88 baseline todo files hold the information about which version of
89 Perl lacks a certain part of the API.
90
91 However, only the documented public API can be checked this way.
92 And since C<Devel::PPPort> provides more macros, these would not be
93 affected by C<--compat-version>. It's the job of F<devel/scanprov>
94 to figure out the baseline information for all remaining provided
95 macros by scanning the include files in the F<CORE> directory of
96 various Perl versions.
97
98 The whole process isn't platform independent. It has currently been
99 tested only under Linux, and it definitely requires at least C<gcc> and
100 the C<nm> utility.
101
102 It's not very often that one has to regenerate the baseline and todo
103 files. If you have to, you can either run F<devel/regenerate> or just
104 execute the following steps by hand:
105
106 =over 4
107
108 =item *
109
110 You need a whole bunch of different Perls. The more, the better.
111 You can use F<devel/buildperl.pl> to build them. I keep my perls
112 in F</tmp/perl>, so most of the tools take this as a default.
113
114 =item *
115
116 You also need a freshly built bleadperl that is in the path under
117 exactly this name. (The name of the executable is currently hardcoded
118 in F<devel/mktodo> and F<devel/scanprov>.)
119
120 =item *
121
122 Remove all existing todo files in the F<parts/base> and
123 F<parts/todo> directories.
124
125 =item *
126
127 Update the API information. Copy the latest F<embed.fnc> file from
128 bleadperl to the F<parts> directory and run F<devel/mkapidoc.sh> to
129 collect the remaining information in F<parts/apidoc.fnc>.
130
131 =item *
132
133 Build the new baseline by running
134
135     perl devel/mktodo --base
136
137 in the root directory of the distribution. When it's finished,
138 move all files from the F<parts/todo> directory to F<parts/base>.
139
140 =item *
141
142 Build the new todo files by running
143
144     perl devel/mktodo
145
146 in the root directory of the distribution.
147
148 =item *
149
150 Finally, add the remaining baseline information by running
151
152     perl Makefile.PL && make
153     perl devel/scanprov --mode=write
154
155 =back
156
157 =head2 Implementation
158
159 Residing in F<parts/inc/> is the "heart" of C<Devel::PPPort>. Each
160 of the files implements a part of the supported API, along with
161 hints, dependency information, XS code and tests.
162 The files are in a POD-like format that is parsed using the
163 functions in F<parts/ppptools.pl>.
164
165 The scripts F<PPPort_pm.PL>, F<RealPPPort_xs.PL> and F<mktests.PL> all
166 use the information in F<parts/inc/> to generate the main module
167 F<PPPort.pm>, the XS code in F<RealPPPort.xs> and various test files
168 in F<t/>.
169
170 You can get extra information from F<PPPort_pm.PL> by setting the environment
171 variable C<DPPP_CHECK_LEVEL> to 1 or 2.
172
173 All of these files could be generated on the fly while building
174 C<Devel::PPPort>, but not having the tests in F<t/> will confuse
175 TEST/harness in the core. Not having F<PPPort.pm> will be bad for
176 viewing the docs on C<search.cpan.org>. So unfortunately, it's
177 unavoidable to put some redundancy into the package.
178
179 =head2 Adding stuff to Devel::PPPort
180
181 First, check if the code you plan to add fits into one of the
182 existing files in F<parts/inc/>. If not, just start a new one and
183 remember to include it from within F<PPPort_pm.PL>.
184
185 Each file holds all relevant data for implementing a certain part
186 of the API:
187
188 =over 2
189
190 =item *
191
192 A list of the provided API in the C<=provides> section.
193
194 =item *
195
196 The implementation to add to F<ppport.h> in the C<=implementation>
197 section.
198
199 Here you can add additional information for a given item that will be displayed
200 when F<ppport.h> is run.  If your item is named C<foo>, you add a
201 comment like so:
202
203  /* Hint: foo
204     paragraphs of stuff about foo you want to have
205     shown when ppport.h outputs something about foo
206  */
207
208 This will cause S<C<perl ppport.h>> to display this hint when it outputs
209 something about C<foo>.
210
211 A more serious caution about C<foo> can be displayed by instead saying
212
213  /* Warning: foo
214     paragraphs of stuff about foo you want to have
215     shown when ppport.h outputs something about foo
216  */
217
218 =item *
219
220 The code required to add to PPPort.xs for testing the implementation.
221 This code goes into the C<=xshead>, C<=xsinit>, C<=xsmisc>, C<=xsboot>
222 and C<=xsubs> section. Have a look at the template at the bottom
223 of F<RealPPPort_xs.PL> to see where the code ends up.
224
225 =item *
226
227 The tests in the C<=tests> section. Remember not to use any fancy
228 modules or syntax elements, as the test code needs to be able to run
229 with Perl 5.003.  (This is because Devel::PPPort itself will run all test files
230 in the process of generating the information about when a feature came into
231 existence.)  This means, for example
232
233 =over
234
235 =item C<my> isn't supported in C<for>-loops
236
237     for my $x (1, 2, 3) { }    # won't work with 5.003
238
239 Instead declare C<$x> just before the statement
240
241 =item The postfix for statement modifier isn't supported
242
243     foo for 1..2
244
245 won't compile.  Instead enclose C<foo> in a loop.
246
247 =item You can't use plain C<qr//>
248
249 Instead, wrap it in a string eval C<eval "qr//">, and be sure it's skipped at
250 execution time on perls earlier than 5.005
251
252 =back
253
254 You can use C<ok()> to report success or failure:
255
256  ok($got, $expected, 'name');
257  ok($got == 42);     # Doesn't give good runtime diagnostics
258
259  ok($got, eval "qr/foo/", 'name') # But don't execute this statement
260                                   # on perls earlier than 5.005
261
262 =back
263
264 It's usually the best approach to just copy an existing file and
265 use it as a template.
266
267 =head2 Implementation Hints
268
269 In the C<=implementation> section, you can use
270
271   __UNDEFINED__ macro    some definition
272
273 instead of
274
275   #ifndef macro
276   #  define macro    some definition
277   #endif
278
279 The macro can have optional arguments and the definition can even
280 span multiple lines, like in
281
282   __UNDEFINED__ SvMAGIC_set(sv, val) \
283                 STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
284                 (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END
285
286 This usually makes the code more compact and readable. And you only have to add
287 the line C<__UNDEFINED__> to the C<=provides> section to get all macros
288 implemented this way to be imported into this section, so they all get
289 documented as being provided.
290
291 If you need to define a helper macro which is not part of C<Devel::PPPort> API
292 and its usage is only for definition of other C<Devel::PPPort> macros then use
293 the C<D_PPP_> prefix for this macro name (e.g. C<D_PPP_SVPV_NOLEN_LP_ARG>).
294 Some C<Devel::PPPort> scripts would report a warning when there is defined a
295 macro which is not part of Perl public API, except those macros which start
296 with the C<D_PPP_> prefix.
297
298 Version checking can be tricky to get correct.
299 You can use
300
301   #if { VERSION < 5.9.3 }
302
303 instead of
304
305   #if ((PERL_VERSION < 9) || (PERL_VERSION == 9 && PERL_SUBVERSION < 3))
306
307 The version number can be either of the new form C<5.x.x> or of the older
308 form C<5.00x_yy>. Both are translated into the correct preprocessor
309 statements. It is also possible to combine this with other statements:
310
311   #if { VERSION >= 5.004 } && !defined(sv_vcatpvf)
312     /* a */
313   #elif { VERSION < 5.004_63 } && { VERSION != 5.004_05 }
314     /* b */
315   #endif
316
317 This not only works in the C<=implementation> section, but also in
318 the C<=xsubs>, C<=xsinit>, C<=xsmisc>, C<=xshead> and C<=xsboot> sections.
319
320 =head2 Testing
321
322 To automatically test C<Devel::PPPort> with lots of different Perl
323 versions, you can use the F<soak> script. Just pass it a list of
324 all Perl binaries you want to test.
325
326 =head2 Special Makefile targets
327
328 You can use
329
330     make regen
331
332 to regenerate all of the autogenerated files. To get rid of all
333 generated files (except for F<parts/todo/*> and F<parts/base/*>),
334 use
335
336     make purge_all
337
338 That's it.
339
340 =head2 Submitting Patches
341
342 If you've added some functionality to C<Devel::PPPort>, please
343 consider submitting a patch with your work to P5P by sending a mail
344 L<perlbug@perl.org|mailto:perlbug@perl.org>.
345
346 When submitting patches, please only add the relevant changes
347 and don't include the differences of the generated files. You
348 can use the C<purge_all> target to delete all autogenerated
349 files.
350
351 =head2 Integrating into the Perl core
352
353 When integrating this module into the Perl core, be sure to
354 remove the following files from the distribution. They are
355 either not needed or generated on the fly when building this
356 module in the core:
357
358   MANIFEST
359   META.yml
360   PPPort.pm
361
362 =head1 COPYRIGHT
363
364 Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
365
366 Version 2.x, Copyright (C) 2001, Paul Marquess.
367
368 Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
369
370 This program is free software; you can redistribute it and/or
371 modify it under the same terms as Perl itself.
372
373 =head1 SEE ALSO
374
375 See F<ppport.h> and F<devel/regenerate>.
376
377 =cut