How to optimise Nix package rebuilds

Setup: Assume I am working on a project that contains a bunch of C/Rust/whatever. The codebase depends on some large projects with custom patches (such as the Linux kernel). Gluing them together reproducibly is nice in Nix, so I want to use Nix packages for development, and I end up with a build situation like this:

  • The main project code has a cmake build. This build is important for packaging to various platforms (not just Nix).
  • I defined Nix derivations for the custom dependencies.
  • I defined one Nix derivation for my project, simply invoking cmake during the build, and pulling in the custom dependencies.

Problem: This works, but it is inefficient as any change to my codebase will cause a rebuild of the Nix package for my application, preventing quick iteration.

I understand that Nix operating at the granularity of Nix packages cannot optimize within a single package build automatically.

  • What are the typical approaches to tackle this situation?
    • I don’t want to de-compose the application into many fine-grained Nix derivations, effectively replacing the cmake build
  • For example, could I make the cmake build output from a previous package build available to a subsequent build, such that cmake can reuse artifacts which don’t need to be recompiled?
  • Are there any examples of something like this?
  • Are there other approaches?

For iterating on your project (and not on the custom dependencies), the usual thing is to drop into a shell with nix-shell or nix develop and do your iteration inside that, working directly with CMake.

For the custom dependencies, I’d be a lot less confident about how to make it quick to iterate between working on your patches and your main project. Maybe you could make a dev shell Nix script that includes, rather than depends on, the build inputs and build steps of your custom dependencies, and some custom CMake to wire them together just for that shell? I think Nix is much better optimized for one derivation per isolated development unit.