Merge pull request #268619 from tweag/lib-descriptions
[NixPkgs.git] / pkgs / top-level / php-packages.nix
blob20e39d98fb42af16d90c7d233357d97429a84147
1 { stdenv
2 , config
3 , callPackages
4 , lib
5 , pkgs
6 , phpPackage
7 , autoconf
8 , pkg-config
9 , aspell
10 , bzip2
11 , curl
12 , cyrus_sasl
13 , enchant2
14 , freetds
15 , gd
16 , gettext
17 , gmp
18 , html-tidy
19 , icu64
20 , libffi
21 , libiconv
22 , libkrb5
23 , libsodium
24 , libxml2
25 , libxslt
26 , libzip
27 , net-snmp
28 , nix-update-script
29 , oniguruma
30 , openldap
31 , openssl_1_1
32 , openssl
33 , overrideSDK
34 , pam
35 , pcre2
36 , postgresql
37 , bison
38 , re2c
39 , readline
40 , rsync
41 , sqlite
42 , unixODBC
43 , uwimap
44 , valgrind
45 , zlib
46 , fetchpatch
49 lib.makeScope pkgs.newScope (self: with self; {
50   buildPecl = callPackage ../build-support/php/build-pecl.nix {
51     php = php.unwrapped;
52   };
54   composerHooks = callPackages ../build-support/php/hooks { };
56   mkComposerRepository = callPackage ../build-support/php/build-composer-repository.nix { };
57   buildComposerProject = callPackage ../build-support/php/build-composer-project.nix { };
59   # Wrap mkDerivation to prepend pname with "php-" to make names consistent
60   # with how buildPecl does it and make the file easier to overview.
61   mkDerivation = origArgs:
62     let
63       args = lib.fix (lib.extends
64         (_: previousAttrs: {
65           pname = "php-${previousAttrs.pname}";
66           passthru = (previousAttrs.passthru or { }) // {
67             updateScript = nix-update-script { };
68           };
69           meta = (previousAttrs.meta or { }) // {
70             mainProgram = previousAttrs.meta.mainProgram or previousAttrs.pname;
71           };
72         })
73         (if lib.isFunction origArgs then origArgs else (_: origArgs))
74       );
75     in
76     pkgs.stdenv.mkDerivation args;
78   # Function to build an extension which is shipped as part of the php
79   # source, based on the php version.
80   #
81   # Name passed is the name of the extension and is automatically used
82   # to add the configureFlag "--enable-${name}", which can be overridden.
83   #
84   # Build inputs is used for extra deps that may be needed. And zendExtension
85   # will mark the extension as a zend extension or not.
86   mkExtension = lib.makeOverridable
87     ({ name
88      , configureFlags ? [ "--enable-${extName}" ]
89      , internalDeps ? [ ]
90      , postPhpize ? ""
91      , buildInputs ? [ ]
92      , zendExtension ? false
93      , doCheck ? true
94      , extName ? name
95      , ...
96      }@args: stdenv.mkDerivation ((builtins.removeAttrs args [ "name" ]) // {
97       pname = "php-${name}";
98       extensionName = extName;
100       outputs = [ "out" "dev" ];
102       inherit (php.unwrapped) version src;
104       enableParallelBuilding = true;
106       nativeBuildInputs = [
107         php.unwrapped
108         autoconf
109         pkg-config
110         re2c
111         bison
112       ];
114       inherit configureFlags internalDeps buildInputs zendExtension doCheck;
116       preConfigurePhases = [
117         "genfiles"
118         "cdToExtensionRootPhase"
119       ];
121       genfiles = ''
122         if [ -f "scripts/dev/genfiles" ]; then
123           ./scripts/dev/genfiles
124         fi
125       '';
127       cdToExtensionRootPhase = ''
128         # Go to extension source root.
129         cd "ext/${extName}"
130       '';
132       preConfigure = ''
133         nullglobRestore=$(shopt -p nullglob)
134         shopt -u nullglob   # To make ?-globbing work
136         # Some extensions have a config0.m4 or config9.m4
137         if [ -f config?.m4 ]; then
138           mv config?.m4 config.m4
139         fi
141         $nullglobRestore
143         phpize
144         ${postPhpize}
146         ${lib.concatMapStringsSep
147           "\n"
148           (dep: "mkdir -p ext; ln -s ${dep.dev}/include ext/${dep.extensionName}")
149           internalDeps
150         }
151       '';
153       checkPhase = ''
154         runHook preCheck
156         NO_INTERACTION=yes SKIP_PERF_SENSITIVE=yes make test
157         runHook postCheck
158       '';
160       installPhase = ''
161         runHook preInstall
163         mkdir -p $out/lib/php/extensions
164         cp modules/${extName}.so $out/lib/php/extensions/${extName}.so
165         mkdir -p $dev/include
166         ${rsync}/bin/rsync -r --filter="+ */" \
167                               --filter="+ *.h" \
168                               --filter="- *" \
169                               --prune-empty-dirs \
170                               . $dev/include/
172         runHook postInstall
173       '';
175       meta = {
176         description = "PHP upstream extension: ${name}";
177         inherit (php.meta) maintainers homepage license;
178       };
179     }));
181   php = phpPackage;
183   # This is a set of interactive tools based on PHP.
184   tools = {
185     box = callPackage ../development/php-packages/box { };
187     castor = callPackage ../development/php-packages/castor { };
189     composer = callPackage ../development/php-packages/composer { };
191     deployer = callPackage ../development/php-packages/deployer { };
193     grumphp = callPackage ../development/php-packages/grumphp { };
195     phan = callPackage ../development/php-packages/phan { };
197     phing = callPackage ../development/php-packages/phing { };
199     phive = callPackage ../development/php-packages/phive { };
201     php-cs-fixer = callPackage ../development/php-packages/php-cs-fixer { };
203     php-parallel-lint = callPackage ../development/php-packages/php-parallel-lint { };
205     phpcbf = callPackage ../development/php-packages/phpcbf { };
207     phpcs = callPackage ../development/php-packages/phpcs { };
209     phpmd = callPackage ../development/php-packages/phpmd { };
211     phpstan = callPackage ../development/php-packages/phpstan { };
213     psalm = callPackage ../development/php-packages/psalm { };
215     psysh = callPackage ../development/php-packages/psysh { };
216   };
220   # This is a set of PHP extensions meant to be used in php.buildEnv
221   # or php.withExtensions to extend the functionality of the PHP
222   # interpreter.
223   # The extensions attributes is composed of three sections:
224   # 1. The contrib conditional extensions, which are only available on specific PHP versions
225   # 2. The contrib extensions available
226   # 3. The core extensions
227   extensions =
228   # Contrib conditional extensions
229    lib.optionalAttrs (!(lib.versionAtLeast php.version "8.3")) {
230     blackfire = callPackage ../development/tools/misc/blackfire/php-probe.nix { inherit php; };
231   } //
232   # Contrib extensions
233   {
234     amqp = callPackage ../development/php-packages/amqp { };
236     apcu = callPackage ../development/php-packages/apcu { };
238     ast = callPackage ../development/php-packages/ast { };
240     couchbase = callPackage ../development/php-packages/couchbase { };
242     datadog_trace = callPackage ../development/php-packages/datadog_trace {
243       buildPecl = buildPecl.override {
244         stdenv = if stdenv.isDarwin then overrideSDK stdenv "11.0" else stdenv;
245       };
246       inherit (pkgs) darwin;
247     };
249     ds = callPackage ../development/php-packages/ds { };
251     event = callPackage ../development/php-packages/event { };
253     gnupg = callPackage ../development/php-packages/gnupg { };
255     grpc = callPackage ../development/php-packages/grpc { };
257     igbinary = callPackage ../development/php-packages/igbinary { };
259     imagick = callPackage ../development/php-packages/imagick { };
261     inotify = callPackage ../development/php-packages/inotify { };
263     mailparse = callPackage ../development/php-packages/mailparse { };
265     maxminddb = callPackage ../development/php-packages/maxminddb { };
267     memcache = callPackage ../development/php-packages/memcache { };
269     memcached = callPackage ../development/php-packages/memcached { };
271     meminfo = callPackage ../development/php-packages/meminfo { };
273     memprof = callPackage ../development/php-packages/memprof { };
275     mongodb = callPackage ../development/php-packages/mongodb {
276       inherit (pkgs) darwin;
277     };
279     msgpack = callPackage ../development/php-packages/msgpack { };
281     oci8 = callPackage ../development/php-packages/oci8 { };
283     opentelemetry = callPackage ../development/php-packages/opentelemetry { };
285     openswoole = callPackage ../development/php-packages/openswoole { };
287     pdlib = callPackage ../development/php-packages/pdlib { };
289     pcov = callPackage ../development/php-packages/pcov { };
291     pdo_oci = buildPecl rec {
292       inherit (php.unwrapped) src version;
294       pname = "pdo_oci";
295       sourceRoot = "php-${version}/ext/pdo_oci";
297       buildInputs = [ pkgs.oracle-instantclient ];
298       configureFlags = [ "--with-pdo-oci=instantclient,${pkgs.oracle-instantclient.lib}/lib" ];
300       internalDeps = [ php.extensions.pdo ];
302       postPatch = ''
303         sed -i -e 's|OCISDKMANINC=`.*$|OCISDKMANINC="${pkgs.oracle-instantclient.dev}/include"|' config.m4
304       '';
306       meta.maintainers = lib.teams.php.members;
307     };
309     pdo_sqlsrv = callPackage ../development/php-packages/pdo_sqlsrv { };
311     phalcon = callPackage ../development/php-packages/phalcon { };
313     php-spx = callPackage ../development/php-packages/php-spx { };
315     pinba = callPackage ../development/php-packages/pinba { };
317     protobuf = callPackage ../development/php-packages/protobuf { };
319     rdkafka = callPackage ../development/php-packages/rdkafka { };
321     redis = callPackage ../development/php-packages/redis { };
323     relay = callPackage ../development/php-packages/relay { inherit php; };
325     rrd = callPackage ../development/php-packages/rrd { };
327     smbclient = callPackage ../development/php-packages/smbclient { };
329     snuffleupagus = callPackage ../development/php-packages/snuffleupagus {
330       inherit (pkgs) darwin;
331     };
333     sqlsrv = callPackage ../development/php-packages/sqlsrv { };
335     ssh2 = callPackage ../development/php-packages/ssh2 { };
337     swoole = callPackage ../development/php-packages/swoole { };
339     uv = callPackage ../development/php-packages/uv { };
341     vld = callPackage ../development/php-packages/vld { };
343     xdebug = callPackage ../development/php-packages/xdebug { };
345     yaml = callPackage ../development/php-packages/yaml { };
346   } // (
347     # Core extensions
348     let
349       # This list contains build instructions for different modules that one may
350       # want to build.
351       #
352       # These will be passed as arguments to mkExtension above.
353       extensionData = [
354         { name = "bcmath"; }
355         { name = "bz2"; buildInputs = [ bzip2 ]; configureFlags = [ "--with-bz2=${bzip2.dev}" ]; }
356         { name = "calendar"; }
357         { name = "ctype"; }
358         {
359           name = "curl";
360           buildInputs = [ curl ];
361           configureFlags = [ "--with-curl=${curl.dev}" ];
362           doCheck = false;
363         }
364         { name = "dba"; }
365         {
366           name = "dom";
367           buildInputs = [ libxml2 ];
368           configureFlags = [
369             "--enable-dom"
370           ];
371         }
372         {
373           name = "enchant";
374           buildInputs = [ enchant2 ];
375           configureFlags = [ "--with-enchant" ];
376           doCheck = false;
377         }
378         { name = "exif"; doCheck = false; }
379         { name = "ffi"; buildInputs = [ libffi ]; }
380         {
381           name = "fileinfo";
382           buildInputs = [ pcre2 ];
383         }
384         { name = "filter"; buildInputs = [ pcre2 ]; }
385         { name = "ftp"; buildInputs = [ openssl ]; }
386         {
387           name = "gd";
388           buildInputs = [ zlib gd ];
389           configureFlags = [
390             "--enable-gd"
391             "--with-external-gd=${gd.dev}"
392             "--enable-gd-jis-conv"
393           ];
394           doCheck = false;
395         }
396         {
397           name = "gettext";
398           buildInputs = [ gettext ];
399           postPhpize = ''substituteInPlace configure --replace 'as_fn_error $? "Cannot locate header file libintl.h" "$LINENO" 5' ':' '';
400           configureFlags = [ "--with-gettext=${gettext}" ];
401         }
402         {
403           name = "gmp";
404           buildInputs = [ gmp ];
405           configureFlags = [ "--with-gmp=${gmp.dev}" ];
406         }
407         {
408           name = "iconv";
409           configureFlags = [
410             "--with-iconv${lib.optionalString stdenv.isDarwin "=${libiconv}"}"
411           ];
412           doCheck = false;
413         }
414         {
415           name = "imap";
416           buildInputs = [ uwimap openssl pam pcre2 libkrb5 ];
417           configureFlags = [ "--with-imap=${uwimap}" "--with-imap-ssl" "--with-kerberos" ];
418         }
419         {
420           name = "intl";
421           buildInputs = [ icu64 ];
422         }
423         {
424           name = "ldap";
425           buildInputs = [ openldap cyrus_sasl ];
426           configureFlags = [
427             "--with-ldap"
428             "LDAP_DIR=${openldap.dev}"
429             "LDAP_INCDIR=${openldap.dev}/include"
430             "LDAP_LIBDIR=${openldap.out}/lib"
431           ] ++ lib.optionals stdenv.isLinux [
432             "--with-ldap-sasl=${cyrus_sasl.dev}"
433           ];
434           doCheck = false;
435         }
436         {
437           name = "mbstring";
438           buildInputs = [ oniguruma pcre2 ];
439           doCheck = false;
440         }
441         {
442           name = "mysqli";
443           internalDeps = [ php.extensions.mysqlnd ];
444           configureFlags = [ "--with-mysqli=mysqlnd" "--with-mysql-sock=/run/mysqld/mysqld.sock" ];
445           doCheck = false;
446         }
447         {
448           name = "mysqlnd";
449           buildInputs = [ zlib openssl ];
450           # The configure script doesn't correctly add library link
451           # flags, so we add them to the variable used by the Makefile
452           # when linking.
453           MYSQLND_SHARED_LIBADD = "-lssl -lcrypto";
454           # The configure script builds a config.h which is never
455           # included. Let's include it in the main header file
456           # included by all .c-files.
457           patches = [
458             (pkgs.writeText "mysqlnd_config.patch" ''
459               --- a/ext/mysqlnd/mysqlnd.h
460               +++ b/ext/mysqlnd/mysqlnd.h
461               @@ -1,3 +1,6 @@
462               +#ifdef HAVE_CONFIG_H
463               +#include "config.h"
464               +#endif
465                /*
466                  +----------------------------------------------------------------------+
467                  | Copyright (c) The PHP Group                                          |
468             '')
469           ];
470         }
471         {
472           name = "opcache";
473           buildInputs = [ pcre2 ] ++
474             lib.optional
475               (!stdenv.isDarwin && lib.meta.availableOn stdenv.hostPlatform valgrind)
476               valgrind.dev;
477           zendExtension = true;
478           postPatch = lib.optionalString stdenv.isDarwin ''
479             # Tests are flaky on darwin
480             rm ext/opcache/tests/blacklist.phpt
481             rm ext/opcache/tests/bug66338.phpt
482             rm ext/opcache/tests/bug78106.phpt
483             rm ext/opcache/tests/issue0115.phpt
484             rm ext/opcache/tests/issue0149.phpt
485             rm ext/opcache/tests/revalidate_path_01.phpt
486           '';
487           # Tests launch the builtin webserver.
488           __darwinAllowLocalNetworking = true;
489         }
490         {
491           name = "openssl";
492           buildInputs = [ openssl ];
493           configureFlags = [ "--with-openssl" ];
494           doCheck = false;
495         }
496         # This provides a legacy OpenSSL PHP extension
497         # For situations where OpenSSL 3 do not support a set of features
498         # without a specific openssl.cnf file
499         {
500           name = "openssl-legacy";
501           extName = "openssl";
502           buildInputs = [ openssl_1_1 ];
503           configureFlags = [ "--with-openssl" ];
504           doCheck = false;
505         }
506         { name = "pcntl"; }
507         { name = "pdo"; doCheck = false; }
508         {
509           name = "pdo_dblib";
510           internalDeps = [ php.extensions.pdo ];
511           configureFlags = [ "--with-pdo-dblib=${freetds}" ];
512           # Doesn't seem to work on darwin.
513           enable = (!stdenv.isDarwin);
514           doCheck = false;
515         }
516         {
517           name = "pdo_mysql";
518           internalDeps = with php.extensions; [ pdo mysqlnd ];
519           configureFlags = [ "--with-pdo-mysql=mysqlnd" "PHP_MYSQL_SOCK=/run/mysqld/mysqld.sock" ];
520           doCheck = false;
521         }
522         {
523           name = "pdo_odbc";
524           internalDeps = [ php.extensions.pdo ];
525           configureFlags = [ "--with-pdo-odbc=unixODBC,${unixODBC}" ];
526           doCheck = false;
527         }
528         {
529           name = "pdo_pgsql";
530           internalDeps = [ php.extensions.pdo ];
531           configureFlags = [ "--with-pdo-pgsql=${postgresql}" ];
532           doCheck = false;
533         }
534         {
535           name = "pdo_sqlite";
536           internalDeps = [ php.extensions.pdo ];
537           buildInputs = [ sqlite ];
538           configureFlags = [ "--with-pdo-sqlite=${sqlite.dev}" ];
539           doCheck = false;
540         }
541         {
542           name = "pgsql";
543           buildInputs = [ pcre2 ];
544           configureFlags = [ "--with-pgsql=${postgresql}" ];
545           doCheck = false;
546         }
547         { name = "posix"; doCheck = false; }
548         { name = "pspell"; configureFlags = [ "--with-pspell=${aspell}" ]; }
549         {
550           name = "readline";
551           buildInputs = [
552             readline
553           ];
554           configureFlags = [
555             "--with-readline=${readline.dev}"
556           ];
557           postPatch = ''
558             # Fix `--with-readline` option not being available.
559             # `PHP_ALWAYS_SHARED` generated by phpize enables all options
560             # without the possibility to override them. But when `--with-libedit`
561             # is enabled, `--with-readline` is not registered.
562             echo '
563             AC_DEFUN([PHP_ALWAYS_SHARED],[
564               test "[$]$1" != "no" && ext_shared=yes
565             ])dnl
566             ' | cat - ext/readline/config.m4 > ext/readline/config.m4.tmp
567             mv ext/readline/config.m4{.tmp,}
568           '';
569           doCheck = false;
570         }
571         { name = "session";
572           doCheck = false;
573         }
574         { name = "shmop"; }
575         {
576           name = "simplexml";
577           buildInputs = [ libxml2 pcre2 ];
578           configureFlags = [
579             "--enable-simplexml"
580           ];
581         }
582         {
583           name = "snmp";
584           buildInputs = [ net-snmp openssl ];
585           configureFlags = [ "--with-snmp" ];
586           # net-snmp doesn't build on darwin.
587           enable = (!stdenv.isDarwin);
588           doCheck = false;
589         }
590         {
591           name = "soap";
592           buildInputs = [ libxml2 ];
593           configureFlags = [
594             "--enable-soap"
595           ];
596           doCheck = false;
597         }
598         {
599           name = "sockets";
600           doCheck = false;
601         }
602         { name = "sodium"; buildInputs = [ libsodium ]; }
603         { name = "sqlite3"; buildInputs = [ sqlite ]; }
604         { name = "sysvmsg"; }
605         { name = "sysvsem"; }
606         { name = "sysvshm"; }
607         { name = "tidy"; configureFlags = [ "--with-tidy=${html-tidy}" ]; doCheck = false; }
608         {
609           name = "tokenizer";
610           patches = [ ../development/interpreters/php/fix-tokenizer-php81.patch ];
611         }
612         {
613           name = "xml";
614           buildInputs = [ libxml2 ];
615           configureFlags = [
616             "--enable-xml"
617           ];
618           doCheck = false;
619         }
620         {
621           name = "xmlreader";
622           buildInputs = [ libxml2 ];
623           internalDeps = [ php.extensions.dom ];
624           env.NIX_CFLAGS_COMPILE = toString [ "-I../.." "-DHAVE_DOM" ];
625           doCheck = false;
626           configureFlags = [
627             "--enable-xmlreader"
628           ];
629         }
630         {
631           name = "xmlwriter";
632           buildInputs = [ libxml2 ];
633           configureFlags = [
634             "--enable-xmlwriter"
635           ];
636         }
637         {
638           name = "xsl";
639           buildInputs = [ libxslt libxml2 ];
640           doCheck = false;
641           configureFlags = [ "--with-xsl=${libxslt.dev}" ];
642         }
643         { name = "zend_test"; }
644         {
645           name = "zip";
646           buildInputs = [ libzip pcre2 ];
647           configureFlags = [
648             "--with-zip"
649           ];
650           doCheck = false;
651         }
652         {
653           name = "zlib";
654           buildInputs = [ zlib ];
655           configureFlags = [
656             "--with-zlib"
657           ];
658         }
659       ];
661       # Convert the list of attrs:
662       # [ { name = <name>; ... } ... ]
663       # to a list of
664       # [ { name = <name>; value = <extension drv>; } ... ]
665       #
666       # which we later use listToAttrs to make all attrs available by name.
667       #
668       # Also filter out extensions based on the enable property.
669       namedExtensions = builtins.map
670         (drv: {
671           name = drv.name;
672           value = mkExtension drv;
673         })
674         (builtins.filter (i: i.enable or true) extensionData);
676       # Produce the final attribute set of all extensions defined.
677     in
678     builtins.listToAttrs namedExtensions
679   );