Search code examples
nix

How is vendorSha256 computed?


I'm trying to understand how the vendorSha256 is calculated when using buildGoModule. In nixpkgs manual the only info I get is:

"vendorSha256: is the hash of the output of the intermediate fetcher derivation."

Is there a way I can calculate the vendorSha256 for a nix expression I'm writing? To take a specific example, how was the "sha256-Y4WM+o+5jiwj8/99UyNHLpBNbtJkKteIGW2P1Jd9L6M=" generated here:

{ lib, buildGoModule, fetchFromGitHub }:

buildGoModule rec {
  pname = "oapi-codegen";
  version = "1.6.0";

  src = fetchFromGitHub {
    owner = "deepmap";
    repo = pname;
    rev = "v${version}";
    sha256 = "sha256-doJ1ceuJ/gL9vlGgV/hKIJeAErAseH0dtHKJX2z7pV0=";
  };

  vendorSha256 = "sha256-Y4WM+o+5jiwj8/99UyNHLpBNbtJkKteIGW2P1Jd9L6M=";

  # Tests use network
  doCheck = false;

  meta = with lib; {
    description = "Go client and server OpenAPI 3 generator";
    homepage    = "https://github.com/deepmap/oapi-codegen";
    license     = licenses.asl20;
    maintainers = [ maintainers.j4m3s ];
  };
}

Solution

  • From the manual:

    The function buildGoModule builds Go programs managed with Go modules. It builds a Go Modules through a two phase build:

    1. An intermediate fetcher derivation. This derivation will be used to fetch all of the dependencies of the Go module.
    2. A final derivation will use the output of the intermediate derivation to build the binaries and produce the final output.

    You can see that, when you're trying to build the above expression in the ouput of nix-build. If you run:

    nix-build -E 'with import <nixpkgs> { }; callPackage ./yourExpression.nix { }'
    

    you see the first 2 lines of output:

    these 2 derivations will be built:
      /nix/store/j13s3dvlwz5w9xl5wbhkcs7lrkgksv3l-oapi-codegen-1.6.0-go-modules.drv
      /nix/store/4wyj1d9f2m0521nlkjgr6al0wfz12yjn-oapi-codegen-1.6.0.drv
    

    The first derivation will be used to fetch all dependencies for your Go module, and the second will be used to build your actual module. So vendorSha256 is the hash of the output of that first derivation.

    When you write a Nix expression to build a Go module you don't know in advance that hash. You only know it that the first derivation has been realised(download dependencies and find the hash based on them). However you can use Nix validation to find out the value of vendorSha256.

    Modify your Nix expression like so:

    { lib, buildGoModule, fetchFromGitHub }:
    
    buildGoModule rec {
      pname = "oapi-codegen";
      version = "1.6.0";
    
      src = fetchFromGitHub {
        owner = "deepmap";
        repo = pname;
        rev = "v${version}";
        sha256 = "sha256-doJ1ceuJ/gL9vlGgV/hKIJeAErAseH0dtHKJX2z7pV0=";
      };
    
       vendorSha256 = lib.fakeSha256;
    
      # Tests use network
      doCheck = false;
    
      meta = with lib; {
        description = "Go client and server OpenAPI 3 generator";
        homepage    = "https://github.com/deepmap/oapi-codegen";
        license     = licenses.asl20;
        maintainers = [ maintainers.j4m3s ];
      };
    }
    
    

    The only difference is vendorSha256 has now the value of lib.fakeSha256, which is just a fake/wrong sha256 hash. Nix will try to build the first derivation and will check the hash of the dependencies against this value. Since they will not match, an error will occur:

    error: hash mismatch in fixed-output derivation '/nix/store/j13s3dvlwz5w9xl5wbhkcs7lrkgksv3l-oapi-codegen-1.6.0-go-modules.drv':
             specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
                got:    sha256-Y4WM+o+5jiwj8/99UyNHLpBNbtJkKteIGW2P1Jd9L6M=
    error: 1 dependencies of derivation '/nix/store/4wyj1d9f2m0521nlkjgr6al0wfz12yjn-oapi-codegen-1.6.0.drv' failed to build
    

    So this answer your question. The value of vendorSha256 you need is sha256-Y4WM+o+5jiwj8/99UyNHLpBNbtJkKteIGW2P1Jd9L6M=. Copy and add it your file and you're good to go!