Unverified Commit b36ad2f5 authored by Pol Dellaiera's avatar Pol Dellaiera
Browse files

php: add new builder `buildComposerProject`

parent 27e3b694
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -257,7 +257,8 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
# PHP interpreter, packages, extensions, tests and documentation
/doc/languages-frameworks/php.section.md          @aanderse @drupol @etu @globin @ma27 @talyz
/nixos/tests/php                                  @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/build-pecl.nix                @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/php/build-pecl.nix            @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/php                                     @drupol @etu
/pkgs/development/interpreters/php       @jtojnar @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/development/php-packages                    @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/top-level/php-packages.nix         @jtojnar @aanderse @drupol @etu @globin @ma27 @talyz
+61 −0
Original line number Diff line number Diff line
{ stdenvNoCC, lib, writeTextDir, php, makeBinaryWrapper, fetchFromGitHub, fetchurl, composer-local-repo-plugin }:

let
  buildComposerProjectOverride = finalAttrs: previousAttrs:

    let
      phpDrv = finalAttrs.php or php;
      composer = finalAttrs.composer or phpDrv.packages.composer;
      composerLock = finalAttrs.composerLock or null;
    in
    {
      nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
        composer
        composer-local-repo-plugin
        phpDrv.composerHooks.composerInstallHook
      ];

      buildInputs = (previousAttrs.buildInputs or [ ]) ++ [
        phpDrv
      ];

      patches = previousAttrs.patches or [ ];
      strictDeps = previousAttrs.strictDeps or true;

      # Should we keep these empty phases?
      configurePhase = previousAttrs.configurePhase or ''
        runHook preConfigure

        runHook postConfigure
      '';

      buildPhase = previousAttrs.buildPhase or ''
        runHook preBuild

        runHook postBuild
      '';

      doCheck = previousAttrs.doCheck or true;
      checkPhase = previousAttrs.checkPhase or ''
        runHook preCheck

        runHook postCheck
      '';

      installPhase = previousAttrs.installPhase or ''
        runHook preInstall

        runHook postInstall
      '';

      composerRepository = phpDrv.mkComposerRepository {
        inherit composer composer-local-repo-plugin composerLock;
        inherit (finalAttrs) patches pname src vendorHash version;
      };

      meta = previousAttrs.meta or { } // {
        platforms = lib.platforms.all;
      };
    };
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerProjectOverride
+79 −0
Original line number Diff line number Diff line
{ stdenvNoCC, lib, writeTextDir, fetchFromGitHub, php, composer-local-repo-plugin }:

let
  mkComposerRepositoryOverride =
    /*
      We cannot destruct finalAttrs since the attrset below is used to construct it
      and Nix currently does not support lazy attribute names.
      {
      php ? null,
      composer ? null,
      composerLock ? "composer.lock",
      src,
      vendorHash,
      ...
      }@finalAttrs:
    */
    finalAttrs: previousAttrs:

    let
      phpDrv = finalAttrs.php or php;
      composer = finalAttrs.composer or phpDrv.packages.composer;
    in
    assert (lib.assertMsg (previousAttrs ? src) "mkComposerRepository expects src argument.");
    assert (lib.assertMsg (previousAttrs ? vendorHash) "mkComposerRepository expects vendorHash argument.");
    assert (lib.assertMsg (previousAttrs ? version) "mkComposerRepository expects version argument.");
    assert (lib.assertMsg (previousAttrs ? pname) "mkComposerRepository expects pname argument.");
    {
      name = "${previousAttrs.pname}-${previousAttrs.version}-composer-repository";

      # See https://github.com/NixOS/nix/issues/6660
      dontPatchShebangs = previousAttrs.dontPatchShebangs or true;

      nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [
        composer
        composer-local-repo-plugin
        phpDrv.composerHooks.composerRepositoryHook
      ];

      buildInputs = previousAttrs.buildInputs or [ ];

      strictDeps = previousAttrs.strictDeps or true;

      # Should we keep these empty phases?
      configurePhase = previousAttrs.configurePhase or ''
        runHook preConfigure

        runHook postConfigure
      '';

      buildPhase = previousAttrs.buildPhase or ''
        runHook preBuild

        runHook postBuild
      '';

      doCheck = previousAttrs.doCheck or true;
      checkPhase = previousAttrs.checkPhase or ''
        runHook preCheck

        runHook postCheck
      '';

      installPhase = previousAttrs.installPhase or ''
        runHook preInstall

        runHook postInstall
      '';

      COMPOSER_CACHE_DIR = "/dev/null";
      COMPOSER_MIRROR_PATH_REPOS = "1";
      COMPOSER_HTACCESS_PROTECT = "0";
      COMPOSER_DISABLE_NETWORK = "0";

      outputHashMode = "recursive";
      outputHashAlgo = if (finalAttrs ? vendorHash && finalAttrs.vendorHash != "") then null else "sha256";
      outputHash = finalAttrs.vendorHash or "";
    };
in
args: (stdenvNoCC.mkDerivation args).overrideAttrs mkComposerRepositoryOverride
+109 −0
Original line number Diff line number Diff line
declare composerHomeDir
declare composerRepository
declare version

preConfigureHooks+=(composerInstallConfigureHook)
preBuildHooks+=(composerInstallBuildHook)
preCheckHooks+=(composerInstallCheckHook)
preInstallHooks+=(composerInstallInstallHook)

composerInstallConfigureHook() {
    echo "Executing composerInstallConfigureHook"

    if [[ ! -e "${composerRepository}" ]]; then
        echo "No local composer repository found."
        exit 1
    fi

    if [[ -e "$composerLock" ]]; then
        cp $composerLock composer.lock
    fi

    if [[ ! -f "composer.lock" ]]; then
        echo "No composer.lock file found, consider adding one to your repository to ensure reproducible builds."

        if [[ -f "${composerRepository}/composer.lock" ]]; then
            cp ${composerRepository}/composer.lock composer.lock
        fi

        echo "Using an autogenerated composer.lock file."
    fi

    chmod +w composer.json composer.lock

    echo "Finished composerInstallConfigureHook"
}

composerInstallBuildHook() {
    echo "Executing composerInstallBuildHook"

    # Since this file cannot be generated in the composer-repository-hook.sh
    # because the file contains hardcoded nix store paths, we generate it here.
    composer-local-repo-plugin --no-ansi build-local-repo -p ${composerRepository} > packages.json

    # Remove all the repositories of type "composer"
    # from the composer.json file.
    jq -r -c 'del(try .repositories[] | select(.type == "composer"))' composer.json | sponge composer.json

    # Configure composer to disable packagist and avoid using the network.
    composer config repo.packagist false
    # Configure composer to use the local repository.
    composer config repo.composer composer file://$PWD/packages.json

    # Since the composer.json file has been modified in the previous step, the
    # composer.lock file needs to be updated.
    COMPOSER_DISABLE_NETWORK=1 \
    COMPOSER_ROOT_VERSION="${version}" \
    composer \
      --lock \
      --no-ansi \
      --no-install \
      --no-interaction \
      --no-plugins \
      --no-scripts \
      update

    echo "Finished composerInstallBuildHook"
}

composerInstallCheckHook() {
    echo "Executing composerInstallCheckHook"

    composer validate --no-ansi --no-interaction

    echo "Finished composerInstallCheckHook"
}

composerInstallInstallHook() {
    echo "Executing composerInstallInstallHook"

    # Finally, run `composer install` to install the dependencies and generate
    # the autoloader.
    # The COMPOSER_ROOT_VERSION environment variable is needed only for
    # vimeo/psalm.
    COMPOSER_CACHE_DIR=/dev/null \
    COMPOSER_DISABLE_NETWORK=1 \
    COMPOSER_ROOT_VERSION="${version}" \
    COMPOSER_MIRROR_PATH_REPOS="1" \
    composer \
      --no-ansi \
      --no-interaction \
      --no-scripts \
      --no-plugins \
      install

    # Remove packages.json, we don't need it in the store.
    rm packages.json

    # Copy the relevant files only in the store.
    mkdir -p $out/share/php/${pname}
    cp -r . $out/share/php/${pname}/

    # Create symlinks for the binaries.
    jq -r -c 'try .bin[]' composer.json | while read bin; do
        mkdir -p $out/share/php/${pname} $out/bin
        ln -s $out/share/php/${pname}/$bin $out/bin/$(basename $bin)
    done

    echo "Finished composerInstallInstallHook"
}
Loading