Drowse: Dynamic derivations made easy

Drowse is a thin wrapper around dynamic derivations to make it easier to use. It allows you to enjoy the fine-grained caching of lang2nix tools without needing IFD or keeping around generated files.

Here is what using drowse with crate2nix looks like

drowse.crate2nix {
  pname = "hello";
  version = "0.1.0";

  src = ./.; # filter with lib.fileset to reduce rebuilds
  # src = fetchFromGitHub <...> # this can also be fetched

  # optional: enable the fancy feature
  args.rootFeatures = [ "fancy" ];

  # optional: another way to enable the fancy feature
  select = ''
    project: project.rootCrate.build.override { features = [ "fancy" ]; }
  '';
};
15 Likes

looking pretty good! it might be nice to even see something like this upstream at some point?

2 Likes

Would love to see this in nixpkgs once dynamic-derivations is stabilized! All the API are made with extendMkDerivation, which should make drowse a good testing ground for an ergonomic API suitable for nixpkgs.

One current issue is that drowse depends on recursive-nix, which might take a very long time if it ever gets stabilized. I suggest keeping an eye on A very restricted recursive nix socket in the sandbox · Issue #8602 · NixOS/nix · GitHub, which is an alternative to recursive-nix that can hopefully be stabilized with dynamic-derivations in the near(er) future.

9 Likes

I made a nix plugin that does something similar, mainly because crate2nix has really slow eval time for large projects.

but I also made crate2nix at the same time faster:

1 Like

how do you get native dependencies aka crate overrides into your dynamic derivations?

1 Like

args can be a string for things that aren’t json-compatible. Take the example in the crate2nix docs, it can be translated to this

{
  args = ''
    {
      buildRustCrateForPkgs =
        pkgs:
        pkgs.buildRustCrate.override {
          defaultCrateOverrides = pkgs.defaultCrateOverrides // {
            funky-things = attrs: {
              buildInputs = [ pkgs.openssl ];
            };
          };
        };
    }
  '';
}

I’m not sure where this is documented, but looking at Cargo.nix, this might also work:

{
  args = ''
    {
      defaultCrateOverrides =
        let
          pkgs = import <nixpkgs> { };
        in
        pkgs.defaultCrateOverrides
        // {
          funky-things = attrs: {
            buildInputs = [ pkgs.openssl ];
          };
        };
    }
  '';
}

<nixpkgs> is passed in by default through NIX_PATH, you can pass other external dependencies through environment variables too

ah, I see, this would be than not very lazy I assume?

args is simply copied into the builder as plain text (or json if it’s structured) and gets nix-instantiateed only at build time. The NIX_PATH is built with pkgs.path, which should be basically free at evaluation time.