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 As of version 3.56 of Devel::PPPort, the old Test style tests have been
89 replaced with the more modern Test::More style, with some limitations. This
90 means, for example, that C<is> is finally available, as well as
91 C<done_testing>. You can pass the number of tests to C<skip>, instead of
92 having to have your own C<for> loop.
94 There is no C<like> nor C<unlike> (as those require C<qr> which didn't exist in
95 the earliest perls that Devel::PPPort runs on).
97 C<skip> doesn't do a S<C<last SKIP>>. (Perhaps it could, but that would mean
98 converting all the skips in the existing tests.)
100 The existing tests have been changed only as much as necessary so as to get
101 things to work. But feel free to use the full functionality for any new tests
104 Here's a list of the supported functions:
125 These are copied from F<t/test.pl> in the perl distribution. Not all of them
126 have been tested back as far as Devel::PPPort supports. Bug reports welcome.
128 It's fine to backport an element only as far as convenient and necessary. But
129 remember that your test file will end up being called on all perl versions
130 available, likely including ones earlier than your backport. That may mean
131 that elements in the C<=xs> sections will have to be C<#idef>'d out so that the
132 object will not get missing symbols when loaded.
134 It also means you have to check for and skip tests that aren't relevant to this
135 version. The recommended way to do this is like:
137 if (ivers($]) < ivers(5.6.2)) {
138 skip "reason", $count;
140 elsif (if (ivers($]) > ivers(5.5) {
141 skip "other reason", $count;
144 C<ivers()> is a function automatically made available to all F<.t> files. It
145 converts any reasonble expression of a version number into an integer, which
146 can reliably be compared using numeric comparison operators, with the output of
147 a second C<ivers()> call on a different version number, like in the result above.
151 In all sections, lines that begin with C<##> are completely ignored.
153 =head2 Implementation Section Details
155 You can implement API elements via C functions or macros, or simple variables.
156 For a function, just place its body in this C<=implementation> section. But it
157 is preferable to use a macro if feasible. Otherwise, the user must explicitly
158 request that it get loaded, by defining a C<NEED_I<function>> (or I<variable>)
159 as described in F<ppport.h>.
165 If you add the line C<__UNDEFINED__> to the C<=provides> section, you can use
166 lines like this in the C<=implementation> section:
168 __UNDEFINED__ macro some definition
170 to both define C<macro> and indicate that it is provided by F<ppport.h>. This
171 replaces these C<=implementation> section lines:
174 # define macro some definition
177 besides automagically making it be considered to be provided. C<macro> can
178 have optional arguments and the definition can even span multiple lines, like
181 __UNDEFINED__ SvMAGIC_set(sv, val) \
182 STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
183 (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } \
186 This usually makes the code more compact and readable.
188 But you should only use this on things that you plan to publicly provide. If
189 something, such as a mnemonic for a constant needs to be defined but isn't
190 really needed for the public at large to know about, you should use
192 __UNDEF_NOT_PROVIDED__ macro some definition
194 instead. To avoid name space conflicts, follow what's in L</Helper macros>,
199 If you need to define a helper macro which is not part of C<Devel::PPPort> API
200 and its usage is only for the definition of other C<Devel::PPPort> macros, then
201 use the C<D_PPP_> prefix for this macro name (e.g. C<D_PPP_SVPV_NOLEN_LP_ARG>).
202 This suppresses any warnings when a macro is defined which is not part of the
205 =item Version numbers
207 Version checking can be tricky to get correct (besides being buggy in some perl
209 C<ivers()> is used in the C<=tests> section to overcome this, and constructs
210 like the following in the C language sections.
212 #if { VERSION < 5.9.3 }
216 #if ((PERL_VERSION < 9) \
217 || (PERL_VERSION == 9 && PERL_SUBVERSION < 3))
219 The version number can be either of the new form C<5.x.x> or the older
220 form C<5.00x_yy>. Both are translated into the correct preprocessor
221 statements. It is also possible to combine this with other statements:
223 #if { VERSION >= 5.004 } && !defined(sv_vcatpvf)
225 #elif { VERSION < 5.004_63 } && { VERSION != 5.004_05 }
229 This not only works in the C<=implementation> section, but also in
230 the C<=xsubs>, C<=xsinit>, C<=xsmisc>, C<=xshead> and C<=xsboot> sections.
234 If you add a comment like so:
236 /* Hint: PL_expect, PL_copline, PL_rsfp
237 paragraphs of stuff about foo you want to have
238 shown when ppport.h outputs something about PL_expect or
239 PL_copline or PL_rsfp
242 Earlier versions of F<ppport.h> required an asterisk at the beginning of every
243 continuation line, or else the content would be silently dropped.
247 A more serious caution about C<foo> can be displayed by instead saying
249 /* Warning: PL_expect, PL_copline, PL_rsfp
250 paragraphs of stuff about foo you want to have
251 shown when ppport.h outputs something about PL_expect or
252 PL_copline or PL_rsfp
255 Earlier versions of F<ppport.h> required an asterisk at the beginning of every
256 continuation line, or else the content would be silently dropped.
260 When F<ppport.h> is run on a file(s), you can cause it to automatically flag
261 occurrences of the constructs you specify, encouraging the author to replace
262 them with different (presumably better) ones. These also are used in any
263 suggested edits and generated patches.
265 There are three ways to do this
269 =item in-line comment
271 You can add a trailing comment like so:
273 #define bar foo /* Replace */
274 __UNDEFINED__ bar foo /* Replace */
276 These say that C<foo> should be replaced by C<bar>. NOT the other way around.
278 =item separate comment
280 For situations not amenable to the above, you can say
282 /* Replace foo with bar */
284 =item define a replacement region
286 It you have several replacements, you can group them together like so:
293 These replace C<bar> with C<foo>; C<baz> with C<bat>. NOT the other way
300 F<ppport.h> automatically gathers information as to what functions are
301 dependent on what other things from inspecting the source, but if this is
302 insufficient for you, you can add lines like the following:
304 /* foo, bar depends on baz, bat */
306 Each of C<foo>, C<bar> depends on each of C<baz>, C<bat>.
312 After you have furnished your implementation, you need to test it.
314 =head2 Special Makefile targets
320 to regenerate all of the autogenerated files. To get rid of all
321 generated files (except for F<parts/todo/*> and F<parts/base/*>),
328 To automatically test C<Devel::PPPort> with lots of different Perl
329 versions, you can use the F<soak> script. Just pass it a list of
330 all Perl binaries you want to test.
332 =head2 Regenerating F<ppport.h> and F<PPPort.pm>
334 C<Devel::PPPort> keeps two directories of generated files, in F<parts/base> and
335 F<parts/todo>. The files in each are named after Perl version numbers. When a
336 function or macro came into existence is indicated by placing its name in the
337 corresponding file in F<parts/base>. The files in F<parts/todo> are the same,
338 except they indicate the earliest release that F<ppport.h> supports the
339 element. The delta is effectively what F<ppport.h> buys you.
341 The generation process described in this section creates these files. It does
342 so by examining as many perl versions as are available to it. It tries to make
343 sure each element actually compiles, and it runs the test scripts you have
344 furnished on every version.
346 Ideally, this should be done before every release that includes new backporting
347 and/or when blead has added new public API. At a minimum, it should be done as
348 the next major Perl release comes out.
350 The process isn't platform independent. It has currently been tested only under
351 Linux, and it definitely requires at least C<gcc> and the C<nm> utility.
352 The process used to be problematic, with random failures. But it has now been
353 fixed to be reliable.
355 Before starting the regeneration, you need to have gathered certain data.
356 (Options listed below apply to the tools that eventually will use the data, and
357 which are described further below).
363 You will first need a whole bunch of different Perls, the more, the better, but
364 only one per version tag (which one is random) will actually get used.
365 dromedary has a sufficient set. They should all have the same Configure
366 options with respect to what functions and macros are enabled. For example,
367 they should all be threaded, or all non-threaded. A mixture will screw up the
368 results. Similarly, they should all or none have quad math (at least as far
369 back as that became available). You can use F<devel/buildperl.pl> to build
372 Previous maintainers of this module kept those perls in
373 F</tmp/perl/install/default>, so most of the tools use this as a default, but
374 you'll likely simply use the C<--install=> option to specify where. This
375 should be a path where a S<C<make install>> has been done, so has immediate
376 subdirectories of C</bin> and C</lib>. C</bin> should contain the binaries.
377 It will use all files in this directory whose names begin with C<perl5>.
379 Actually, not all the binaries need be in this directory. You can specify
380 additional places to look since C<--install=> takes a comma separated list of
385 You also need a freshly built bleadperl. The C<--blead=I<path>> option should
386 be used to specify it. (Some of the tools have a default of C<bleadperl-debug>
387 if this option is omitted.) Again, it needs the same Configure options as the
388 earlier versions had. Using C<-DNO_MATHOMS> will change the results, and
389 probably should be avoided. True, these functions are allegedly on their way
390 out, so it could be argued that they shouldn't be encouraged in any way; but
391 some of these have been in limbo for many years, so should be documented.
395 And you will need updated API information. Copy the latest F<embed.fnc> file
396 from bleadperl to the F<parts> directory and run F<devel/mkapidoc.pl> to
397 collect the remaining information in F<parts/apidoc.fnc>.
401 The final step before regenerating everything is to run
402 F</devel/mkppport_fnc.pl> to update the F</parts/ppport.fnc> file.
406 Having done this, run F<devel/regenerate> which wraps the following steps
407 (which you could instead do by hand, but it's easy to forget things):
413 It first does some sanity checking
417 Then it asks you if it's ok to remove all existing todo files in the
418 F<parts/base> and F<parts/todo> directories. If you answer no, the process
421 This is crtical to getting accurate results.
425 It builds the new baseline by running
427 perl devel/mktodo --base
429 in the root directory of the distribution.
431 If there are warnings in blead, it will ask you to examine them, and to ok if
432 it's all right to go ahead. If there are issues with blead, everything
433 following could be wrong.
437 It builds the new todo files by running
441 in the root directory of the distribution.
445 Finally, it adds the remaining information by running
447 perl Makefile.PL && make
448 perl devel/scanprov --mode=write
452 =head2 How to build gobs of versions of Perl
454 C<Devel::PPPort> supports Perl versions between 5.003 and bleadperl.
455 To guarantee this support, its good to have as many versions as possible to
456 test on. dromedary currently has many such versions.
458 There is a tool to build all the different
459 versions and configurations. You can find it in F<devel/buildperl.pl>.
460 It can currently build the following Perl releases:
473 =head2 Implementation
475 Knowing which parts of the API are not backwards compatible and
476 probably need C<Devel::PPPort> support is another problem that's
477 not easy to deal with manually. If you run
479 perl Makefile.PL --with-apicheck
481 a C file is generated by F<parts/apicheck.pl> that is compiled
482 and linked with C<Devel::PPPort>. This C file has the purpose of
483 using each of the public API functions/macros once.
485 The required information is derived from F<parts/embed.fnc> (just
486 a copy of bleadperl's F<embed.fnc>), F<parts/apidoc.fnc> (which
487 is generated by F<devel/mkapidoc.pl> and simply collects the rest
488 of the apidoc entries spread over the Perl source code) and
489 F<parts/ppport.fnc> (which lists the API provided purely by
490 Devel::PPPort, along with other elements that are tested only using
493 The generated C file (usually, F<apicheck.c>) won't compile as-is
494 with older perls. And even if it compiles, there's still a good chance of the
495 dynamic linker failing at C<make test> time. But that's on purpose!
497 We can use these failures to find changes in the API automatically.
498 The Perl script F<devel/mktodo> calls another script F<devel/mktodo.pl>
499 repeatedly to run C<Devel::PPPort> on version after version of perl, in
500 decreasing version order, so we start with blead and work backwards. The
501 latter script generates an F<apicheck.c>. It starts with the code that
502 successfully worked in the previously tested Perl version, which should be the
503 version one higher than the current one. Call the current one I<n>, and the
504 previous one I<n+1>. The items that fail to compile in I<n>, but did compile
505 in I<n+1> must have become available in I<n+1>. We run the Linux command C<nm>
506 to find those undefined symbols in I<n>. We change F<apicheck.c> to ignore
507 (through C<#ifdef>'s) those and recompile, repeating until F<apicheck.c>
508 successfully compiles, the dynamic linker is happy, and C<make test> runs on
509 this version. Then we repeat the process for I<n-1>, and so on. (Actually,
510 this process may generate false positives, so by default each failing API call
511 is checked again. If possible, this is done by generating an F<apicheck.c> for
512 just the one failing API.) Note that the make test is run using F<ppport.h>
515 Running F<devel/mktodo> currently takes a couple hours on dromedary.
517 If you run it with the C<--nocheck> option, it won't recheck the API calls
518 that failed in the compilation stage and it'll take significantly less time.
519 No one currently associated with maintaining this module understands under what
520 circumstances it is safe to run with C<--nocheck>.
522 By repeating the process over and over, we build up information on when every
523 element first became supported. This information is stored in files in the
524 F<parts/base> directory, one file per version. The file for version I<n+1> is
525 generated by running version I<n> of perl.
527 We actually want a second piece of information, which is how much F<ppport.h>
528 buys you. What happens when regenerating is actually two entire runs through
529 all the perls. The first is accomplished by calling F<devel/mktodo> with the
530 C<--base> option. It automically will call F<devel/mktodo.pl> with each
531 version of perl, NOT using anything in F<ppport.h>. When done the results
532 indicate when each API element became available in stock perl, without using
535 And then the whole process is repeated, but this time F<ppport.h> is included.
536 The files are placed in F<parts/todo>. Thus, at the end, we know when each
537 element became available in modified perl, using F<ppport.h>.
539 However, only the public API that is implemented as functions (and must appear
540 in F<embed.fnc>) plus macros whose calling sequence is documented can be
541 checked this way. The final step in the process is calling F<devel/scanprov>.
542 It looks through the header files for when all the symbols provided by
543 C<Devel::PPPort> first became defined. It doesn't test the symbols or try to
544 compile them, as it doesn't generally know the API, but it can tell that
545 something exists in release I<n+1> but not I<n> (by scanning the include files
546 in the F<CORE> directory of various Perl versions). (It does know if a macro
547 has zero arguments or non-zero arguments, so it does get extra information from
548 the zero argument ones.)
552 Residing in F<parts/inc/> is the "heart" of C<Devel::PPPort>. Each
553 of the files implements a part of the supported API, along with
554 hints, dependency information, XS code and tests.
555 The files are in a POD-like format that is parsed using the
556 functions in F<parts/ppptools.pl>.
558 The scripts F<PPPort_pm.PL>, F<RealPPPort_xs.PL> and F<mktests.PL> all
559 use the information in F<parts/inc/> to generate the main module
560 F<PPPort.pm>, the XS code in F<RealPPPort.xs> and various test files
563 You can get extra information from F<PPPort_pm.PL> by setting the environment
564 variable C<DPPP_CHECK_LEVEL> to 1 or 2.
566 All of these files could be generated on the fly while building
567 C<Devel::PPPort>, but not having the tests in F<t/> will confuse
568 TEST/harness in the core. Not having F<PPPort.pm> will be bad for
569 viewing the docs on C<search.cpan.org>. So unfortunately, it's
570 unavoidable to put some redundancy into the package.
572 =head2 Submitting Patches
574 If you've added some functionality to C<Devel::PPPort>, please
575 consider submitting a patch with your work to P5P by sending a pull request to
577 L<https://github.com/Dual-Life/Devel-PPPort/pulls>.
579 When submitting patches, please only add the relevant changes
580 and don't include the differences of the generated files. You
581 can use the C<purge_all> target to delete all autogenerated
584 =head2 Integrating into the Perl core
586 When integrating this module into the Perl core, be sure to
587 remove the following files from the distribution. They are
588 either not needed or generated on the fly when building this
601 Version 3.x, Copyright (C) 2004-2019, Marcus Holland-Moritz
604 Version 2.x, Copyright (C) 2001, Paul Marquess.
606 Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
608 This program is free software; you can redistribute it and/or
609 modify it under the same terms as Perl itself.
613 See F<ppport.h> and F<devel/regenerate>.