3 HACKERS - Devel::PPPort internals for hackers
7 So you probably want to hack C<Devel::PPPort>?
9 Well, here's some information to get you started with what's
10 lying around in this distribution.
14 =head2 How to backport something
16 First, make sure that what you want to backport is documented. If it's worth
17 backporting, it surely is worth documenting. Send a documentation patch to
18 L<perlbug@perl.org|mailto:perlbug@perl.org> if necessary. Also,
19 C<Devel::PPPort> cannot automatically generate proper information about the
20 item without at least knowing its API prototype. It can get this from
21 F<embed.fnc> if the item is a function, but if it is a macro, there needs to be
22 at least a S<C<=for apidoc>> line for C<Devel::PPPort> to be able to figure
23 things out on its own.
25 Next, figure out where to place your implementation. Look at all the files in
26 F<parts/inc/> for one that fits what you're planning. If there isn't one,
27 just start a new one and remember to include it from within F<PPPort_pm.PL>.
28 If you do create a new file, it's usually the best approach to just copy an
29 existing file and use it as a template.
31 Each file holds all relevant data for implementing a certain part
38 A list of the provided API in the C<=provides> section.
42 The optional C<=dontwarn> section is used to suppress warnings about particular
43 API elements. Don't use this unless you get such a warning, and be sure to
44 think about using other other alternatives before resorting to adding something
49 The implementation to add to F<ppport.h> in the C<=implementation>
50 section. See L</Implementation Section Details>.
54 The code required to add to PPPort.xs for testing the implementation.
55 This code goes into the C<=xshead>, C<=xsinit>, C<=xsmisc>, C<=xsboot>
56 and C<=xsubs> section. Have a look at the template at the bottom
57 of F<RealPPPort_xs.PL> to see where the code ends up.
61 The tests in the C<=tests> section. Remember not to use any fancy
62 modules or syntax elements, as the test code needs to be able to run
63 with Perl 5.003. (This is because Devel::PPPort itself will run all test files
64 in the process of generating the information about when a feature came into
65 existence.) This means, for example
69 =item C<my> isn't supported in C<for>-loops
71 for my $x (1, 2, 3) { } # won't work with 5.003
73 Instead declare C<$x> just before the statement
75 =item The postfix C<for> statement modifier isn't supported
79 won't compile. Instead enclose C<foo> in a loop.
81 =item You can't use plain C<qr//>
83 Instead, wrap it in a string eval C<eval "qr//">, and be sure it's skipped at
84 execution time on perls earlier than 5.005
88 You can use C<ok()> to report success or failure:
90 ok($got, $expected, 'name');
91 ok($got == 42); # Doesn't give good runtime diagnostics
93 ok($got, eval "qr/foo/", 'name') # But don't execute this statement
94 # on perls earlier than 5.005
98 In all sections, lines that begin with C<##> are completely ignored.
100 =head2 Implementation Section Details
106 If you add the line C<__UNDEFINED__> to the C<=provides> section, you can use
107 lines like this in the C<=implementation> section:
109 __UNDEFINED__ macro some definition
111 to both define C<macro> and indicate that it is provided by F<ppport.h>. This
112 replaces these C<=implementation> section lines:
115 # define macro some definition
118 besides automagically making it be considered to be provided. C<macro> can
119 have optional arguments and the definition can even span multiple lines, like
122 __UNDEFINED__ SvMAGIC_set(sv, val) \
123 STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
124 (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END
126 This usually makes the code more compact and readable.
128 But you should only use this on things that you plan to publicly provide. If
129 something, such as a mnemonic for a constant needs to be defined but isn't
130 really needed for the public at larget to know about, you should use
132 __UNDEF_NOT_PROVIDED__ macro some definition
134 instead. To avoid name space conflicts, follow what's in L</Helper macros>,
139 If you need to define a helper macro which is not part of C<Devel::PPPort> API
140 and its usage is only for the definition of other C<Devel::PPPort> macros, then
141 use the C<D_PPP_> prefix for this macro name (e.g. C<D_PPP_SVPV_NOLEN_LP_ARG>).
142 This suppresses any warnings when a macro is defined which is not part of the
145 =item Version numbers
147 Version checking can be tricky to get correct.
150 #if { VERSION < 5.9.3 }
154 #if ((PERL_VERSION < 9) || (PERL_VERSION == 9 && PERL_SUBVERSION < 3))
156 The version number can be either of the new form C<5.x.x> or the older
157 form C<5.00x_yy>. Both are translated into the correct preprocessor
158 statements. It is also possible to combine this with other statements:
160 #if { VERSION >= 5.004 } && !defined(sv_vcatpvf)
162 #elif { VERSION < 5.004_63 } && { VERSION != 5.004_05 }
166 This not only works in the C<=implementation> section, but also in
167 the C<=xsubs>, C<=xsinit>, C<=xsmisc>, C<=xshead> and C<=xsboot> sections.
171 If you add a comment like so:
173 /* Hint: PL_expect, PL_copline, PL_rsfp
174 paragraphs of stuff about foo you want to have
175 shown when ppport.h outputs something about PL_expect or
176 PL_copline or PL_rsfp
179 Earlier versions of F<ppport.h> required an asterisk at the beginning of every
180 continuation line, or else the content would be silently dropped.
184 A more serious caution about C<foo> can be displayed by instead saying
186 /* Warning: PL_expect, PL_copline, PL_rsfp
187 paragraphs of stuff about foo you want to have
188 shown when ppport.h outputs something about PL_expect or
189 PL_copline or PL_rsfp
192 Earlier versions of F<ppport.h> required an asterisk at the beginning of every
193 continuation line, or else the content would be silently dropped.
197 When F<ppport.h> is run on a file(s), you can cause it to automatically flag
198 occurrences of the constructs you specify, encouraging the author to replace
199 them with different (presumably better) ones. These also are used in any
200 suggested edits and generated patches.
202 There are three ways to do this
206 =item in-line comment
208 You can add a trailing comment like so:
210 #define bar foo /* Replace */
211 __UNDEFINED__ bar foo /* Replace */
213 These say that C<foo> should be replaced by C<bar>. NOT the other way around.
215 =item separate comment
217 For situations not amenable to the above, you can say
219 /* Replace foo with bar */
221 =item define a replacement region
223 It you have several replacements, you can group them together like so:
230 These replace C<foo> with C<bar>; C<bat> with C<baz>.
236 F<ppport.h> automatically gathers information as to what functions are
237 dependent on what other things from inspecting the source, but if this is
238 insufficient for you, you can add lines like the following:
240 /* foo, bar depends on baz, bat */
242 Each of C<foo>, C<bar> depends on each of C<baz>, C<bat>.
248 After you have furnished your implementation, you need to test it.
250 =head2 Special Makefile targets
256 to regenerate all of the autogenerated files. To get rid of all
257 generated files (except for F<parts/todo/*> and F<parts/base/*>),
264 To automatically test C<Devel::PPPort> with lots of different Perl
265 versions, you can use the F<soak> script. Just pass it a list of
266 all Perl binaries you want to test.
268 =head2 Regenerating F<ppport.h> and F<PPPort.pm>
270 C<Devel::PPPort> keeps two directories of generated files, in F<parts/base> and
271 F<parts/todo>. The files in each are named after Perl version numbers. When a
272 function or macro came into existence is indicated by placing its name in the
273 corresponding file in F<parts/base>. The files in F<parts/todo> are the same,
274 except they indicate the earliest release that F<ppport.h> supports the
275 element. The delta is effectively what F<ppport.h> buys you.
277 The generation process described in this section creates these files. It does
278 so by examining as many perl versions as are available to it. It tries to make
279 sure each element actually compiles, and it runs the test scripts you have
280 furnished on every version.
282 Ideally, this should be done before every release that includes new backporting
283 and/or when blead has added new public API. At a minimum, it should be done as
284 the next major Perl release comes out.
286 The process isn't platform independent. It has currently been tested only under
287 Linux, and it definitely requires at least C<gcc> and the C<nm> utility.
288 The process used to be problematic, with random failures. But it has now been
289 fixed to be reliable.
291 Before starting the regeneration, you need to have gathered certain data.
292 (Options listed below apply to the tools that eventually will use the data, and
293 which are described further below).
299 You will first need a whole bunch of different Perls, the more, the better, but
300 only one per version tag (which one is random) will actually get used.
301 dromedary has a sufficient set. They should all have the same Configure
302 options with respect to what functions and macros are enabled. For example,
303 they should all be threaded, or all non-threaded. A mixture will screw up the
304 results. Similarly, they should all or none have quad math (at least as far
305 back as that became available). You can use F<devel/buildperl.pl> to build
308 Previous maintainers of this module kept those perls in
309 F</tmp/perl/install/default>, so most of the tools use this as a default, but
310 you'll likely simply use the C<--install=> option to specify where. This
311 should be a path where a S<C<make install>> has been done, so has immediate
312 subdirectories of C</bin> and C</lib>. C</bin> should contain the binaries.
313 It will use all files in this directory whose names begin with C<perl5>.
315 Actually, not all the binaries need be in this directory. You can specify
316 additional places to look since C<--install=> takes a comma separated list of
321 You also need a freshly built bleadperl. The C<--blead=I<path>> option should
322 be used to specify it. (Some of the tools have a default of C<bleadperl-debug>
323 if this option is omitted.) Again, it needs the same Configure options as the
324 earlier versions had.
328 And you will need updated API information. Copy the latest F<embed.fnc> file
329 from bleadperl to the F<parts> directory and run F<devel/mkapidoc.pl> to
330 collect the remaining information in F<parts/apidoc.fnc>.
334 The final step before regenerating everything is to run F</devel/mkppport.fnc>
335 to update the F</parts/ppport.fnc> file.
339 Having done this, run F<devel/regenerate> which wraps the following steps
340 (which you could instead do by hand, but it's easy to forget things):
346 It first does some sanity checking
350 Then it asks you if it's ok to remove all existing todo files in the
351 F<parts/base> and F<parts/todo> directories. If you answer no, the process
354 This is crtical to getting accurate results.
358 It builds the new baseline by running
360 perl devel/mktodo --base
362 in the root directory of the distribution.
364 If there are warnings in blead, it will ask you to examine them, and to ok if
365 it's all right to go ahead. If there are issues with blead, everything
366 following could be wrong.
370 It builds the new todo files by running
374 in the root directory of the distribution.
378 Finally, it adds the remaining information by running
380 perl Makefile.PL && make
381 perl devel/scanprov --mode=write
385 =head2 How to build gobs of versions of Perl
387 C<Devel::PPPort> supports Perl versions between 5.003 and bleadperl.
388 To guarantee this support, its good to have as many versions as possible to
389 test on. dromedary currently has many such versions.
391 There is a tool to build all the different
392 versions and configurations. You can find it in F<devel/buildperl.pl>.
393 It can currently build the following Perl releases:
406 =head2 Implementation
408 Knowing which parts of the API are not backwards compatible and
409 probably need C<Devel::PPPort> support is another problem that's
410 not easy to deal with manually. If you run
412 perl Makefile.PL --with-apicheck
414 a C file is generated by F<parts/apicheck.pl> that is compiled
415 and linked with C<Devel::PPPort>. This C file has the purpose of
416 using each of the public API functions/macros once.
418 The required information is derived from F<parts/embed.fnc> (just
419 a copy of bleadperl's F<embed.fnc>), F<parts/apidoc.fnc> (which
420 is generated by F<devel/mkapidoc.sh> and simply collects the rest
421 of the apidoc entries spread over the Perl source code) and
422 F<parts/ppport.fnc> (which lists the API provided purely by
423 Devel::PPPort, along with other elements that are tested only using
426 The generated C file (usually, F<apicheck.c>) won't compile as-is
427 with older perls. And even if it compiles, there's still a good chance of the
428 dynamic linker failing at C<make test> time. But that's on purpose!
430 We can use these failures to find changes in the API automatically.
431 The Perl script F<devel/mktodo> calls another script F<devel/mktodo.pl>
432 repeatedly to run C<Devel::PPPort> on version after version of perl, in
433 decreasing version order, so we start with blead and work backwards. The
434 latter script generates an F<apicheck.c>. It starts with the code that
435 successfully worked in the previously tested Perl version, which should be the
436 version one higher than the current one. Call the current one I<n>, and the
437 previous one I<n+1>. The items that fail to compile in I<n>, but did compile
438 in I<n+1> must have become available in I<n+1>. We run the Linux command C<nm>
439 to find those undefined symbols in I<n>. We change F<apicheck.c> to ignore
440 (through C<#ifdef>'s) those and recompile, repeating until F<apicheck.c>
441 successfully compiles, the dynamic linker is happy, and C<make test> runs on
442 this version. Then we repeat the process for I<n-1>, and so on. (Actually,
443 this process may generate false positives, so by default each failing API call
444 is checked again. If possible, this is done by generating an F<apicheck.c> for
445 just the one failing API.)
447 Running F<devel/mktodo> currently takes a couple hours on dromedary.
449 If you run it with the C<--nocheck> option, it won't recheck the API calls
450 that failed in the compilation stage and it'll take significantly less time.
451 No one currently associated with maintaining this module understands under what
452 circumstances it is safe to run with C<--nocheck>.
454 By repeating the process over and over, we build up information on when every
455 element first became supported. This information is stored in files in the
456 F<parts/base> directory, one file per version. The file for version I<n+1> is
457 generated by running version I<n> of perl.
459 We actually want a second piece of information, which is how much F<ppport.h>
460 buys you. What happens when regenerating is actually two entire runs through
461 all the perls. The first is accomplished by calling F<devel/mktodo> with the
462 C<--base> option. It automically will call F<devel/mktodo.pl> with each
463 version of perl, NOT using anything in F<ppport.h>. When done the results
464 indicate when each API element became available in stock perl, without using
467 And then the whole process is repeated, but this time F<ppport.h> is included.
468 The files are placed in F<parts/todo>. Thus, at the end, we know when each
469 element became available in modified perl, using F<ppport.h>.
471 However, only the public API that is implemented as functions (and must appear
472 in F<embed.fnc>) plus macros whose calling sequence is documented can be
473 checked this way. The final step in the process is calling F<devel/scanprov>.
474 It looks through the header files for when all the symbols provided by
475 C<Devel::PPPort> first became defined. It doesn't test the symbols or try to
476 compile them, as it doesn't generally know the API, but it can tell that
477 something exists in release I<n+1> but not I<n> (by scanning the include files
478 in the F<CORE> directory of various Perl versions). (It does know if a macro
479 has zero arguments or non-zero arguments, so it does get extra information from
480 the zero argument ones.)
484 Residing in F<parts/inc/> is the "heart" of C<Devel::PPPort>. Each
485 of the files implements a part of the supported API, along with
486 hints, dependency information, XS code and tests.
487 The files are in a POD-like format that is parsed using the
488 functions in F<parts/ppptools.pl>.
490 The scripts F<PPPort_pm.PL>, F<RealPPPort_xs.PL> and F<mktests.PL> all
491 use the information in F<parts/inc/> to generate the main module
492 F<PPPort.pm>, the XS code in F<RealPPPort.xs> and various test files
495 You can get extra information from F<PPPort_pm.PL> by setting the environment
496 variable C<DPPP_CHECK_LEVEL> to 1 or 2.
498 All of these files could be generated on the fly while building
499 C<Devel::PPPort>, but not having the tests in F<t/> will confuse
500 TEST/harness in the core. Not having F<PPPort.pm> will be bad for
501 viewing the docs on C<search.cpan.org>. So unfortunately, it's
502 unavoidable to put some redundancy into the package.
504 =head2 Submitting Patches
506 If you've added some functionality to C<Devel::PPPort>, please
507 consider submitting a patch with your work to P5P by sending a pull request to
509 L<https://github.com/Dual-Life/Devel-PPPort/pulls>.
511 When submitting patches, please only add the relevant changes
512 and don't include the differences of the generated files. You
513 can use the C<purge_all> target to delete all autogenerated
516 =head2 Integrating into the Perl core
518 When integrating this module into the Perl core, be sure to
519 remove the following files from the distribution. They are
520 either not needed or generated on the fly when building this
531 Version 3.x, Copyright (C) 2004-2019, Marcus Holland-Moritz
534 Version 2.x, Copyright (C) 2001, Paul Marquess.
536 Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
538 This program is free software; you can redistribute it and/or
539 modify it under the same terms as Perl itself.
543 See F<ppport.h> and F<devel/regenerate>.