Fetching and building a Make dependency from a flake

Hi I am trying to fetch and build a dependency from GitHub. This is a required for a larger Cabal project, but I am trying to see if I can accomplish the following actions:

  • fetch the repo from GitHub with a specific revision
  • build a derivation (assuming the wrapper flake-utils should support autogen.sh and configure)
  • store the build in the /nix/store/

I have the following flake:

{
  description = "Bitcoin core security protocol 256k1.";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }: 
    with flake-utils.lib; eachDefaultSystem (system: 
    let
      pkgs = nixpkgs.legacyPackages.${system};
    in rec {

      packages = { 
        secp256k1 = pkgs.stdenv.mkDerivation rec {
          name = "secp256k1";
          src = builtins.fetchGit {
            url = "https://github.com/bitcoin-core/secp256k1";
            rev = "ac83be33d0956faf6b7f61a60ab524ef7d6a473a";
          };
        };

        gcc = pkgs.gcc;

        buildPhase = ''
          ./autogen.sh && ./configure && make
        '';

        installPhase = ''
          runHook preInstall
          sudo make install
          runHook postInstall
        '';
      };

      defaultPackage = packages.secp256k1;
    });
}

However, the flake failed to build because of the following error:

warning: Git tree '${PARENT_DIR}/deps/secp256k1' is dirty
error: builder for '/nix/store/izj2klinw7m21r6ly55vak7g2h79qs5l-secp256k1.drv' failed to produce output path for output 'out' at '/nix/store/6cyg84v638g5dddvc0bdaj698kihpc3k-secp256k1'

Context: I am new to Nix, only started diving into the ecosystem a couple weeks ago. I think I want to stick with flakes since I like to keep projects isolated into dev shells.

error: builder for '/nix/store/izj2klinw7m21r6ly55vak7g2h79qs5l-secp256k1.drv' >failed to produce output path for output 'out' at '/nix/>store/6cyg84v638g5dddvc0bdaj698kihpc3k-secp256k1'

Hey. I am a newbie myself, but from what I understand, each derivation needs to create something inside $out path, that is, that something to be put in the /nix/store/ for the built package. Here, you download the source for secp256k1, but do nothing with it. You have to tell Nix what to do with the downloaded data. For example, the installPhase inside packages.secp256k1 needs to be

mkdir -p $out/
mv <downloaded data> $out/

However, I presume that the buildPhase and installPhase you already defined are supposed to be the operations made on the secp256k1? Then they need to go inside packages.secp256k1:

# ...
packages = {
  secp256k1 = ... {
    buildPhase = ''
      ...
    '';
    installPhase = ''
      ...
    '';
  }
};

For your installPhase, I am not sure what the hooks and make install do, but if you want to install the dependency in the /nix/store/, you cannot use the predefined make install (presumably) which would try to put the installed data somewhere in /usr/bin/ etc. You need to move the built data to the $out path, that is, $out/bin/ (binary), or $out/lib/ (library), etc.

You might also have to specify packages.secp256k1.nativeBuildInputs for build-time dependencies (such as that gcc) and/or packages.secp256k1.buildInputs for runtime dependencies.

Furthermore, if you do not need the unpackPhase, you might need to set packages.secp256k1.phases to ["buildPhase", "installPhase"] to skip the unpackPhase.

Hope this helps (and is factually correct :wink:).

1 Like

Thanks to @Adda I was able to build the derivation.

Indeed, the build command should be part of the package sec256k1. I also inspected the build using this guide and realized that I don’t need the other phases. flake-utils seems to assume their responsibilities.

I was able to clone and but failed to configure because the autoreconf binary was missing from the flake. This is solved by specifying it in:

nativeBuildInputs = [
    pkgs.autoreconfHook
];

The full working flake is here for future record:

{
    description = "Bitcoin core security protocol 256k1.";

    inputs =
    {
        nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
        flake-utils.url = "github:numtide/flake-utils";
    };

    outputs =
    {
        self,
        nixpkgs,
        flake-utils
    }: 
    with flake-utils.lib; eachDefaultSystem (system: 

        let pkgs = nixpkgs.legacyPackages.${system};

            in rec {

                packages = { 
                    secp256k1 = pkgs.stdenv.mkDerivation {
                        name = "secp256k1";
                        src = builtins.fetchGit {
                            url = "https://github.com/bitcoin-core/secp256k1";
                            ref = "master";
                            rev = "ac83be33d0956faf6b7f61a60ab524ef7d6a473a";
                        };

                    nativeBuildInputs = [
                        pkgs.autoreconfHook
                    ];

                    installPhase = ''
                        ./autogen.sh && ./configure --prefix=$out
                        make install
                    '';
            };
        };

        defaultPackage = packages.secp256k1;
    });
}
1 Like