Building “decimal” PHP extension (PECL)

Hello, everyone. I’m trying to get a legacy system’s development setup away from containers and working under Nix. This system uses PHP 7.1, but the closest I’ve been able to get working is 7.4. I’m using Devenv, although it’s not prepared for PHP stuff this old, so I’m having to build extensions myself and stuff. I have to say, I’m not an expert in either PHP or Nix, so bear with me…

Most of the extensions were already available, but some I couldn’t find. So I had luck building mcrypt using buildPecl, like so:

php-mcrypt = pkgs-php.php74.buildPecl {
  pname = "mcrypt";
  version = "1.0.7";
  sha256 = "Euovu/Li7755ChISH3e/CWyLhM74HQIWvsANVuW63vQ=";
  buildInputs = [
    pkgs.libmcrypt
    pkgs.mcrypt
    pkgs.gawk
    pkgs.pkg-config
  ];
  configureFlags = ["--with-mcrypt=${pkgs.libmcrypt}"];
};

Where pkgs-php is an old version of Nixpkgs that has PHP 7.4, as an input. I’m sure a lot of those buildInputs aren’t even needed.

I got stuck, however, getting the decimal extension to work. This is how far I got:

php-decimal = pkgs-php.php74.buildPecl {
  pname = "decimal";
  version = "1.5.0";
  sha256 = "it8w8hOLYwtCZoDYhaP5k5TD/pQLtj37K2lSESF80ok=";
  buildInputs = [
    pkgs.mpdecimal
  ];
  configureFlags = ["--with-libmpdec-path=${pkgs.mpdecimal}"];
};

Figuring out the flag to specify mpdecimal took me way, way too long. But now I’m getting this error about some php_json.h file.

       > build flags: SHELL=/nix/store/8f6h1lp9i8s0pd31n220k9zh1ksb13ln-bash-5.1-p16/bin/bash EXTENSION_DIR=\$\(out\)/lib/php/extensions
       > /nix/store/8f6h1lp9i8s0pd31n220k9zh1ksb13ln-bash-5.1-p16/bin/bash /private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/libtool --mode=compile clang -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -I. -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0 -DPHP_ATOM_INC -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/include -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/main -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0 -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/main -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/TSRM -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/Zend -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/ext -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/php_decimal.c -o php_decimal.lo
       > mkdir .libs
       >  clang -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -I. -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0 -DPHP_ATOM_INC -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/include -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/main -I/private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0 -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/main -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/TSRM -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/Zend -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/ext -I/nix/store/6n4kzn2ai0d8wfx0vkld6x01wwr8lslx-php-7.4.29-dev/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/php_decimal.c  -fno-common -DPIC -o .libs/php_decimal.o
       > In file included from /private/tmp/nix-build-php-decimal-1.5.0.drv-0/decimal-1.5.0/php_decimal.c:27:
       > ./php_decimal.h:48:10: fatal error: 'ext/json/php_json.h' file not found
       > #include "ext/json/php_json.h"
       >          ^~~~~~~~~~~~~~~~~~~~~
       > 1 error generated.

My guess is that this version of PHP doesn’t include the JSON extension. I tried building with PHP 8.1 and sure enough it built, but now it isn’t compatible with the PHP 7.4 that I’m trying to use it on.

If it sounds like I don’t know that I’m doing, it’s because I don’t. Appreciate any guidance at all. :pray:

You can pass built-in PHP extensions to buildPecl using internalDeps attribute. See, for example:

Also devenv should be able to pick up old PHP versions from fossar/nix-phps:

2 Likes

Wow, it worked! Thank you @jtojnar, you saved me from I don’t wanna know how many days of scouring the internet for clues. :sob:

Regarding Devenv and directly specifying the PHP version, I tried but I believe that the problem was that in order to add the custom-built PECLs I had to drop down to specifying the PHP package myself and use the buildEnv function it provides. But I’ll try getting 7.1 directly from that repo, it was actually something I had already planned.

Right, looks like customPhpPackage is not exposed so if you use version, you can only specify extensions packaged in Nixpkgs or nix-phps:

This would be a good reason for packaging decimal in Nixpkgs (it will then propagate to nix-phps on next update).

However, mcrypt is also not available, since it’s deprecated, so it’s not just decimal. Also, adding it to Nixpkgs now would not help with making it work for an older version of PHP!

We do have mcrypt (though only for PHP 5.6):

PECL version would not be accepted in Nixpkgs but would be welcome in nix-phps.

decimal should be fine to go to Nixpkgs. If it were to be packaged there, it would automatically become available in nix-phps after the next update for all compatible PHP versions. Since it is listed as PHP ≥ 7.0 on PECL, it should be fine.

Well, I guess I’m up for a PR then? Wish me luck. :sweat_smile:

1 Like

For posterity and the DuckDuckGo hits, I’ll write here the complete solution.

This is a Devenv proyect, so we have the devenv.yaml file, in which I added the fossar/nix-phps input:

# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
inputs:
  nixpkgs:
    url: github:cachix/devenv-nixpkgs/rolling
  phps:
    url: github:fossar/nix-phps
    inputs:
      nixpkgs:
        follows: nixpkgs

And here’s the devenv.nix file (only the relevant bits):

{
  pkgs,
  lib,
  config,
  inputs,
  ...
}: let
  phps = inputs.phps.packages."${pkgs.stdenv.system}";

  php-mcrypt = phps.php74.buildPecl {
    pname = "mcrypt";
    version = "1.0.7";
    sha256 = "Euovu/Li7755ChISH3e/CWyLhM74HQIWvsANVuW63vQ=";
    buildInputs = [pkgs.libmcrypt];
    configureFlags = ["--with-mcrypt=${pkgs.libmcrypt}"];
  };

  php-decimal = phps.php74.buildPecl {
    pname = "decimal";
    version = "1.5.0";
    sha256 = "it8w8hOLYwtCZoDYhaP5k5TD/pQLtj37K2lSESF80ok=";
    internalDeps = [phps.php74.extensions.json];
    buildInputs = [pkgs.mpdecimal];
    configureFlags = ["--with-libmpdec-path=${pkgs.mpdecimal}"];
  };
in {
  languages = {
    php = {
      enable = true;
      package = phps.php74.buildEnv {
        extensions = {
          enabled,
          all,
        }:
          enabled
          ++ [
            php-decimal
            php-mcrypt
          ];
      };
    };
  };
}
1 Like

Nixkpgs PR for decimal.