Future direction of rules_nixpkgs regarding nix flakes
Is your feature request related to a problem? Please describe. With the Nix ecosystem moving towards flakes we should start thinking about what this means for rules_nixpkgs. Flakes are still experimental in Nix and will need to stabilise before we can fully commit to an approach, but starting the discussion now and exploring ideas will help us prepare.
Some things to think about:
- How can flakes be integrated into rules_nixpkgs?
- How can they benefit users?
- What API improvements can they enable?
- etc
Discussions on the subject:
The current approach I'm attempting to use is having a Flake at the WORKSPACE level that defines both the devShell and a bazel set under packages."${system}" containing any derivations I want to pull into Bazel. From there, I quickly wrote nix_flake_package() (using nixpkgs_package() as a starting point) that uses nix build to get the output path for a given derivation.
Example:
nix_flake_package(
name = "nix_rust",
nix_flake_file = "//:flake.nix",
nix_flake_lock_file = "//:flake.lock",
package = "bazel.rust",
)
This expand to nix build <nix_flake_file.dirname>#bazel.rust --print-out-paths --out-link bazel-support/nix-out-link <nixopts> and then uses the same logic as nixpkgs_package(). One of the main upsides I see is not needing the repository/repositories parameters of nixpkgs_package() as the Flake evaluation takes care of all of that and Bazel doesn't have to separately fetch them.
Rough docs:
Make the content of a local Nix Flake package available in the Bazel workspace.
Args:
name: A unique name for this repository.
nix_flake_file: Label to `flake.nix` that will be evaluated.
nix_flake_lock_file: Label to `flake.lock` that corresponds to `nix_flake_file`.
nix_flake_file_deps: Additional dependencies of `nix_flake_file` if any.
package: Nix Flake package to make available. The default package will be used if not specified.
... <build_file docs+behavior copied from `nixpkgs_package()`>
If this approach/API seems reasonable, I'd be happy to put up a PR 🙂
Hi @rickvanprim, thanks for taking an interest in this issue and sorry for the delayed reply. While I expect we'll need a lot more thought and discussion on this topic before we settle on a complete solution, this seems like a reasonable first step towards making flake packages available to Bazel. If you already have a change that implements this it would be great to see a PR so we can discuss the details.
One thing to consider — rules_nixpkgs is currently undergoing a large refactor to support bzlmod, so we should try not to regress that effort in the process of supporting flake packages. Any thoughts on this proposal @aherrmann and @layus?
While I expect we'll need a lot more thought and discussion on this topic before we settle on a complete solution, this seems like a reasonable first step towards making flake packages available to Bazel.
:100: Exactly, it makes sense to move forward in incremental steps on this. So long as the code makes it clear that the API isn't stable, yet, we can keep iterating on it.
One thing to consider — rules_nixpkgs is currently undergoing a large refactor to support bzlmod, so we should try not to regress that effort in the process of supporting flake packages.
This approach seems to fit well with the local_attr|file|expr set of nix_pkg bzlmod tags. However, I don't know how to square it with the globally unified attr tag. The design doc goes in-depth on the constraints and requirements. But, generally the idea is to provide two different ways of import Nix packages: local and globally unified. Local imports are for dependencies where your Bazel module needs this very specific version of a Nix provided package. Build tools or test runners might good examples. Globally unified imports are for packages that need be identical across the transitive Bazel module graph, shared library dependencies are a good example. If you have multiple components coming from different Bazel modules with common Nix provided shared library dependencies that you need to link together, then the shared library needs to be unified to avoid nasty linking or runtime errors.