Skip to content

Commit

Permalink
Add old PHP versions through Nix
Browse files Browse the repository at this point in the history
Seeing the state of various methods to install dependencies to PHP
(pyenv, nvm and phpenv and custom PHP tarballs on Travis,
Docker and who knows what on GitHub actions), I have decided to
switch to Nix for installing all dependencies.

Unfortunately, Nixpkgs repository does not contain old PHP versions
but it is trivial with Nix to build them ourselves. We will be able to
use Cachix to avoid rebuilding them over and over again.

This is only a first step, the actual switch to Nix on CI will come later.

Also the Nixpkgs PHP infrastructure does not support overriding nicely,
I opened NixOS/nixpkgs#107044 to address that.
  • Loading branch information
jtojnar committed Dec 16, 2020
1 parent 71ff3b5 commit cb22131
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 28 deletions.
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 33 additions & 22 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,38 @@
};

outputs = { self, flake-compat, nixpkgs, utils }:
utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShell =
let
php = pkgs.php.withExtensions ({ enabled, all }: with all; enabled ++ [
imagick
let
mkDevShell = pkgs: phpPackage:
let
php = pkgs.${phpPackage}.withExtensions ({ enabled, all }: with all; enabled ++ [
imagick
]);
in
pkgs.mkShell {
nativeBuildInputs = [
php
pkgs.zola
pkgs.nodejs_latest
] ++ (with php.packages; [
composer
psalm
phpstan
]);
in
pkgs.mkShell {
nativeBuildInputs = [
php
pkgs.zola
pkgs.nodejs_latest
] ++ (with php.packages; [
composer
psalm
phpstan
]);
};
}
);
};
in
utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs.outPath {
inherit system;
overlays = [
(import ./utils/nix/phps.nix nixpkgs.outPath)
];
};
in {
packages = {
inherit (pkgs) php56 php70 php71 php72;
};
devShell = mkDevShell pkgs "php";
}
);
}
87 changes: 87 additions & 0 deletions utils/nix/intl-icu-patch-5.6-compat.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
--- a
+++ b
@@ -58,7 +58,7 @@
--- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
+++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
-@@ -26,6 +26,9 @@
+@@ -25,6 +25,9 @@
+
#include "../intl_convertcpp.h"
- #include "../intl_common.h"

+using U_ICU_NAMESPACE::RuleBasedBreakIterator;
+using U_ICU_NAMESPACE::Locale;
@@ -111,9 +111,9 @@
+
extern "C" {
#include "../php_intl.h"
- #include "../intl_common.h"
-@@ -34,6 +36,11 @@
- #include "zend_exceptions.h"
+ #define USE_TIMEZONE_POINTER 1
+@@ -32,6 +34,11 @@
+ #include <ext/date/php_date.h>
}

+using U_ICU_NAMESPACE::GregorianCalendar;
@@ -133,9 +133,9 @@
+using U_ICU_NAMESPACE::TimeZone;
+using U_ICU_NAMESPACE::UnicodeString;
+
- #include "zend_portability.h"
-
- /* {{{ timezone_convert_datetimezone
+ #ifndef INFINITY
+ #define INFINITY (DBL_MAX+DBL_MAX)
+ #endif
--- a/ext/intl/common/common_date.h
+++ b/ext/intl/common/common_date.h
@@ -28,6 +28,8 @@
@@ -144,19 +144,19 @@

+using U_ICU_NAMESPACE::TimeZone;
+
- U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func);
+ U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func TSRMLS_DC);
U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz,
- intl_error *err, const char *func);
+ intl_error *err, const char *func TSRMLS_DC);
--- a/ext/intl/common/common_enum.h
+++ b/ext/intl/common/common_enum.h
-@@ -75,6 +75,7 @@
- U_CFUNC void zoi_with_current_invalidate_current(zend_object_iterator *iter);
+@@ -69,6 +69,7 @@
+ U_CFUNC void zoi_with_current_invalidate_current(zend_object_iterator *iter TSRMLS_DC);

#ifdef __cplusplus
+using U_ICU_NAMESPACE::StringEnumeration;
- U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *object);
+ U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *object TSRMLS_DC);
#endif

--- a/ext/intl/dateformat/dateformat_format_object.cpp
+++ b/ext/intl/dateformat/dateformat_format_object.cpp
@@ -33,6 +33,12 @@
@@ -203,16 +203,16 @@
Locale const& locale,
const char *func_name,
--- a/ext/intl/intl_convertcpp.h
+++ b/ext/intl/intl_convertcpp.h
-@@ -26,6 +26,8 @@
+@@ -25,6 +25,8 @@
+
#include <unicode/unistr.h>
- #include <zend_types.h>

+using U_ICU_NAMESPACE::UnicodeString;
+
- int intl_stringFromChar(UnicodeString &ret, char *str, size_t str_len, UErrorCode *status);
-
- zend_string* intl_charFromString(const UnicodeString &from, UErrorCode *status);
+ int intl_stringFromChar(UnicodeString &ret, char *str, int32_t str_len, UErrorCode *status);
+
+ int intl_charFromString(const UnicodeString &from, char **res, int *res_len, UErrorCode *status);
--- a/ext/intl/msgformat/msgformat_helpers.cpp
+++ b/ext/intl/msgformat/msgformat_helpers.cpp
@@ -76,6 +76,16 @@MessageFormatAdapter::getMessagePattern(MessageFormat* m) {
EOF
15 changes: 15 additions & 0 deletions utils/nix/intl-icu-patch-7.0-compat.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- a
+++ b
@@ -133,8 +133,8 @@
+using U_ICU_NAMESPACE::TimeZone;
+using U_ICU_NAMESPACE::UnicodeString;
+
- #include "zend_portability.h"
-
- /* {{{ timezone_convert_datetimezone
+ #ifndef INFINITY
+ #define INFINITY (DBL_MAX+DBL_MAX)
+ #endif
--- a/ext/intl/common/common_date.h
+++ b/ext/intl/common/common_date.h
EOF
139 changes: 139 additions & 0 deletions utils/nix/phps.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
nixpkgs:

# These are older versions of PHP removed from Nixpkgs.

final: prev:

let
_args = { inherit (prev) callPackage lib stdenv nixosTests; };

generic = (import "${nixpkgs}/pkgs/development/interpreters/php/generic.nix") _args;

base56 = prev.callPackage generic (_args // {
version = "5.6.40";
sha256 = "/9Al00YjVTqy9/2Psh0Mnm+fow3FZcoDode3YwI/ugA=";
});

base70 = prev.callPackage generic (_args // {
version = "7.0.33";
sha256 = "STPqdCmKG6BGsCRv43cUFchN+4eDliAbVstTM6vobwc=";
});

base71 = prev.callPackage generic (_args // {
version = "7.1.33";
sha256 = "laXl8uK3mzdrc3qC2WgskYkeYCifokGDRjoqyhWPT0s=";
});

base72 = prev.callPackage generic (_args // {
version = "7.2.34";
sha256 = "DlgW1miiuxSspozvjEMEML2Gw8UjP2xCfRpUqsEnq88=";
});

fixDom = dom: dom.overrideAttrs (attrs: {
patches = attrs.patches or [] ++ [
# Fix tests with libxml2 2.9.10
(prev.fetchpatch {
url = "https://github.com/php/php-src/commit/e29922f054639a934f3077190729007896ae244c.patch";
sha256 = "zC2QE6snAhhA7ItXgrc80WlDVczTlZEzgZsD7AS+gtw=";
})
];
});

fixOpenssl = openssl: openssl.overrideAttrs (attrs: {
# PHP 5.6 requires openssl 1.0. It is insecure but that should not matter in an isolated test environment.
buildInputs = map (p: if p == prev.openssl then prev.openssl_1_0_2.overrideAttrs (attrs: { meta = attrs.meta // { knownVulnerabilities = []; }; }) else p) attrs.buildInputs or [];
});

fixZlib = zlib: zlib.overrideAttrs (attrs: {
# The patch do not apply to PHP 7’s zlib.
patches = if prev.lib.versionOlder zlib.version "7.1" then [] else attrs.patches;
});

fixOpcache = opcache: opcache.overrideAttrs (attrs: {
# The patch do not apply to PHP 5’s opcache.
patches = if prev.lib.versionOlder opcache.version "7.0" then [] else attrs.patches;
});

# Replace mysqlnd dependency by our fixed one.
fixMysqlndDep = ext: ext.overrideAttrs (attrs:
let
origDeps = attrs.internalDeps or [];
mysqlnds = builtins.filter (p: p.extensionName == "mysqlnd") origDeps;
in {
internalDeps = map (p: if p.extensionName == "mysqlnd" then fixMysqlnd p else p) origDeps;
preConfigure =
prev.lib.pipe (attrs.preConfigure or "") [
# We need to discard string context because replaceStrings does not seem to update it.
builtins.unsafeDiscardStringContext

# Fix mysqlnd references.
(builtins.replaceStrings (map (p: "${p.dev}") mysqlnds) (map (p: "${(fixMysqlnd p).dev}") mysqlnds))

# Re-introduce original context.
(builtins.replaceStrings (map (p: "${p.dev}") origDeps) (map (p: "${p.dev}") origDeps))
];
}
);

fixMysqlnd = mysqlnd: mysqlnd.overrideAttrs (attrs: {
postPatch = attrs.postPatch or "" + "\n" + ''
ln -s $PWD/../../ext/ $PWD
'';
});

fixRl = rl: rl.overrideAttrs (attrs: {
patches = attrs.patches or [] ++ [
# Fix readline build
(prev.fetchpatch {
url = "https://github.com/php/php-src/commit/1ea58b6e78355437b79fb7b1f287ba6688fb1c57.patch";
sha256 = "Lh2h07lKkAXpyBGqgLDNXeiOocksARTYIysLWMon694=";
})
];
});
fixIntl = intl: intl.overrideAttrs (attrs: {
doCheck = false;
patches = attrs.patches or [] ++ prev.lib.optionals (prev.lib.versionOlder intl.version "7.1") [
# Fix build with newer ICU.
(prev.fetchpatch {
url = "https://github.com/php/php-src/commit/8d35a423838eb462cd39ee535c5d003073cc5f22.patch";
sha256 = if prev.lib.versionOlder intl.version "7.0" then "8v0k6zaE5w4yCopCVa470TMozAXyK4fQelr+KuVnAv4=" else "NO3EY5z1LFWKor9c/9rJo1rpigG5x8W3Uj5+xAOwm+g=";
postFetch = ''
patch "$out" < ${if prev.lib.versionOlder intl.version "7.0" then ./intl-icu-patch-5.6-compat.patch else ./intl-icu-patch-7.0-compat.patch}
'';
})
];
});

in {
php56 = base56.withExtensions ({ all, ... }: with all; ([
bcmath calendar curl ctype (fixDom dom) exif fileinfo filter ftp gd
gettext gmp hash iconv (fixIntl intl) json ldap mbstring (fixMysqlndDep mysqli) (fixMysqlnd mysqlnd) (fixOpcache opcache)
(fixOpenssl openssl) pcntl pdo (fixMysqlndDep pdo_mysql) pdo_odbc pdo_pgsql pdo_sqlite pgsql
posix (fixRl readline) session simplexml sockets soap sqlite3
tokenizer xmlreader xmlwriter zip (fixZlib zlib)
] ++ prev.lib.optionals (!prev.stdenv.isDarwin) [ imap ]));

php70 = base70.withExtensions ({ all, ... }: with all; ([
bcmath calendar curl ctype (fixDom dom) exif fileinfo filter ftp gd
gettext gmp hash iconv (fixIntl intl) json ldap mbstring (fixMysqlndDep mysqli) (fixMysqlnd mysqlnd) opcache
(fixOpenssl openssl) pcntl pdo (fixMysqlndDep pdo_mysql) pdo_odbc pdo_pgsql pdo_sqlite pgsql
posix (fixRl readline) session simplexml sockets soap sqlite3
tokenizer xmlreader xmlwriter zip (fixZlib zlib)
] ++ prev.lib.optionals (!prev.stdenv.isDarwin) [ imap ]));

php71 = base71.withExtensions ({ all, ... }: with all; ([
bcmath calendar curl ctype (fixDom dom) exif fileinfo filter ftp gd
gettext gmp hash iconv (fixIntl intl) json ldap mbstring mysqli mysqlnd opcache
openssl pcntl pdo pdo_mysql pdo_odbc pdo_pgsql pdo_sqlite pgsql
posix (fixRl readline) session simplexml sockets soap sqlite3
tokenizer xmlreader xmlwriter zip zlib
] ++ prev.lib.optionals (!prev.stdenv.isDarwin) [ imap ]));

php72 = base72.withExtensions ({ all, ... }: with all; ([
bcmath calendar curl ctype dom exif fileinfo filter ftp gd
gettext gmp hash iconv intl json ldap mbstring mysqli mysqlnd opcache
openssl pcntl pdo pdo_mysql pdo_odbc pdo_pgsql pdo_sqlite pgsql
posix readline session simplexml sockets soap sodium sqlite3
tokenizer xmlreader xmlwriter zip zlib
] ++ prev.lib.optionals (!prev.stdenv.isDarwin) [ imap ]));
}

0 comments on commit cb22131

Please sign in to comment.