about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/interpreters/php/generic.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/development/interpreters/php/generic.nix')
-rw-r--r--nixpkgs/pkgs/development/interpreters/php/generic.nix345
1 files changed, 345 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/interpreters/php/generic.nix b/nixpkgs/pkgs/development/interpreters/php/generic.nix
new file mode 100644
index 000000000000..cee1e833f9a6
--- /dev/null
+++ b/nixpkgs/pkgs/development/interpreters/php/generic.nix
@@ -0,0 +1,345 @@
+# We have tests for PCRE and PHP-FPM in nixos/tests/php/ or
+# both in the same attribute named nixosTests.php
+
+let
+  generic =
+    { callPackage
+    , lib
+    , stdenv
+    , nixosTests
+    , tests
+    , fetchurl
+    , makeBinaryWrapper
+    , symlinkJoin
+    , writeText
+    , autoconf
+    , automake
+    , bison
+    , flex
+    , libtool
+    , pkg-config
+    , re2c
+    , apacheHttpd
+    , libargon2
+    , libxml2
+    , pcre2
+    , systemd
+    , system-sendmail
+    , valgrind
+    , xcbuild
+    , writeShellScript
+    , common-updater-scripts
+    , curl
+    , jq
+
+    , version
+    , hash
+    , extraPatches ? [ ]
+    , packageOverrides ? (final: prev: { })
+    , phpAttrsOverrides ? (attrs: { })
+
+      # Sapi flags
+    , cgiSupport ? true
+    , cliSupport ? true
+    , fpmSupport ? true
+    , pearSupport ? true
+    , pharSupport ? true
+    , phpdbgSupport ? true
+
+      # Misc flags
+    , apxs2Support ? false
+    , argon2Support ? true
+    , cgotoSupport ? false
+    , embedSupport ? false
+    , ipv6Support ? true
+    , systemdSupport ? lib.meta.availableOn stdenv.hostPlatform systemd
+    , valgrindSupport ? !stdenv.isDarwin && lib.meta.availableOn stdenv.hostPlatform valgrind
+    , ztsSupport ? apxs2Support
+    }@args:
+
+    let
+      # Compose two functions of the type expected by 'overrideAttrs'
+      # into one where changes made in the first are available to the second.
+      composeOverrides =
+        f: g: attrs:
+        let
+          fApplied = f attrs;
+          attrs' = attrs // fApplied;
+        in
+        fApplied // g attrs';
+
+      # buildEnv wraps php to provide additional extensions and
+      # configuration. Its usage is documented in
+      # doc/languages-frameworks/php.section.md.
+      #
+      # Create a buildEnv with earlier overridden values and
+      # extensions functions in its closure. This is necessary for
+      # consecutive calls to buildEnv and overrides to work as
+      # expected.
+      mkBuildEnv = prevArgs: prevExtensionFunctions: lib.makeOverridable (
+        { extensions ? ({ enabled, ... }: enabled), extraConfig ? "", ... }@innerArgs:
+        let
+          allArgs = args // prevArgs // innerArgs;
+          filteredArgs = builtins.removeAttrs allArgs [ "extensions" "extraConfig" ];
+          php = generic filteredArgs;
+
+          php-packages = (callPackage ../../../top-level/php-packages.nix {
+            phpPackage = phpWithExtensions;
+          }).overrideScope packageOverrides;
+
+          allExtensionFunctions = prevExtensionFunctions ++ [ extensions ];
+          enabledExtensions =
+            builtins.foldl'
+              (enabled: f:
+                f { inherit enabled; all = php-packages.extensions; })
+              [ ]
+              allExtensionFunctions;
+
+          getExtName = ext: ext.extensionName;
+
+          # Recursively get a list of all internal dependencies
+          # for a list of extensions.
+          getDepsRecursively = extensions:
+            let
+              deps = lib.concatMap
+                (ext: (ext.internalDeps or [ ]) ++ (ext.peclDeps or [ ]))
+                extensions;
+            in
+            if ! (deps == [ ]) then
+              deps ++ (getDepsRecursively deps)
+            else
+              deps;
+
+          # Generate extension load configuration snippets from the
+          # extension parameter. This is an attrset suitable for use
+          # with textClosureList, which is used to put the strings in
+          # the right order - if a plugin which is dependent on
+          # another plugin is placed before its dependency, it will
+          # fail to load.
+          extensionTexts =
+            lib.listToAttrs
+              (map
+                (ext:
+                  let
+                    extName = getExtName ext;
+                    phpDeps = (ext.internalDeps or [ ]) ++ (ext.peclDeps or [ ]);
+                    type = "${lib.optionalString (ext.zendExtension or false) "zend_"}extension";
+                  in
+                  lib.nameValuePair extName {
+                    text = "${type}=${ext}/lib/php/extensions/${extName}.so";
+                    deps = map getExtName phpDeps;
+                  })
+                (enabledExtensions ++ (getDepsRecursively enabledExtensions)));
+
+          extNames = map getExtName enabledExtensions;
+          extraInit = writeText "php-extra-init-${version}.ini" ''
+            ${lib.concatStringsSep "\n"
+              (lib.textClosureList extensionTexts extNames)}
+            ${extraConfig}
+          '';
+
+          phpWithExtensions = symlinkJoin {
+            name = "php-with-extensions-${version}";
+            inherit (php) version;
+            nativeBuildInputs = [ makeBinaryWrapper ];
+            passthru = php.passthru // {
+              buildEnv = mkBuildEnv allArgs allExtensionFunctions;
+              withExtensions = mkWithExtensions allArgs allExtensionFunctions;
+              overrideAttrs =
+                f:
+                let
+                  newPhpAttrsOverrides = composeOverrides (filteredArgs.phpAttrsOverrides or (attrs: { })) f;
+                  php = generic (filteredArgs // { phpAttrsOverrides = newPhpAttrsOverrides; });
+                in
+                php.buildEnv { inherit extensions extraConfig; };
+              phpIni = "${phpWithExtensions}/lib/php.ini";
+              unwrapped = php;
+              # Select the right php tests for the php version
+              tests = {
+                nixos = lib.recurseIntoAttrs nixosTests."php${lib.strings.replaceStrings [ "." ] [ "" ] (lib.versions.majorMinor php.version)}";
+                package = tests.php;
+              };
+              inherit (php-packages) extensions buildPecl mkExtension;
+              packages = php-packages.tools;
+              meta = php.meta // {
+                outputsToInstall = [ "out" ];
+              };
+            };
+            paths = [ php ];
+            postBuild = ''
+              ln -s ${extraInit} $out/lib/php.ini
+
+              if test -e $out/bin/php; then
+                wrapProgram $out/bin/php --set-default PHP_INI_SCAN_DIR $out/lib
+              fi
+
+              if test -e $out/bin/php-fpm; then
+                wrapProgram $out/bin/php-fpm --set-default PHP_INI_SCAN_DIR $out/lib
+              fi
+
+              if test -e $out/bin/phpdbg; then
+                wrapProgram $out/bin/phpdbg --set-default PHP_INI_SCAN_DIR $out/lib
+              fi
+
+              if test -e $out/bin/php-cgi; then
+                wrapProgram $out/bin/php-cgi --set-default PHP_INI_SCAN_DIR $out/lib
+              fi
+            '';
+          };
+        in
+        phpWithExtensions
+      );
+
+      mkWithExtensions = prevArgs: prevExtensionFunctions: extensions:
+        mkBuildEnv prevArgs prevExtensionFunctions { inherit extensions; };
+    in
+    stdenv.mkDerivation (
+      let
+        attrs = {
+          pname = "php";
+
+          inherit version;
+
+          enableParallelBuilding = true;
+
+          nativeBuildInputs = [ autoconf automake bison flex libtool pkg-config re2c ]
+            ++ lib.optional stdenv.isDarwin xcbuild;
+
+          buildInputs =
+            # PCRE extension
+            [ pcre2 ]
+
+            # Enable sapis
+            ++ lib.optionals pearSupport [ libxml2.dev ]
+
+            # Misc deps
+            ++ lib.optional apxs2Support apacheHttpd
+            ++ lib.optional argon2Support libargon2
+            ++ lib.optional systemdSupport systemd
+            ++ lib.optional valgrindSupport valgrind
+          ;
+
+          CXXFLAGS = lib.optionalString stdenv.cc.isClang "-std=c++11";
+          SKIP_PERF_SENSITIVE = 1;
+
+          configureFlags =
+            # Disable all extensions
+            [ "--disable-all" ]
+
+            # PCRE
+            ++ [ "--with-external-pcre=${pcre2.dev}" ]
+
+
+            # Enable sapis
+            ++ lib.optional (!cgiSupport) "--disable-cgi"
+            ++ lib.optional (!cliSupport) "--disable-cli"
+            ++ lib.optional fpmSupport "--enable-fpm"
+            ++ lib.optionals pearSupport [ "--with-pear" "--enable-xml" "--with-libxml" ]
+            ++ lib.optional pharSupport "--enable-phar"
+            ++ lib.optional (!phpdbgSupport) "--disable-phpdbg"
+
+
+            # Misc flags
+            ++ lib.optional apxs2Support "--with-apxs2=${apacheHttpd.dev}/bin/apxs"
+            ++ lib.optional argon2Support "--with-password-argon2=${libargon2}"
+            ++ lib.optional cgotoSupport "--enable-re2c-cgoto"
+            ++ lib.optional embedSupport "--enable-embed"
+            ++ lib.optional (!ipv6Support) "--disable-ipv6"
+            ++ lib.optional systemdSupport "--with-fpm-systemd"
+            ++ lib.optional valgrindSupport "--with-valgrind=${valgrind.dev}"
+            ++ lib.optional ztsSupport "--enable-zts"
+
+
+            # Sendmail
+            ++ [ "PROG_SENDMAIL=${system-sendmail}/bin/sendmail" ]
+          ;
+
+          hardeningDisable = [ "bindnow" ];
+
+          preConfigure =
+            # Don't record the configure flags since this causes unnecessary
+            # runtime dependencies
+            ''
+              for i in main/build-defs.h.in scripts/php-config.in; do
+                substituteInPlace $i \
+                  --replace '@CONFIGURE_COMMAND@' '(omitted)' \
+                  --replace '@CONFIGURE_OPTIONS@' "" \
+                  --replace '@PHP_LDFLAGS@' ""
+              done
+
+              export EXTENSION_DIR=$out/lib/php/extensions
+
+              ./buildconf --copy --force
+
+              if [ -f "scripts/dev/genfiles" ]; then
+                ./scripts/dev/genfiles
+              fi
+            '' + lib.optionalString stdenv.isDarwin ''
+              substituteInPlace configure --replace "-lstdc++" "-lc++"
+            '';
+
+          postInstall = ''
+            test -d $out/etc || mkdir $out/etc
+            cp php.ini-production $out/etc/php.ini
+          '';
+
+          postFixup = ''
+            mkdir -p $dev/bin $dev/share/man/man1
+            mv $out/bin/phpize $out/bin/php-config $dev/bin/
+            mv $out/share/man/man1/phpize.1.gz \
+               $out/share/man/man1/php-config.1.gz \
+               $dev/share/man/man1/
+          '';
+
+          src = fetchurl {
+            url = "https://www.php.net/distributions/php-${version}.tar.bz2";
+            inherit hash;
+          };
+
+          patches = [ ./fix-paths-php7.patch ] ++ extraPatches;
+
+          separateDebugInfo = true;
+
+          outputs = [ "out" "dev" ];
+
+          passthru = {
+            updateScript =
+              let
+                script = writeShellScript "php${lib.versions.major version}${lib.versions.minor version}-update-script" ''
+                  set -o errexit
+                  PATH=${lib.makeBinPath [ common-updater-scripts curl jq ]}
+                  new_version=$(curl --silent "https://www.php.net/releases/active" | jq --raw-output '."${lib.versions.major version}"."${lib.versions.majorMinor version}".version')
+                  update-source-version "$UPDATE_NIX_ATTR_PATH.unwrapped" "$new_version" "--file=$1"
+                '';
+              in [
+                script
+                # Passed as an argument so that update.nix can ensure it does not become a store path.
+                (./. + "/${lib.versions.majorMinor version}.nix")
+              ];
+            buildEnv = mkBuildEnv { } [ ];
+            withExtensions = mkWithExtensions { } [ ];
+            overrideAttrs =
+              f:
+              let
+                newPhpAttrsOverrides = composeOverrides phpAttrsOverrides f;
+                php = generic (args // { phpAttrsOverrides = newPhpAttrsOverrides; });
+              in
+              php;
+            inherit ztsSupport;
+          };
+
+          meta = with lib; {
+            description = "An HTML-embedded scripting language";
+            homepage = "https://www.php.net/";
+            license = licenses.php301;
+            mainProgram = "php";
+            maintainers = teams.php.members;
+            platforms = platforms.all;
+            outputsToInstall = [ "out" "dev" ];
+          };
+        };
+      in
+      attrs // phpAttrsOverrides attrs
+    );
+in
+generic