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