Unverified Commit 06a152f9 authored by Pol Dellaiera's avatar Pol Dellaiera Committed by GitHub
Browse files

build-support/go: support `finalAttrs` through `lib.extendMkDerivation` (#390220)

parents a73a7a65 0dd2d4fe
Loading
Loading
Loading
Loading
+384 −331
Original line number Diff line number Diff line
{ go, cacert, git, lib, stdenv }:

{ name ? "${args'.pname}-${args'.version}"
  # The source used to build the derivation.
, src
  # Native build inputs used for the derivation.
, nativeBuildInputs ? [ ]
, passthru ? { }
, patches ? [ ]
{
  go,
  cacert,
  gitMinimal,
  lib,
  stdenv,
}:

lib.extendMkDerivation {
  constructDrv = stdenv.mkDerivation;
  excludeDrvArgNames = [
    "overrideModAttrs"
    # Compatibility layer to the directly-specified CGO_ENABLED.
    # TODO(@ShamrockLee): Remove after Nixpkgs 25.05 branch-off
    "CGO_ENABLED"
  ];
  extendDrvArgs =
    finalAttrs:
    {
      nativeBuildInputs ? [ ], # Native build inputs used for the derivation.
      passthru ? { },
      patches ? [ ],

      # A function to override the `goModules` derivation.
, overrideModAttrs ? (finalAttrs: previousAttrs: { })
      overrideModAttrs ? (finalAttrs: previousAttrs: { }),

      # Directory to the `go.mod` and `go.sum` relative to the `src`.
, modRoot ? "./"
      modRoot ? "./",

      # The SRI hash of the vendored dependencies.
      # If `vendorHash` is `null`, no dependencies are fetched and
      # the build relies on the vendor folder within the source.
, vendorHash ? throw (
    if args'?vendorSha256 then
      vendorHash ? throw (
        if args ? vendorSha256 then
          "buildGoModule: Expect vendorHash instead of vendorSha256"
        else
          "buildGoModule: vendorHash is missing"
  )
      ),

      # Whether to delete the vendor folder supplied with the source.
, deleteVendor ? false
      deleteVendor ? false,

      # Whether to fetch (go mod download) and proxy the vendor directory.
      # This is useful if your code depends on c code and go mod tidy does not
      # include the needed sources to build or if any dependency has case-insensitive
      # conflicts which will produce platform dependant `vendorHash` checksums.
, proxyVendor ? false
      proxyVendor ? false,

      # We want parallel builds by default.
, enableParallelBuilding ? true
      enableParallelBuilding ? true,

      # Do not enable this without good reason
      # IE: programs coupled with the compiler.
, allowGoReference ? false
      allowGoReference ? false,

      # Meta data for the final derivation.
, meta ? { }
      meta ? { },

      # Go linker flags.
, ldflags ? [ ]
      ldflags ? [ ],
      # Go build flags.
, GOFLAGS ? [ ]

, ...
}@args':

let
  args = removeAttrs args' [
    "overrideModAttrs"
    # Compatibility layer to the directly-specified CGO_ENABLED.
    # TODO(@ShamrockLee): Remove after Nixpkgs 25.05 branch-off
    "CGO_ENABLED"
  ];
in
(stdenv.mkDerivation (finalAttrs:
  args
  // {

  inherit modRoot vendorHash deleteVendor proxyVendor;
  goModules = if (finalAttrs.vendorHash == null) then "" else
      GOFLAGS ? [ ],

      ...
    }@args:
    {
      inherit
        modRoot
        vendorHash
        deleteVendor
        proxyVendor
        ;
      goModules =
        if (finalAttrs.vendorHash == null) then
          ""
        else
          (stdenv.mkDerivation {
            name = "${finalAttrs.name or "${finalAttrs.pname}-${finalAttrs.version}"}-go-modules";

    nativeBuildInputs = (finalAttrs.nativeBuildInputs or [ ]) ++ [ go git cacert ];
            nativeBuildInputs = (finalAttrs.nativeBuildInputs or [ ]) ++ [
              go
              gitMinimal
              cacert
            ];

            inherit (finalAttrs) src modRoot;

@@ -92,7 +105,8 @@ in
              "GOPROXY"
            ];

    configurePhase = args.modConfigurePhase or ''
            configurePhase =
              args.modConfigurePhase or ''
                runHook preConfigure
                export GOCACHE=$TMPDIR/go-cache
                export GOPATH="$TMPDIR/go"
@@ -100,46 +114,62 @@ in
                runHook postConfigure
              '';

    buildPhase = args.modBuildPhase or (''
            buildPhase =
              args.modBuildPhase or (
                ''
                  runHook preBuild
    '' + lib.optionalString finalAttrs.deleteVendor ''
                ''
                + lib.optionalString finalAttrs.deleteVendor ''
                  if [ ! -d vendor ]; then
                    echo "vendor folder does not exist, 'deleteVendor' is not needed"
                    exit 10
                  else
                    rm -rf vendor
                  fi
    '' + ''
                ''
                + ''
                  if [ -d vendor ]; then
                    echo "vendor folder exists, please set 'vendorHash = null;' in your expression"
                    exit 10
                  fi

                  export GIT_SSL_CAINFO=$NIX_SSL_CERT_FILE
      ${if finalAttrs.proxyVendor then ''
                  ${
                    if finalAttrs.proxyVendor then
                      ''
                        mkdir -p "$GOPATH/pkg/mod/cache/download"
                        go mod download
      '' else ''
                      ''
                    else
                      ''
                        if (( "''${NIX_DEBUG:-0}" >= 1 )); then
                          goModVendorFlags+=(-v)
                        fi
                        go mod vendor "''${goModVendorFlags[@]}"
      ''}
                      ''
                  }

                  mkdir -p vendor

                  runHook postBuild
    '');
                ''
              );

    installPhase = args.modInstallPhase or ''
            installPhase =
              args.modInstallPhase or ''
                runHook preInstall

      ${if finalAttrs.proxyVendor then ''
                ${
                  if finalAttrs.proxyVendor then
                    ''
                      rm -rf "$GOPATH/pkg/mod/cache/download/sumdb"
                      cp -r --reflink=auto "$GOPATH/pkg/mod/cache/download" $out
      '' else ''
                    ''
                  else
                    ''
                      cp -r --reflink=auto vendor $out
      ''}
                    ''
                }

                if ! [ "$(ls -A $out)" ]; then
                  echo "vendor folder is empty, please set 'vendorHash = null;' in your expression"
@@ -157,7 +187,8 @@ in
            # empty hash requires explicit hash algorithm.
            outputHashAlgo = if finalAttrs.vendorHash == "" then "sha256" else null;
            # in case an overlay clears passthru by accident, don't fail evaluation
  }).overrideAttrs (finalAttrs.passthru.overrideModAttrs or overrideModAttrs);
          }).overrideAttrs
            (finalAttrs.passthru.overrideModAttrs or overrideModAttrs);

      nativeBuildInputs = [ go ] ++ nativeBuildInputs;

@@ -167,24 +198,30 @@ in
        GO111MODULE = "on";
        GOTOOLCHAIN = "local";

    CGO_ENABLED = args.env.CGO_ENABLED or (
      if args'?CGO_ENABLED then
        CGO_ENABLED =
          args.env.CGO_ENABLED or (
            if args ? CGO_ENABLED then
              # Compatibility layer to the CGO_ENABLED attribute not specified as env.CGO_ENABLED
              # TODO(@ShamrockLee): Remove and convert to
              # CGO_ENABLED = args.env.CGO_ENABLED or go.CGO_ENABLED
              # after the Nixpkgs 25.05 branch-off.
              lib.warn
                "${finalAttrs.finalPackage.meta.position}: buildGoModule: specify CGO_ENABLED with env.CGO_ENABLED instead."
          args'.CGO_ENABLED
                args.CGO_ENABLED
            else
              go.CGO_ENABLED
          );
      };

    GOFLAGS = GOFLAGS
      ++ lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS"
      GOFLAGS =
        GOFLAGS
        ++
          lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS)
            "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS"
            (lib.optional (!finalAttrs.proxyVendor) "-mod=vendor")
      ++ lib.warnIf (builtins.elem "-trimpath" GOFLAGS) "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true"
        ++
          lib.warnIf (builtins.elem "-trimpath" GOFLAGS)
            "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true"
            (lib.optional (!allowGoReference) "-trimpath");

      inherit enableParallelBuilding;
@@ -192,7 +229,9 @@ in
      # If not set to an explicit value, set the buildid empty for reproducibility.
      ldflags = ldflags ++ lib.optional (!lib.any (lib.hasPrefix "-buildid=") ldflags) "-buildid=";

    configurePhase = args.configurePhase or (''
      configurePhase =
        args.configurePhase or (
          ''
            runHook preConfigure

            export GOCACHE=$TMPDIR/go-cache
@@ -200,14 +239,21 @@ in
            export GOPROXY=off
            export GOSUMDB=off
            cd "$modRoot"
    '' + lib.optionalString (finalAttrs.vendorHash != null) ''
      ${if finalAttrs.proxyVendor then ''
          ''
          + lib.optionalString (finalAttrs.vendorHash != null) ''
            ${
              if finalAttrs.proxyVendor then
                ''
                  export GOPROXY="file://$goModules"
      '' else ''
                ''
              else
                ''
                  rm -rf vendor
                  cp -r --reflink=auto "$goModules" vendor
      ''}
    '' + ''
                ''
            }
          ''
          + ''

            # currently pie is only enabled by default in pkgsMusl
            # this will respect the `hardening{Disable,Enable}` flags if set
@@ -216,9 +262,11 @@ in
            fi

            runHook postConfigure
    '');
          ''
        );

    buildPhase = args.buildPhase or (
      buildPhase =
        args.buildPhase or (
          lib.warnIf (builtins.elem "-buildid=" ldflags)
            "`-buildid=` is set by default as ldflag by buildGoModule"
            ''
@@ -279,7 +327,8 @@ in
                echo "Building subPackage $pkg"
                buildGoDir install "$pkg"
              done
    '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
            ''
          + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
            # normalize cross-compiled builds w.r.t. native builds
            (
              dir=$GOPATH/bin/''${GOOS}_''${GOARCH}
@@ -290,12 +339,15 @@ in
                rmdir $dir
              fi
            )
    '' + ''
          ''
          + ''
            runHook postBuild
    '');
          ''
        );

      doCheck = args.doCheck or true;
    checkPhase = args.checkPhase or ''
      checkPhase =
        args.checkPhase or ''
          runHook preCheck
          # We do not set trimpath for tests, in case they reference test assets
          export GOFLAGS=''${GOFLAGS//-trimpath/}
@@ -307,7 +359,8 @@ in
          runHook postCheck
        '';

    installPhase = args.installPhase or ''
      installPhase =
        args.installPhase or ''
          runHook preInstall

          mkdir -p $out
@@ -333,5 +386,5 @@ in
        # Add default meta information.
        platforms = go.meta.platforms or lib.platforms.all;
      } // meta;
    };
}
))
+6 −6
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
  makeBinaryWrapper,
}:

buildGoModule rec {
buildGoModule (finalAttrs: {
  pname = "symfony-cli";
  version = "5.11.0";
  vendorHash = "sha256-6DNirMtVuuWJziDy6HeJxHQnV2f7jmie7kcXvUDfN94=";
@@ -17,7 +17,7 @@ buildGoModule rec {
  src = fetchFromGitHub {
    owner = "symfony-cli";
    repo = "symfony-cli";
    rev = "v${version}";
    rev = "v${finalAttrs.version}";
    hash = "sha256-r8B9lFcTG0TWb3U8eRzg9SkwUY90805wdFlmPbtMywk=";
    leaveDotGit = true;
    postFetch = ''
@@ -29,7 +29,7 @@ buildGoModule rec {
  ldflags = [
    "-s"
    "-w"
    "-X main.version=${version}"
    "-X main.version=${finalAttrs.version}"
    "-X main.channel=stable"
  ];

@@ -53,18 +53,18 @@ buildGoModule rec {
  passthru = {
    updateScript = nix-update-script { };
    tests.version = testers.testVersion {
      inherit version;
      inherit (finalAttrs) version;
      package = symfony-cli;
      command = "symfony version --no-ansi";
    };
  };

  meta = {
    changelog = "https://github.com/symfony-cli/symfony-cli/releases/tag/v${version}";
    changelog = "https://github.com/symfony-cli/symfony-cli/releases/tag/v${finalAttrs.version}";
    description = "Symfony CLI";
    homepage = "https://github.com/symfony-cli/symfony-cli";
    license = lib.licenses.agpl3Plus;
    mainProgram = "symfony";
    maintainers = with lib.maintainers; [ drupol ];
  };
}
})