php-ext-source-r3.eclass: Add EAPI=7 support
[gentoo.git] / eclass / php-ext-source-r3.eclass
1 # Copyright 1999-2019 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: php-ext-source-r3.eclass
5 # @MAINTAINER:
6 # Gentoo PHP team <php-bugs@gentoo.org>
7 # @SUPPORTED_EAPIS: 6 7
8 # @BLURB: Compile and install standalone PHP extensions.
9 # @DESCRIPTION:
10 # A unified interface for compiling and installing standalone PHP
11 # extensions.
12
13 inherit autotools
14
15 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_install src_test
16
17 case ${EAPI:-0} in
18         6|7) ;;
19         *)
20                 die "${ECLASS} is not compatible with EAPI=${EAPI}"
21 esac
22
23 # @ECLASS-VARIABLE: PHP_EXT_NAME
24 # @REQUIRED
25 # @DESCRIPTION:
26 # The extension name. This must be set, otherwise the eclass dies.
27 # Only automagically set by php-ext-pecl-r3.eclass, so unless your ebuild
28 # inherits that eclass, you must set this manually before inherit.
29 [[ -z "${PHP_EXT_NAME}" ]] && \
30         die "no extension name specified for the php-ext-source-r3 eclass"
31
32 # @ECLASS-VARIABLE: PHP_EXT_INI
33 # @DESCRIPTION:
34 # Controls whether or not to add a line to php.ini for the extension.
35 # Defaults to "yes" and should not be changed in most cases.
36 [[ -z "${PHP_EXT_INI}" ]] && PHP_EXT_INI="yes"
37
38 # @ECLASS-VARIABLE: PHP_EXT_ZENDEXT
39 # @DESCRIPTION:
40 # Controls whether the extension is a ZendEngine extension or not.
41 # Defaults to "no". If you don't know what this is, you don't need it.
42 [[ -z "${PHP_EXT_ZENDEXT}" ]] && PHP_EXT_ZENDEXT="no"
43
44 # @ECLASS-VARIABLE: USE_PHP
45 # @REQUIRED
46 # @DESCRIPTION:
47 # Lists the PHP slots compatible the extension is compatible with.
48 # Example:
49 # @CODE
50 # USE_PHP="php5-6 php7-0"
51 # @CODE
52 [[ -z "${USE_PHP}" ]] && \
53         die "USE_PHP is not set for the php-ext-source-r3 eclass"
54
55 # @ECLASS-VARIABLE: PHP_EXT_OPTIONAL_USE
56 # @DEFAULT_UNSET
57 # @DESCRIPTION:
58 # If set, all of the dependencies added by this eclass will be
59 # conditional on USE=${PHP_EXT_OPTIONAL_USE}. This is needed when
60 # ebuilds have to inherit this eclass unconditionally, but only
61 # actually use it when (for example) the user has USE=php.
62
63 # @ECLASS-VARIABLE: PHP_EXT_S
64 # @DESCRIPTION:
65 # The relative location of the temporary build directory for the PHP
66 # extension within the source package. This is useful for packages that
67 # bundle the PHP extension. Defaults to ${S}.
68 [[ -z "${PHP_EXT_S}" ]] && PHP_EXT_S="${S}"
69
70 # @ECLASS-VARIABLE: PHP_EXT_SAPIS
71 # @DESCRIPTION:
72 # A list of SAPIs for which we will install this extension. Formerly
73 # called PHPSAPILIST. The default includes every SAPI currently used in
74 # the tree.
75 [[ -z "${PHP_EXT_SAPIS}" ]] && PHP_EXT_SAPIS="apache2 cli cgi fpm embed phpdbg"
76
77 # @ECLASS-VARIABLE: PHP_INI_NAME
78 # @DESCRIPTION:
79 # An optional file name of the saved ini file minis the ini extension
80 # This allows ordering of extensions such that one is loaded before
81 # or after another.  Defaults to the PHP_EXT_NAME.
82 # Example (produces 40-foo.ini file):
83 # @CODE@
84 # PHP_INI_NAME="40-foo"
85 # @CODE@
86 : ${PHP_INI_NAME:=${PHP_EXT_NAME}}
87
88 # @ECLASS-VARIABLE: PHP_EXT_NEEDED_USE
89 # @DEFAULT_UNSET
90 # @DESCRIPTION:
91 # A list of USE flags to append to each PHP target selected
92 # as a valid USE-dependency string.  The value should be valid
93 # for all targets so USE defaults may be necessary.
94 # Example:
95 # @CODE
96 # PHP_EXT_NEEDED_USE="mysql?,pdo,pcre(+)"
97 # @CODE
98 #
99 # The PHP dependencies will result in:
100 # @CODE
101 # php_targets_php7-0? ( dev-lang/php:7.0[mysql?,pdo,pcre(+)] )
102 # @CODE
103
104
105 # Make sure at least one target is installed. First, start a USE
106 # conditional like "php?", but only when PHP_EXT_OPTIONAL_USE is
107 # non-null. The option group "|| (..." is always started here.
108 REQUIRED_USE="${PHP_EXT_OPTIONAL_USE}${PHP_EXT_OPTIONAL_USE:+? ( }|| ( "
109 PHPDEPEND="${PHP_EXT_OPTIONAL_USE}${PHP_EXT_OPTIONAL_USE:+? ( } "
110 for _php_target in ${USE_PHP}; do
111         # Now loop through each USE_PHP target and add the corresponding
112         # dev-lang/php slot to PHPDEPEND.
113         IUSE+=" php_targets_${_php_target}"
114         REQUIRED_USE+="php_targets_${_php_target} "
115         _php_slot=${_php_target/php}
116         _php_slot=${_php_slot/-/.}
117         if [[ ${PHP_EXT_NEEDED_USE} ]] ; then
118                 _php_slot+=[${PHP_EXT_NEEDED_USE}]
119         fi
120         PHPDEPEND+=" php_targets_${_php_target}? ( dev-lang/php:${_php_slot} )"
121 done
122
123 # Don't pollute the environment with our loop variables.
124 unset _php_slot _php_target
125
126 # Finally, end the optional group that we started before the loop. Close
127 # the USE-conditional if PHP_EXT_OPTIONAL_USE is non-null.
128 REQUIRED_USE+=") ${PHP_EXT_OPTIONAL_USE:+ )}"
129 PHPDEPEND+=" ${PHP_EXT_OPTIONAL_USE:+ )}"
130 TOOLDEPS="sys-devel/m4 sys-devel/libtool"
131
132 RDEPEND="${PHPDEPEND}"
133
134 case ${EAPI:-0} in
135         6) DEPEND="${TOOLDEPS} ${PHPDEPEND}" ;;
136         7) DEPEND="${PHPDEPEND}" ; BDEPEND="${TOOLDEPS} ${PHPDEPEND}" ;;
137 esac
138
139 unset PHPDEPEND TOOLDEPS
140
141 # @ECLASS-VARIABLE: PHP_EXT_SKIP_PHPIZE
142 # @DEFAULT_UNSET
143 # @DESCRIPTION:
144 # By default, we run "phpize" in php-ext-source-r3_src_prepare(). Set
145 # PHP_EXT_SKIP_PHPIZE="yes" in your ebuild if you do not want to run
146 # phpize (and the autoreconf that becomes necessary afterwards).
147
148 # @ECLASS-VARIABLE: PHP_EXT_SKIP_PATCHES
149 # @DEFAULT_UNSET
150 # @DESCRIPTION:
151 # By default, we run default_src_prepare to PHP_EXT_S.
152 # Set PHP_EXT_SKIP_PATCHES="yes" in your ebuild if you
153 # want to apply patches yourself.
154
155 # @FUNCTION: php-ext-source-r3_src_prepare
156 # @DESCRIPTION:
157 # Runs the default src_prepare() for PATCHES/eapply_user() support (optional),
158 # and for each PHP slot, makes a copy of sources, initializes the environment,
159 # and calls php-ext-source-r3_phpize().
160 php-ext-source-r3_src_prepare() {
161         local slot orig_s="${PHP_EXT_S}"
162         if [[ "${PHP_EXT_SKIP_PATCHES}" != 'yes' ]] ; then
163                 pushd "${orig_s}" > /dev/null || die
164                 default
165                 popd > /dev/null || die
166         fi
167         for slot in $(php_get_slots); do
168                 cp --recursive --preserve "${orig_s}" "${WORKDIR}/${slot}" || \
169                         die "failed to copy sources from ${orig_s} to ${WORKDIR}/${slot}"
170                 php_init_slot_env "${slot}"
171                 php-ext-source-r3_phpize
172         done
173 }
174
175 # @FUNCTION: php-ext-source-r3_phpize
176 # @DESCRIPTION:
177 # Subject to PHP_EXT_SKIP_PHPIZE, this function runs phpize and
178 # autoreconf in a manner that avoids warnings.
179 php-ext-source-r3_phpize() {
180         if [[ "${PHP_EXT_SKIP_PHPIZE}" != 'yes' ]] ; then
181                 # Create configure out of config.m4. We use autotools_run_tool
182                 # to avoid some warnings about WANT_AUTOCONF and
183                 # WANT_AUTOMAKE (see bugs #329071 and #549268).
184                 autotools_run_tool "${PHPIZE}"
185
186                 # Force libtoolize to run and regenerate autotools files (bug
187                 # #220519).
188                 rm aclocal.m4 || die "failed to remove aclocal.m4"
189                 eautoreconf
190         fi
191 }
192
193
194 # @ECLASS-VARIABLE: PHP_EXT_ECONF_ARGS
195 # @DEFAULT_UNSET
196 # @DESCRIPTION:
197 # Set this in the ebuild to pass additional configure options to
198 # econf. Formerly called my_conf. Either a string or an array of
199 # --flag=value parameters is supported.
200
201 # @FUNCTION: php-ext-source-r3_src_configure
202 # @DESCRIPTION:
203 # Takes care of standard configure for PHP extensions (modules).
204 php-ext-source-r3_src_configure() {
205         # net-snmp creates these, bug #385403.
206         addpredict /usr/share/snmp/mibs/.index
207         addpredict /var/lib/net-snmp/mib_indexes
208
209         # Support either a string or an array for PHP_EXT_ECONF_ARGS.
210         local econf_args
211         if [[ -n "${PHP_EXT_ECONF_ARGS}" && $(declare -p PHP_EXT_ECONF_ARGS) == "declare -a"* ]]; then
212                 econf_args=( "${PHP_EXT_ECONF_ARGS[@]}" )
213         else
214                 econf_args=( ${PHP_EXT_ECONF_ARGS} )
215         fi
216
217         local slot
218         for slot in $(php_get_slots); do
219                 php_init_slot_env "${slot}"
220                 econf --with-php-config="${PHPCONFIG}" "${econf_args[@]}"
221         done
222 }
223
224 # @FUNCTION: php-ext-source-r3_src_compile
225 # @DESCRIPTION:
226 # Compile a standard standalone PHP extension.
227 php-ext-source-r3_src_compile() {
228         # net-snmp creates these, bug #324739.
229         addpredict /usr/share/snmp/mibs/.index
230         addpredict /var/lib/net-snmp/mib_indexes
231
232         # shm extension creates a semaphore file, bug #173574.
233         addpredict /session_mm_cli0.sem
234         local slot
235         for slot in $(php_get_slots); do
236                 php_init_slot_env "${slot}"
237                 emake
238         done
239 }
240
241 # @FUNCTION: php-ext-source-r3_src_install
242 # @DESCRIPTION:
243 # Install a standard standalone PHP extension. Uses einstalldocs()
244 # to support the DOCS variable/array.
245 php-ext-source-r3_src_install() {
246         local slot
247         for slot in $(php_get_slots); do
248                 php_init_slot_env "${slot}"
249
250                 # Strip $EPREFIX from $EXT_DIR before calling doexe (which
251                 # handles EPREFIX itself). Shared libs are +x by convention,
252                 # although nothing seems to depend on that.
253                 exeinto "${EXT_DIR#$EPREFIX}"
254                 doexe "modules/${PHP_EXT_NAME}.so"
255
256                 INSTALL_ROOT="${D}" emake install-headers
257         done
258         einstalldocs
259         php-ext-source-r3_createinifiles
260 }
261
262 # @FUNCTION: php-ext-source-r3_src_test
263 # @DESCRIPTION:
264 # Run tests delivered with the standalone PHP extension. Phpize will have generated
265 # a run-tests.php file to be executed by `make test`. We only need to
266 # force the test suite to run in non-interactive mode.
267 php-ext-source-r3_src_test() {
268         local slot
269         for slot in $(php_get_slots); do
270                 php_init_slot_env "${slot}"
271                 NO_INTERACTION="yes" emake test
272         done
273 }
274
275 # @FUNCTION: php_get_slots
276 # @DESCRIPTION:
277 # Get a list of PHP slots contained in both the ebuild's USE_PHP and the
278 # user's PHP_TARGETS.
279 php_get_slots() {
280         local s=""
281         local slot
282         for slot in ${USE_PHP}; do
283                 use php_targets_${slot} && s+=" ${slot/-/.}"
284         done
285         echo $s
286 }
287
288 # @FUNCTION: php_init_slot_env
289 # @USAGE: <slot>
290 # @DESCRIPTION:
291 # Takes a slot name, and initializes some global variables to values
292 # corresponding to that slot. For example, it sets the path to the "php"
293 # and "phpize" binaries, which will differ for each slot. This function
294 # is intended to be called while looping through a list of slots
295 # obtained from php_get_slots().
296 #
297 # Calling this function will change the working directory to the
298 # temporary build directory for the given slot.
299 php_init_slot_env() {
300         local libdir=$(get_libdir)
301         local slot="${1}"
302
303         PHPPREFIX="${EPREFIX}/usr/${libdir}/${slot}"
304         PHPIZE="${PHPPREFIX}/bin/phpize"
305         PHPCONFIG="${PHPPREFIX}/bin/php-config"
306         PHPCLI="${PHPPREFIX}/bin/php"
307         PHPCGI="${PHPPREFIX}/bin/php-cgi"
308         PHP_PKG="$(best_version =dev-lang/php-${1:3}*)"
309
310         EXT_DIR="$(${PHPCONFIG} --extension-dir 2>/dev/null)"
311         PHP_CURRENTSLOT=${1:3}
312
313         PHP_EXT_S="${WORKDIR}/${slot}"
314         cd "${PHP_EXT_S}" || die "failed to change directory to ${PHP_EXT_S}"
315 }
316
317 # @FUNCTION: php_slot_ini_files
318 # @USAGE: <slot>
319 # @INTERNAL
320 # @DESCRIPTION:
321 # Output a list of relative paths to INI files for the given
322 # slot. Usually there will be one INI file per SAPI.
323 php_slot_ini_files() {
324         local slot_ini_files=""
325         local x
326         for x in ${PHP_EXT_SAPIS} ; do
327                 if [[ -f "${EPREFIX}/etc/php/${x}-${1}/php.ini" ]] ; then
328                         slot_ini_files+=" etc/php/${x}-${1}/ext/${PHP_INI_NAME}.ini"
329                 fi
330         done
331
332         echo "${slot_ini_files}"
333 }
334
335 # @FUNCTION: php-ext-source-r3_createinifiles
336 # @DESCRIPTION:
337 # Builds INI files for every enabled slot and SAPI.
338 php-ext-source-r3_createinifiles() {
339         local slot
340         for slot in $(php_get_slots); do
341                 php_init_slot_env "${slot}"
342
343                 local file
344                 for file in $(php_slot_ini_files "${slot}") ; do
345                         if [[ "${PHP_EXT_INI}" = "yes" ]] ; then
346                                 # Add the needed lines to the <ext>.ini files
347                                 php-ext-source-r3_addextension "${PHP_EXT_NAME}.so" "${file}"
348                         fi
349
350                         if [[ -n "${PHP_EXT_INIFILE}" ]] ; then
351                                 cat "${FILESDIR}/${PHP_EXT_INIFILE}" >> "${ED}/${file}" \
352                                         || die "failed to append to ${ED}/${file}"
353
354                                 einfo "Added contents of ${FILESDIR}/${PHP_EXT_INIFILE}" \
355                                           "to ${file}"
356                         fi
357                         inidir="${file/${PHP_INI_NAME}.ini/}"
358                         inidir="${inidir/ext/ext-active}"
359                         dodir "/${inidir}"
360                         dosym "/${file}" "/${file/ext/ext-active}"
361                 done
362         done
363
364         # A location where PHP code for this extension can be stored,
365         # independent of the PHP or extension versions. This will be part of
366         # PHP's include_path, configured in php.ini. For example, pecl-apcu
367         # installs an "apc.php" file which you are supposed to load with
368         #
369         #   require('apcu/apc.php');
370         #
371         PHP_EXT_SHARED_DIR="${EPREFIX}/usr/share/php/${PHP_EXT_NAME}"
372 }
373
374 # @FUNCTION: php-ext-source-r3_addextension
375 # @USAGE: <extension-path> <ini-file>
376 # @INTERNAL
377 # @DESCRIPTION:
378 # Add a line to an INI file that will enable the given extension. The
379 # first parameter is the path to the extension (.so) file, and the
380 # second parameter is the name of the INI file in which it should be
381 # loaded. This function determines the setting name (either
382 # "extension=..." or "zend_extension=...") and then calls
383 # php-ext-source-r3_addtoinifile to do the actual work.
384 php-ext-source-r3_addextension() {
385         local ext_type="extension"
386         local ext_file="${1}"
387
388         if [[ "${PHP_EXT_ZENDEXT}" = "yes" ]] ; then
389                 ext_type="zend_extension"
390                 ext_file="${EXT_DIR}/${1}" # Zend extensions need the path...
391         fi
392
393         php-ext-source-r3_addtoinifile "${2}" "${ext_type}" "${ext_file}"
394 }
395
396 # @FUNCTION: php-ext-source-r3_addtoinifile
397 # @USAGE: <relative-ini-path> <setting-or-section-name> [setting-value]
398 # @INTERNAL
399 # @DESCRIPTION:
400 # Add a setting=value to one INI file. The first argument is the
401 # relative path to the INI file. The second argument is the setting
402 # name, and the third argument is its value.
403 #
404 # You can also pass "[Section]" as the second parameter, to create a new
405 # section in the INI file. In that case, the third parameter (which
406 # would otherwise be the value of the setting) is ignored.
407 php-ext-source-r3_addtoinifile() {
408         local inifile="${WORKDIR}/${1}"
409         local inidir="${inifile%/*}"
410
411         mkdir -p "${inidir}" || die "failed to create INI directory ${inidir}"
412
413         # Are we adding the name of a section? Assume not by default.
414         local my_added="${2}=${3}"
415         if [[ ${2:0:1} == "[" ]] ; then
416                 # Ok, it's a section name.
417                 my_added="${2}"
418         fi
419         echo "${my_added}" >> "${inifile}" || die "failed to append to ${inifile}"
420         einfo "Added '${my_added}' to /${1}"
421
422         insinto "/${1%/*}"
423         doins "${inifile}"
424 }
425
426 # @FUNCTION: php-ext-source-r3_addtoinifiles
427 # @USAGE: <setting-or-section-name> [setting-value] [message]
428 # @DESCRIPTION:
429 # Add settings to every php.ini file installed by this extension.
430 # You can also add new [Section]s -- see the example below.
431 #
432 # @CODE
433 # Add some settings for the extension:
434 #
435 # php-ext-source-r3_addtoinifiles "zend_optimizer.optimization_level" "15"
436 # php-ext-source-r3_addtoinifiles "zend_optimizer.enable_loader" "0"
437 # php-ext-source-r3_addtoinifiles "zend_optimizer.disable_licensing" "0"
438 #
439 # Adding values to a section in php.ini file installed by the extension:
440 #
441 # php-ext-source-r3_addtoinifiles "[Debugger]"
442 # php-ext-source-r3_addtoinifiles "debugger.enabled" "on"
443 # php-ext-source-r3_addtoinifiles "debugger.profiler_enabled" "on"
444 # @CODE
445 php-ext-source-r3_addtoinifiles() {
446         local slot
447         for slot in $(php_get_slots); do
448                 for file in $(php_slot_ini_files "${slot}") ; do
449                         php-ext-source-r3_addtoinifile "${file}" "${1}" "${2}"
450                 done
451         done
452 }