Converting custom overlays to a flake

Hi, I am pretty new to NixOS and I am trying to create a git which contains a bunch of custom overlays which I have written to use as a development environment for another project. I have got this working using a default.nix and importing it into my shell on the project but I would like to update this to a flake. I am really struggling with groking flakes.

Basically i have this in a default.nix

self: super:
{
  custom-lib-1 = super.callPackage ./pkgs/custom-lib-1 { };
  custom-lib-2 = super.callPackage ./pkgs/custom-lib-2 { };
}

and I can use it in a shell.nix in my application using this:

let
  src = {
    url = "https://github.com/xxxx/overlay.tar.gz";
    sha256 = "sha256:0000";
  };
  overlay = builtins.fetchtarball src;
  pkgs = import  <nixpkgs> {
    config = {};
    overlays = [ (import overlay) ];
};

in pkgs.mkshell {
  nativebuildinputs = [ 
    pkgs.custom-library-1
    pkgs.custom-library-2
  ];
}

Can anyone point me in the right direction to converting this to a flake? I just cant seem to get my head around it and have little no progress.

Thanks

I can point you to Starter Confifs from @Misterio77:

The standard directory has some examples.

Unless you’re replacing existing dependencies of existing packages, you don’t really an overlay for this, and they do come with a somewhat heavy computational cost. Right now you’re just using the overlay to put values in pkgs and immediately extracting them again. There’s no actual need for pkgs to be involved in transporting them around.

That said, the most straightforward conversion of what you have is to make one flake which has the overlay as an output, then use that flake as an input to another flake with a devShell output. You reference the overlay through the flake input instead of using a fetchtarball.

a/flake.nix:

{
  outputs = { self, ... }: {
    overlay = self: super: { ... };
  };
}

b/flake.nix:

{
  inputs.a.url = ...;
  inputs.nixpkgs.url = ...;
  outputs = { self, nixpkgs, a, ... }: {
    devShells.x86_64-linux.default = let
      pkgs = import nixpkgs {
        system = "x86_64-linux";
        overlays = [ a.overlay ];
      };
    in pkgs.mkShell { ... };
  };
2 Likes

According to the wiki the conventional naming is

  # Overlay, consumed by other flakes
  overlays."<name>" = final: prev: { };
  # Default overlay
  overlays.default = {};

Thanks very much everyone this is very helpful. I downloaded the nix-start-configs and have been experimenting with it but I am experiencing a issue with package dependency.

For example:

I have a application and library that are not in nixpkgs and application depends on the library - how would I ensure that the application has access to the library? Right now I get the following error

error: Function called without required argument "lib1" at /nix/store/s94wkwdpqpaj6w4mvbghbbxp1558sjxm-source/pkgs/app1/default.nix:12

This previously worked when using self:super, here is what the application nix looks like:


{ pkgs ? (import <nixpkgs> {}).pkgs }: {
  lib1 = pkgs.callPackage ./lib1 { };
  app1 = pkgs.callPackage ./app1 { };
}
{ 
  stdenv,
  cmake,
  pkg-config,
  lib1
}:

stdenv.mkDerivation rec {
  name = "app1";

  src = builtins.fetchGit {
    url = "git@gitlab.com:app1.git";
    ref = "master";   
  };app1

  nativeBuildInputs = [ 
    cmake
    pkg-config
    lib1
  ];

  doCheck = true;

  cmakeFlags = [
    "-DCMAKE_BUILD_TYPE=Release"
  ];
}

and here is my flake.nix;

{
  description = "Your new nix config";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11";
  };

  outputs = { self, nixpkgs, home-manager, ... }@inputs:
    let
      inherit (self) outputs;
      forAllSystems = nixpkgs.lib.genAttrs [
        "aarch64-linux"
        "i686-linux"
        "x86_64-linux"
        "aarch64-darwin"
        "x86_64-darwin"
      ];
    in
    rec {
      # Your custom packages
      # Acessible through 'nix build', 'nix shell', etc
      packages = forAllSystems (system:
        let pkgs = nixpkgs.legacyPackages.${system};
        in import ./pkgs { inherit pkgs; }
      );
      # Devshell for bootstrapping
      # Acessible through 'nix develop' or 'nix-shell' (legacy)
      devShells = forAllSystems (system:
        let pkgs = nixpkgs.legacyPackages.${system};
        in import ./shell.nix { inherit pkgs; }
      );
    };
}

calling nix build .#app1 produces the error above

Well here where is your overlay supposed to come from? From an external flake? Then you need to add your flake as an input as explained by @tejing. Also, your pkgs needs to say that it uses the overlay, so instead of pkgs = nixpkgs.legacyPackages.${system}; you should do somethink like:

    let pkgs = import nixpkgs {
      system = "x86_64-linux";
      overlays = [
        self.overlays.default # For an overlay defined in the current flake
        a.overlays.default # For an overlay defined in a dependency "a" of your flake as explained by tejing
      ];
    }; in …

edit oh I see, I read too quickly your message. Let me correct my message

Ah I think I see what disturb you, I read too quickly your message. All your libraries are in the current flake so you don’t need to add an external flake. What you want to do is to create a local overlay with your libraries, add this overlay to pkgs, and just add the wanted packages to packages.

{
  description = "Your new nix config";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11";
  };

  outputs = { self, nixpkgs, home-manager, ... }@inputs:
    let
      inherit (self) outputs;
      forAllSystems = nixpkgs.lib.genAttrs [
        "aarch64-linux"
        "i686-linux"
        "x86_64-linux"
        "aarch64-darwin"
        "x86_64-darwin"
      ];
    in
      rec {
        # Your custom packages
        # Acessible through 'nix build', 'nix shell', etc
        packages = forAllSystems (system:
          let
            pkgs = import nixpkgs {
              inherit system;
              overlays = [
                self.overlays.default
              ];
            };
          in {
            lib1 = pkgs.lib1;
            app1 = pkgs.app1;
          }
        );
        overlays.default = final: prev: {
          lib1 = prev.callPackage ./lib1 { };
          app1 = prev.callPackage ./app1 { };
        };
        # Devshell for bootstrapping
        # Acessible through 'nix develop' or 'nix-shell' (legacy)
        devShells = forAllSystems (system:
          let
            pkgs = import nixpkgs {
              inherit system;
              overlays = [
                self.overlays.default
              ];
            };
          in import ./shell.nix { inherit pkgs; }
        );
      };
}
1 Like

Replace with (note the rec)

{ pkgs ? (import <nixpkgs> {}).pkgs }: rec {
  lib1 = pkgs.callPackage ./lib1 { };
  app1 = pkgs.callPackage ./app1 { inherit lib1; };
}

callPackage automatically fills in things that are in nixpkgs, but for anything else, or anything you want to override for some reason, you need to include it in the argument to callPackage.