1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
- = PHP Packaging Guidelines
- Fedora Packaging Guidelines for PHP addon modules
- [#types]
- == Different types of PHP packages
- There are basically 4 different kinds of PHP modules, which are packaged for Fedora:
- * https://pecl.php.net[PECL] (PHP Extension Community Library) modules,
- which are PHP modules usually written in C
- and are dynamically loaded by the PHP interpreter on startup.
- * https://pear.php.net[PEAR] (PHP Extension and Application Repository) modules,
- which are reusable components written in PHP, usually classes,
- which can be used in your own PHP applications and scripts
- by using e.g. the `+include()+` directive.
- * Composer registered libraries,
- which are reusable components written in PHP,
- usually PSR-0 compliant classes,
- registered on a package registry,
- most often on https://packagist.org/[Packagist].
- * CHANNEL : packages which register a channel.
- A channel is a repository which provides PHP extensions.
- * Other packages providing a PHP extension not handled by PEAR/PECL mechanisms.
- While upstream uses the same package and distribution format for PECL and PEAR,
- creating RPMs has to take some differences into account.
- 3 channels are defined on installation of `+php-pear+`:
- * `+pear.php.net+` (alias `+pear+`) :
- the default channel for PHP Extension and Application Repository
- * `+pecl.php.net+` (alias `+pecl+`) :
- the default channel for PHP Extension Community Library
- * `+__uri+` :
- Pseudo-channel for static packages
- Other channels must be configured at RPM build time
- and at at RPM installation time.
- [#naming-scheme]
- == Naming scheme
- * PECL packages from standard pecl channel should be named
- `+php-pecl-PECLPackageName-%{version}-%{release}.%{arch}.rpm+`.
- * PEAR packages from standard pear channel should be named
- `+php-pear-PEARPackageName-%{version}-%{release}.noarch.rpm+`.
- * CHANNEL packages should be named
- `+php-channel-ChannelAlias-%{version}-%{release}.noarch.rpm+`
- * Packages from another channel should be named
- `+php-ChannelAlias-PackageName-%{version}-%{release}.noarch.rpm+`
- * Composer enabled packages
- (referenced in packagist.org or another registry)
- should be named
- `+php-vendor-library-%{version}-%{release}.noarch.rpm+`
- (where `+vendor/library+` is the known packagist name,
- `+name+` attribute in `+composer.json+`).
- When `+vendor+` equals `+library+`, one can be dropped
- (ex `+symfony/symfony+` can be named `+php-symfony+`).
- * Other packages should be named
- `+php-PackageName-%{version}-%{release}.%{arch}.rpm+`;
- `+%{arch}+` can be `+noarch+` where appropriate.
- Please make sure that a pure PHP package (PEAR, packagist...)
- is correctly being built for `+noarch+`.
- As for other packages,
- name should only use lowercase, underscore and slash replaced by dash.
- The `+PECLPackageName+` and the `+PEARPackageName+` should be consistent
- with the upstream naming scheme.
- The Crack PHP Extension would thus be named `+php-pecl-crack+`
- with the resulting packages being
- `+php-pecl-crack-0.4-1.i386.rpm+` and `+php-pecl-crack-0.4-1.src.rpm+`.
- Note that applications that happen to be written in PHP
- do not belong under the `+php-*+` namespace.
- [#file-placement]
- == File Placement
- Non-PEAR PHP software which provides shared libraries
- should put its PHP source files for such shared libraries
- in a subfolder of `+%{_datadir}/php+`,
- named according to the name of the software.
- For example, a library called _Whizz_Bang_
- (with a RPM called `+php-something-Whizz-Bang+`)
- would put the PHP source files for its shared libraries
- in `+%{_datadir}/php/Whizz_Bang+`.
- A PSR-0 footnote:[https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md[PSR-0]] compliant library
- would put its PHP files in `+%{_datadir}/php/+`
- A PSR-4 footnote:[https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md[PSR-4]] compliant library
- would put its PHP files in `+%{_datadir}/php/+`
- in a PSR-0 compliant tree.
- PEAR documentation provided by upstream are installed in `+%{pear_docdir}+`,
- should stay there,
- and must be marked as `+%doc+`.
- PECL documentation provided by upstream is installed in `+%{pecl_docdir}+`,
- should stay there,
- and must be marked as `+%doc+`.
- The `+composer.json+` file is not used,
- and should be installed as `+%doc+`
- as it provides useful information about the package and its dependencies.
- [#requires-provides]
- == Requires and Provides
- [#requires-provides-pear]
- === PEAR Packages from the standard channel/repository
- A PEAR package *MUST* have:
- ....
- BuildRequires: php-pear(PEAR)
- Requires: php-pear(PEAR)
- Requires(post): %{__pear}
- Requires(postun): %{__pear}
- Provides: php-pear(foo) = %{version}
- ....
- The virtual provide should match exactly upstream name,
- including case and underscore, ex: `+php-pear(Text_Wiki)+`
- A PEAR package must have all its dependencies available as PEAR packages,
- so should only requires those using the `+php-pear(foo)+` virtual provides.
- Known exception for unbundled libraries
- (which are often bundled because not available in any PEAR channel).
- [#requires-provides-channel]
- === Packages for CHANNEL (repository) configuration
- A CHANNEL package *MUST* have :
- ....
- Requires: php-pear(PEAR)
- Requires(post): %{__pear}
- Requires(postun): %{__pear}
- Provides: php-channel(channelname)
- ....
- [#requires-provides-pear-nonstandard]
- === PEAR Packages from a non standard channel/repository
- A PEAR package *MUST* have:
- ....
- BuildRequires: php-channel(channelname)
- BuildRequires: php-pear(PEAR)
- Requires: php-pear(PEAR)
- Requires(post): %{__pear}
- Requires(postun): %{__pear}
- Requires: php-channel(channelname)
- Provides: php-pear(channelname/foo) = %{version}
- ....
- [#requires-provides-composer]
- === Composer registered Packages
- Each package registered on https://packagist.org/[Packagist]
- (which is the most widely used registry,
- so defined as the implicit one)
- *MUST* have
- ....
- Provides: php-composer(vendor/library) = %{version}
- ....
- Package registered on another registry *MUST* have
- ....
- Provides: php-composer(registry_url/vendor/library) = %{version}
- ....
- The virtual provide should match exactly upstream name,
- including underscore,
- ex: `+php-composer(pear/console_table)+`
- Packages moved from PEAR to Composer/Packagist
- should also Provide `+php-pear(foo)+`
- when needed (used by other PEAR packages).
- Packages must not Require any `+php-pear(foo)+`,
- but should use `+php-composer(pear/foo)+`.
- `+composer.json+` useful attributes
- (see https://getcomposer.org/doc/04-schema.md[Composer schema documentation])
- * `+name+`
- * `+description+` : 1 line, could be used as RPM summary attribute
- * `+homepage+` : could be used as RPM URL attribute
- * `+license+`
- * `+require+` :
- describes mandatory dependencies
- PHP version,
- PHP extensions
- or other composer libraries,
- those must be required by the RPM package as `+php-composer(foo)+`
- * `+require-dev+` :
- describes development dependencies,
- usually useful a build time (ex: to run unit test),
- so could appear as BuidRequires
- * `+suggest+` :
- describes optional dependencies,
- so could appear as Requires (packager choice)
- * `+conflict+` : as RPM Conflicts
- * `+replace+` : as RPM Obsoletes
- * `+provide+` :
- for additional virtual provides,
- must also be in RPM Provides as `+php-composer(foo)+`
- [#requires-provides-c]
- === C extensions (PECL and others)
- To be certain that a binary extension will run correctly
- with a particular version of PHP,
- it is necessary to check that a particular package
- has both API and ABIs matching the installed version of PHP.
- The mechanism for doing this is as follows:
- ....
- BuildRequires: php-devel
- Requires: php(zend-abi) = %{php_zend_api}
- Requires: php(api) = %{php_core_api}
- ....
- [#requires-provides-pecl]
- === PECL Packages
- PECL extension *MUST* have ABI check
- (see xref:requires-provides-c[C extensions] above).
- A PECL package *MUST* also have:
- ....
- Provides: php-pecl(foo) = %{version}
- Provides: php-pecl(foo)%{?_isa} = %{version}
- ....
- [#requires-provides-pecl-nonstandard]
- === PECL Packages from a non standard channel/repository
- A PECL package from a non standard channel MUST have
- (instead of previous provides)
- ....
- Requires: php-channel(channelname)
- Provides: php-pecl(channelname/foo) = %{version}
- Provides: php-pecl(channelname/foo)%{?_isa} = %{version}
- ....
- [#requires-provides-other]
- === Other Packages
- PHP addons which are neither PEAR nor PECL
- should require what makes sense
- (either a base PHP version or a `+php-api+`, `+php(zend-abi)+` as necessary).
- [#requires-provides-httpd]
- === Apache requirement
- A PHP library must not have an explicit Requires on `+php+` or `+httpd+`,
- since these libraries could be used with any webserver
- or any SAPI (`+php-cli+`, `+php-cgi+`, `+php-fpm+`, ...).
- Only a PHP web application,
- which provides a specific Apache httpd configuration,
- should have a Requires on `+httpd+` and `+mod_php+`.
- [#requires-provides-extensions]
- === Extensions Requires
- PHP extensions must have a Requires on all of the dependent extensions
- (`+php-date+`, `+php-gd+`, `+php-mbstring+`, ...).
- These extensions are virtual Provides of the php sub-packages.
- [#requires-provides-min-php]
- === Requiring a Minimum PHP version
- If you need to specify a minimum PHP version,
- the recommended method is to add a Requires: `+php(language) >= $VERSION+`
- (where `+$VERSION+` is the minimum PHP version).
- [#c-pecl-config-file]
- == C extension and PECL package configuration files
- Each extension should drop a configuration file
- in `+%{php_inidir}+` and/or `+%{php_ztsinidir}+`
- to enable the extension.
- This file must contain the name of the loaded extension.
- The file must use a numeric prefix to ensure correct load order:
- * range 00-19 is reserved for zend_extensions
- (ex: `+10-opcache.ini+`, `+15-xdebug.ini+`, ...)
- * range 20-39 is reserved for extensions from php sources
- (ex: `+20-pdo.ini+`, `+30-pdo_pgsql.ini+`, ...)
- * range 40-99 is available for other extensions
- (ex: `+40-zip.ini+`, ...)
- [#macros-scriptlets]
- == Macros and scriptlets
- [#macros-scriptlets-zts]
- === PHP ZTS extension
- When the Apache HTTPD is run in worker mode (instead of prefork mode),
- the ZTS (Zend Thread Safe) version of PHP is used.
- If an extension maintainer wants to provide a ZTS version of this extension,
- the maintainer must ensure that:
- * the extension is thread safe
- * the libraries used by the extension are thread safe
- The `+php-devel+` package provides the necessary files
- to build ZTS modules
- and provides several helper macros:
- For standard (NTS) extensions
- ....
- %{__php} %{_bindir}/php
- %{php_extdir} %{_libdir}/php/modules
- %{php_inidir} %{_sysconfdir}/php.d
- %{php_incldir %{_includedir}/php
- ....
- For ZTS extensions
- ....
- %{__ztsphp} %{_bindir}/zts-php
- %{php_ztsextdir} %{_libdir}/php-zts/modules
- %{php_ztsinidir} %{_sysconfdir}/php-zts.d
- %{php_ztsincldir %{_includedir}/php-zts/php
- ....
- `+php-devel+` provides the executables needed during the build of a ZTS extension,
- which are:
- * `+zts-phpize+`
- * `+zts-php-config+`
- * `+zts-php+` (which is only useful to run the test suite during build)
- [#macros-scriptlets-channel]
- === Packages for CHANNEL (repository) configuration
- Here are some recommended scriptlets
- for properly registering and unregistering the channel:
- ....
- %post
- if [ $1 -eq 1 ] ; then
- %{__pear} channel-add %{pear_xmldir}/%{name}.xml > /dev/null || :
- else
- %{__pear} channel-update %{pear_xmldir}/%{name}.xml > /dev/null ||:
- fi
- %postun
- if [ $1 -eq 0 ] ; then
- %{__pear} channel-delete %{channelname} > /dev/null || :
- fi
- ....
- [#macros-scriptlets-pear]
- === PEAR Modules
- The `+php-pear+` package provides several useful macros:
- * `+%{pear_phpdir}+`
- * `+%{pear_docdir}+` (This evaluates to `+%{_docdir}/pear+`.)
- * `+%{pear_testdir}+`
- * `+%{pear_datadir}+`
- * `+%{pear_xmldir}+`
- * `+%{pear_metadir}+` (This evaluates to `+/var/lib/pear+`.)
- These definitions for the .spec should be of interest:
- ....
- BuildRequires: php-pear >= 1:1.4.9-1.2
- Provides: php-pear(PackageName) = %{version}
- Requires: php-common >= 4.3, php-pear(PEAR)
- Requires(post): %{_bindir}/pear
- Requires(postun): %{_bindir}/pear
- ....
- Be sure you delete any PEAR metadata files at the end of `+%install+`:
- ....
- rm -rf %{buildroot}/%{pear_metadir}/.??*
- ....
- Here are some recommended scriptlets for properly registering the module:
- ....
- %post
- %{_bindir}/pear install --nodeps --soft --force --register-only %{pear_xmldir}/%{name}.xml >/dev/null ||:
- ....
- And here are some recommended scriptlets for properly unregistering the module,
- from the standard channel:
- ....
- %postun
- if [ "$1" -eq "0" ] ; then
- %{_bindir}/pear uninstall --nodeps --ignore-errors --register-only Foo_Bar >/dev/null ||:
- fi
- ....
- From a non standard channel (`+pear+` command requires the channel):
- ....
- %postun
- if [ "$1" -eq "0" ] ; then
- %{_bindir}/pear uninstall --nodeps --ignore-errors --register-only Foo_channel/Foo_Bar >/dev/null ||:
- fi
- ....
- [#macros-scriptlets-pecl]
- === PECL Modules
- The `+php-pear+` package provides several useful macros:
- * `+%{pecl_phpdir}+`
- * `+%{pecl_docdir}+`
- * `+%{pecl_testdir}+`
- * `+%{pecl_datadir}+`
- * `+%{pecl_xmldir}+`
- You may need to define a few additional macros
- to extract some information from PHP.
- It is recommended that you use the following:
- ....
- %global php_apiver %((echo 0; php -i 2>/dev/null | sed -n 's/^PHP API => //p') | tail -1)
- %{!?__pecl: %{expand: %%global __pecl %{_bindir}/pecl}}
- %{!?php_extdir: %{expand: %%global php_extdir %(php-config --extension-dir)}}
- ....
- Module (un)registration is handled automatically
- by file triggers in the `+php-pear+` package.
- For older releases,
- here are some recommended scriptlets
- for properly registering and unregistering a module:
- ....
- BuildRequires: php-pear
- Requires(post): %{__pecl}
- Requires(postun): %{__pecl}
- %post
- %{pecl_install} %{pecl_xmldir}/%{name}.xml >/dev/null || :
- %postun
- if [ $1 -eq 0 ] ; then
- %{pecl_uninstall} %{pecl_name} >/dev/null || :
- fi
- ....
- [#macros-scriptlets-other]
- === Other Modules
- If your module includes compiled code,
- you may need to define some macros
- to extract some information from PHP.
- It is recommended that you user the following:
- ....
- %global php_apiver %((echo 0; php -i 2>/dev/null | sed -n 's/^PHP API => //p') | tail -1)
- %global php_extdir %(php-config --extension-dir 2>/dev/null || echo "undefined")
- %global php_version %(php-config --version 2>/dev/null || echo 0)
- ....
- [#hints]
- == Additional Hints for Packagers
- [#hints-pear-pecl]
- === PEAR & PECL Packages
- The source archive contains a `+package.xml+` outside any directory,
- so you have to use use
- ....
- %setup -q -c
- ....
- in your `+%prep+` section to avoid writing files to the build root.
- [#hints-pear]
- === PEAR Packages
- To create your initial specfile,
- you can use the default template provided by the `+rpmdevtools+` package:
- ....
- rpmdev-newspec -t php-pear php-pear-Foo
- ....
- Or you can generate one;
- make sure you have the `+php-pear-PEAR-Command-Packaging+` package installed:
- ....
- pear make-rpm-spec Foo.tgz
- ....
|