Skip to content

Consume and modify dream2nix packages

Given the following package

upstream/my-package.nix

{config, lib, dream2nix, ...}: {

  imports = [
    dream2nix.modules.nodejs.mkDerivation
    dream2nix.modules.nodejs.package-lock
  ];

  pname = "my-package";
  version = "2.0.0";

  src = {
    type = github;
    owner = "my-user";
    repo = "my-repo";
    ref = config.version;
    hash = "sha256-mia90VYv/YTdWNhKpvwvFW9RfbXZJSWhJ+yva6EnLE8=";
  };

  # declare dependency on python3
  deps = {nixpkgs, ...}: {
    python3 = nixpkgs.python39;
  };

  nativeBuildInputs = [
    config.deps.python3
  ];

  configurePhase = ''
    python3 --version
  '';

  buildPhase = ''
    python3 -c 'print("Hello World!")' > $out
  '';
}

upstream/default.nix

{
  nixpkgs ? import <nixpkgs> {},
  dream2nix ?
    import
    (builtins.fetchTarball "https://dream2nix.dev/tarball/1.0")
    {inherit nixpkgs;},
}: {
  packages.my-package = dream2nix.eval ./my-package.nix;
}

1. Override using modules

1.1 Define a module for the override

my-package-override.nix

{config, lib, ... }: {

  version = "2.1.0";

  # No need to re-define other fetcher attributes.
  # The module system updates them for us.
  src.hash = "sha256-LM5GDNjLcmgZVQEeANWAOO09KppwGaYEzJBjYmuSwys=";

  deps = {nixpkgs, ...}: {

    # change the python version
    python3 = lib.mkForce nixpkgs.python310;

    # add a dependency on hello  
    hello = nixpkgs.hello;
  };

  # add hello to nativeBuildInputs
  # (`oldAttrs.nativeBuildInputs + ...` not needed here)
  nativeBuildInputs = [
    config.deps.hello
  ];

  # add lines to configurePhase
  postConfigure = ''
    hello --version
  '';

  # replace the build phase via mkForce
  buildPhase = lib.mkForce "
    hello > $out
  ";
}

1.2 Apply my-package-override.nix via extendModules

Using extendModules is simple. It allows to extend an existing package with another module. This doesn't require knowledge about the original modules that went into the package.

./default.nix

let
  nixpkgs = import <nixpkgs> {};
  upstream = import ./upstream {inherit nixpkgs;};
  my-package = upstream.packages.my-package;

  # The recommended way of modifying a package is using extendModules,
  #    which uses the module systems merge logic to apply changes.
  my-package-extended = my-package.extendModules {
    modules = [./my-package-override.nix];
  };

in {
  inherit my-package-extended;
}

1.3 Or apply my-package-override.nix via dream2nix.eval

This approach is a bit cleaner. It doesn't introduce a chain of extendModules function calls. This style also makes it obvious which modules went into the package. Though, this requires access to the original my-package.nix module and knowledge about the packageSets that went into it.

default.nix

{
  nixpkgs ? import <nixpkgs> {},
  dream2nix ?
    import
    (builtins.fetchTarball "https://dream2nix.dev/tarball/1.0")
    {inherit nixpkgs;},

}: let

  my-package-extended = dream2nix.eval
    {packagetSets = {inherit nixpkgs;};}
    [
      ./upstream/my-package.nix
      ./my-package-override.nix
    ];

in {
  my-package-extended
}

2. Override package via override[Attrs] functions

It is recommended to use modules for overriding, like described above, but for backward compatibility, overrideAttrs and override are still supported.

let
  nixpkgs = import <nixpkgs> {};
  upstream = import ./upstream {inherit nixpkgs;};
  my-package = upstream.packages.my-package;

  # Override the package via `override` and `overrideAttrs`
  my-package-overridden' = my-package.override
    (oldAttrs: {

      # change the python version
      python3 = nixpkgs.python310;
    });

  my-package-overridden = my-package-overridden'.overrideAttrs
    (oldAttrs: rec {

      version = "2.1.0";

      src = nixpkgs.fetchFromGithub {
        owner = "my-owner";
        repo = "my-repo";
        ref = version;
        hash = "sha256-LM5GDNjLcmgZVQEeANWAOO09KppwGaYEzJBjYmuSwys=";
      };

      # add hello to nativeBuildInputs
      nativeBuildInputs = [
        nixpkgs.hello
      ];

      # add lines to configurePhase
      postConfigure = ''
        hello --version
      '';

      # replace the build phase
      buildPhase = ''
        hello > $out
      '';
    });

in {
  inherit my-package-overridden;
}