Skip to content

Commit b8f1d73

Browse files
committed
Enable support for many php extensions
1 parent 87bc907 commit b8f1d73

6 files changed

Lines changed: 352 additions & 26 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
workspace.code-workspace
1+
workspace.code-workspace
2+
.idea

src/php/devcontainer-feature.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"default": "latest",
1717
"description": "Select or enter a PHP version"
1818
},
19+
"extensions": {
20+
"type": "string",
21+
"default": ""
22+
},
1923
"installComposer": {
2024
"type": "boolean",
2125
"default": true,

src/php/install.sh

Lines changed: 300 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ set -eux
1212
rm -rf /var/lib/apt/lists/*
1313

1414
PHP_VERSION="${VERSION:-"latest"}"
15+
read -r -a PHP_EXTENSIONS <<< "${EXTENSIONS-""}"
1516
INSTALL_COMPOSER="${INSTALLCOMPOSER:-"true"}"
1617
OVERRIDE_DEFAULT_VERSION="${OVERRIDEDEFAULTVERSION:-"true"}"
1718

19+
PHP_EXTENSIONS+=("openssl" "curl" "zlib" "mbstring")
20+
1821
export PHP_DIR="${PHP_DIR:-"/usr/local/php"}"
1922
USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
2023
UPDATE_RC="${UPDATE_RC:-"true"}"
@@ -75,12 +78,13 @@ updaterc() {
7578

7679
# Checks if packages are installed and installs them if not
7780
check_packages() {
78-
if ! dpkg -s "$@" > /dev/null 2>&1; then
81+
local packages=("$@")
82+
if ! dpkg -s "${packages[@]}" > /dev/null 2>&1; then
7983
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
8084
echo "Running apt-get update..."
8185
apt-get update -y
8286
fi
83-
apt-get -y install --no-install-recommends "$@"
87+
apt-get -y install --no-install-recommends "${packages[@]}"
8488
fi
8589
}
8690

@@ -217,19 +221,29 @@ install_php() {
217221
tar -xf $PHP_SRC_DIR/php.tar.xz -C "$PHP_SRC_DIR" --strip-components=1
218222
cd $PHP_SRC_DIR;
219223

224+
CONFIGURE_ARGS=(
225+
"--prefix=${PHP_INSTALL_DIR}"
226+
"--with-config-file-path=${PHP_INI_DIR}"
227+
"--with-config-file-scan-dir=${CONF_DIR}"
228+
"--enable-option-checking=fatal"
229+
)
230+
220231
# PHP 7.4+, the pecl/pear installers are officially deprecated and are removed in PHP 8+
221232
# Thus, requiring an explicit "--with-pear"
222233
IFS="."
223234
read -a versions <<< "${PHP_VERSION}"
224235
PHP_MAJOR_VERSION=${versions[0]}
225236
PHP_MINOR_VERSION=${versions[1]}
226237

227-
VERSION_CONFIG=""
228-
if (( $(($PHP_MAJOR_VERSION)) >= 8 )) || (( $(($PHP_MAJOR_VERSION)) == 7 && $(($PHP_MINOR_VERSION)) >= 4 )); then
229-
VERSION_CONFIG="--with-pear"
238+
if (( $(($PHP_MAJOR_VERSION)) >= 8 )) || (( $(($PHP_MAJOR_VERSION)) == 7 && $(($PHP_MINOR_VERSION)) >= 4 )); then
239+
CONFIGURE_ARGS+=("--with-pear")
230240
fi
231241

232-
./configure --prefix="${PHP_INSTALL_DIR}" --with-config-file-path="$PHP_INI_DIR" --with-config-file-scan-dir="$CONF_DIR" --enable-option-checking=fatal --with-curl --with-libedit --enable-mbstring --with-openssl --with-zlib --with-password-argon2 --with-sodium=shared "$VERSION_CONFIG" EXTENSION_DIR="$PHP_EXT_DIR";
242+
mapfile -t BUILTIN_ARGS < <(get_builtin_configure_flags "${PHP_EXTENSIONS[@]}")
243+
CONFIGURE_ARGS+=("${BUILTIN_ARGS[@]}")
244+
CONFIGURE_ARGS+=("EXTENSION_DIR=${PHP_EXT_DIR}")
245+
246+
./configure "${CONFIGURE_ARGS[@]}"
233247

234248
make -j "$(nproc)"
235249
find -type f -name '*.a' -delete
@@ -240,36 +254,297 @@ install_php() {
240254
cp -v $PHP_SRC_DIR/php.ini-* "$PHP_INI_DIR/";
241255
cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
242256

243-
# Install xdebug
244-
"${PHP_INSTALL_DIR}/bin/pecl" install xdebug
245-
XDEBUG_INI="${CONF_DIR}/xdebug.ini"
257+
install_pecl_extensions "${PHP_EXTENSIONS[@]}"
258+
}
259+
260+
is_pecl_extension() {
261+
local extension=$1
262+
local extensions=()
263+
mapfile -t extensions < <(pecl_extensions)
246264

247-
echo "zend_extension=${PHP_EXT_DIR}/xdebug.so" > "${XDEBUG_INI}"
248-
echo "xdebug.mode = debug" >> "${XDEBUG_INI}"
249-
echo "xdebug.start_with_request = yes" >> "${XDEBUG_INI}"
250-
echo "xdebug.client_port = 9003" >> "${XDEBUG_INI}"
265+
for item in "${extensions[@]}"; do
266+
if [[ "${item}" == "${extension}" ]]; then
267+
return 0
268+
fi
269+
done
270+
271+
return 1
251272
}
252273

253-
if [ "${PHP_VERSION}" != "none" ]; then
254-
# Persistent / runtime dependencies
255-
RUNTIME_DEPS="wget ca-certificates git build-essential xz-utils curl"
274+
pecl_extensions() {
275+
local packages=("xdebug" "redis" "apcu")
256276

257-
# PHP dependencies
258-
PHP_DEPS="libssl-dev libcurl4-openssl-dev libedit-dev libsqlite3-dev libxml2-dev zlib1g-dev libsodium-dev libonig-dev"
277+
printf '%s\n' "${packages[@]}"
278+
}
279+
280+
is_builtin_extension() {
281+
local extension=$1
282+
local extensions=()
283+
mapfile -t extensions < <(builtin_extensions)
284+
285+
for item in "${extensions[@]}"; do
286+
if [[ "$item" == "$extension" ]]; then
287+
return 1
288+
fi
289+
done
290+
291+
return 0
292+
}
293+
294+
builtin_extensions() {
295+
local packages=(
296+
"bcmath"
297+
"bz2"
298+
"calendar"
299+
"exif"
300+
"ftp"
301+
"gd"
302+
"gettext"
303+
"gmp"
304+
"intl"
305+
"ldap"
306+
"mbstring"
307+
"mysqli"
308+
"openssl"
309+
"password-argon2"
310+
"pcntl"
311+
"pdo"
312+
"pdo_dblib"
313+
"pdo_firebird"
314+
"pdo_oci"
315+
"pdo_odbc"
316+
"pdo_pgsql"
317+
"pdo_mysql"
318+
"pdo_sqlite"
319+
"soap"
320+
"sockets"
321+
"zip"
322+
"zlib"
323+
)
324+
325+
printf '%s\n' "${packages[@]}"
326+
}
327+
328+
get_builtin_configure_flags() {
329+
local extensions=("$@")
330+
local flags=()
331+
332+
for ext in "${extensions[@]}"; do
333+
case "$ext" in
334+
password-argon2)
335+
flags+=("--with-password-argon2")
336+
;;
337+
bcmath)
338+
flags+=("--enable-bcmath")
339+
;;
340+
bz2)
341+
flags+=("--with-bz2")
342+
;;
343+
calendar)
344+
flags+=("--enable-calendar")
345+
;;
346+
curl)
347+
flags+=("--with-curl")
348+
;;
349+
exif)
350+
flags+=("--enable-exif")
351+
;;
352+
ftp)
353+
flags+=("--enable-ftp")
354+
;;
355+
gd)
356+
flags+=("--with-gd")
357+
;;
358+
gettext)
359+
flags+=("--with-gettext")
360+
;;
361+
gmp)
362+
flags+=("--with-gmp")
363+
;;
364+
intl)
365+
flags+=("--enable-intl")
366+
;;
367+
ldap)
368+
flags+=("--with-ldap")
369+
;;
370+
mbstring)
371+
flags+=("--enable-mbstring")
372+
;;
373+
mysqli)
374+
flags+=("--with-mysqli")
375+
;;
376+
openssl)
377+
flags+=("--with-openssl")
378+
;;
379+
pcntl)
380+
flags+=("--enable-pcntl")
381+
;;
382+
pdo)
383+
flags+=("--enable-pdo")
384+
;;
385+
pdo_dblib)
386+
flags+=("--with-pdo-dblib")
387+
;;
388+
pdo_firebird)
389+
flags+=("--with-pdo-firebird")
390+
;;
391+
pdo_mysql)
392+
flags+=("--with-pdo-mysql")
393+
;;
394+
pdo_oci)
395+
flags+=("--with-pdo-oci")
396+
;;
397+
pdo_odbc)
398+
flags+=("--with-pdo-odbc")
399+
;;
400+
pdo_pgsql)
401+
flags+=("--with-pdo-pgsql")
402+
;;
403+
pdo_sqlite)
404+
flags+=("--with-pdo-sqlite")
405+
;;
406+
soap)
407+
flags+=("--enable-soap")
408+
;;
409+
sockets)
410+
flags+=("--enable-sockets")
411+
;;
412+
zip)
413+
flags+=("--with-zip")
414+
;;
415+
zlib)
416+
flags+=("--with-zlib")
417+
;;
418+
esac
419+
done
420+
421+
printf '%s\n' "${flags[@]}"
422+
}
423+
424+
get_extension_apt_packages() {
425+
local extensions=("$@")
426+
local packages=()
259427

260428
. /etc/os-release
261429

262-
if [ "${VERSION_CODENAME}" = "bionic" ]; then
263-
PHP_DEPS="${PHP_DEPS} libargon2-0-dev"
264-
else
265-
PHP_DEPS="${PHP_DEPS} libargon2-dev"
266-
fi
430+
for ext in "${extensions[@]}"; do
431+
case "$ext" in
432+
intl)
433+
packages+=("libicu-dev")
434+
;;
435+
openssl)
436+
packages+=("libssl-dev")
437+
;;
438+
zip)
439+
packages+=("libzip-dev")
440+
;;
441+
gd)
442+
packages+=("libpng-dev" "libjpeg-dev" "libfreetype6-dev")
443+
;;
444+
gmp)
445+
packages+=("libgmp-dev")
446+
;;
447+
bz2)
448+
packages+=("libbz2-dev")
449+
;;
450+
gettext)
451+
packages+=("gettext")
452+
;;
453+
soap)
454+
# libxml2-dev already present
455+
;;
456+
imagick)
457+
packages+=("libmagickwand-dev")
458+
;;
459+
curl)
460+
packages+=("libcurl4-openssl-dev")
461+
;;
462+
mbstring)
463+
packages+=("libonig-dev")
464+
;;
465+
zlib)
466+
packages+=("zlib1g-dev")
467+
;;
468+
password-argon2)
469+
if [ "${VERSION_CODENAME}" = "bionic" ]; then
470+
packages+=("libargon2-0-dev")
471+
else
472+
packages+=("libargon2-dev")
473+
fi
474+
;;
475+
pdo_pgsql)
476+
packages+=("libpq-dev")
477+
;;
478+
pdo_sqlite)
479+
packages+=("libsqlite3-dev")
480+
;;
481+
pdo_odbc)
482+
packages+=("unixodbc-dev")
483+
;;
484+
pdo_dblib)
485+
packages+=("freetds-dev")
486+
;;
487+
ldap)
488+
packages+=("libldap2-dev")
489+
;;
490+
esac
491+
done
492+
493+
printf '%s\n' "${packages[@]}" | sort -u
494+
}
495+
496+
install_pecl_extensions() {
497+
local extensions=("$@")
498+
mapfile -t known_pecl_extensions < <(pecl_extensions)
499+
500+
local pecl_extensions=()
501+
for known_pecl in "${known_pecl_extensions[@]}"; do
502+
for ext in "${extensions[@]}"; do
503+
if [[ "${known_pecl}" = "${ext}" ]]; then
504+
pecl_extensions+=("${ext}")
505+
fi
506+
done
507+
done
508+
509+
for ext in "${pecl_extensions[@]}"; do
510+
local ini_file="${CONF_DIR}/${ext}.ini"
511+
"${PHP_INSTALL_DIR}/bin/pecl" install "$ext"
512+
513+
case "$ext" in
514+
xdebug)
515+
echo "zend_extension=${PHP_EXT_DIR}/xdebug.so" > "${ini_file}"
516+
echo "xdebug.mode=debug" >> "${ini_file}"
517+
echo "xdebug.start_with_request=yes" >> "${ini_file}"
518+
echo "xdebug.client_port=9003" >> "${ini_file}"
519+
;;
520+
*)
521+
echo "extension=${ext}.so" > "${ini_file}"
522+
;;
523+
esac
524+
done
525+
}
526+
527+
if [ "${PHP_VERSION}" != "none" ]; then
528+
APT_PACKAGES=()
529+
# Persistent / runtime dependencies
530+
RUNTIME_DEPS=("wget" "ca-certificates" "git" "build-essential" "xz-utils" "curl")
531+
APT_PACKAGES+=("${RUNTIME_DEPS[@]}")
532+
533+
# PHP dependencies
534+
# PHP_DEPS="libedit-dev"
535+
PHP_DEPS=("libxml2-dev" "libsqlite3-dev")
536+
APT_PACKAGES+=("${PHP_DEPS[@]}")
267537

268538
# Dependencies required for running "phpize"
269-
PHPIZE_DEPS="autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c"
539+
# PHPIZE_DEPS="autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c"
540+
PHPIZE_DEPS=("autoconf" "pkg-config")
541+
APT_PACKAGES+=("${PHPIZE_DEPS[@]}")
542+
543+
mapfile -t BUILTIN_PACKAGE_DEPS < <(get_extension_apt_packages "${PHP_EXTENSIONS[@]}")
544+
APT_PACKAGES+=("${BUILTIN_PACKAGE_DEPS[@]}")
270545

271546
# Install dependencies
272-
check_packages $RUNTIME_DEPS $PHP_DEPS $PHPIZE_DEPS
547+
check_packages "${APT_PACKAGES[@]}"
273548

274549
# storing value of PHP_VERSION before it changes
275550
ORIGINAL_PHP_VERSION=$PHP_VERSION

0 commit comments

Comments
 (0)