From 7997b6fc5dc2f5beb1bbdbb7a5bbed2e6c530dac Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar <3998+srid@users.noreply.github.com> Date: Mon, 6 Mar 2023 17:37:35 -0500 Subject: [PATCH] Add a default for `haskellFlakeProjectModules` (#106) --- CHANGELOG.md | 1 + doc/guide/modules.md | 30 +++++++++++++++++++++++++ nix/flake-module.nix | 52 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aebe1be..a3c32d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - #52: Expose the final package set as `finalPackages`. Rename `haskellPackages`, accordingly, to `basePackages`. Overlays are applied on top of `basePackage` -- using `source-overrides`, `overrides`, `packages` in that order -- to produce `finalPackages`. - #68: You can now use `imports` inside of `haskellProjects.` to modularize your Haskell project configuration. - #79: `flake.haskellFlakeProjectModules.` option can be used to set and expose your Haskell project modules to other flakes. + - #106: Auto-generate the default modules in 'haskellFlakeProjectModules' for reuse in downstream flakes. - #67: `overrides` will be combined using `composeManyExtensions`, however their order is arbitrary. This is an experimental feature, and a warning will be logged. ## 0.1.0 diff --git a/doc/guide/modules.md b/doc/guide/modules.md index c9f5be0..3b2cab5 100644 --- a/doc/guide/modules.md +++ b/doc/guide/modules.md @@ -52,6 +52,36 @@ A haskell-flake project module takes the following arguments: | `pkgs` | The perSystem's `pkgs` argument | | `self` | The flake's `self` | +## Default modules + +By default, haskell-flake will generate the following modules for the "default" `haskellProject`: + +| Module | Contents | +| -- | -- | +| `haskellFlakeProjectModules.input` | Dependency overrides only | +| `haskellFlakeProjectModules.local` | Local packages only | +| `haskellFlakeProjectModules.output` | Local packages & dependency overrides | + +The idea here being that you can "connect" two Haskell projects such that they depend on one another while reusing the overrides from one place. For example, if you have a project "foo" that depends on "bar" and if "foo"'s flake.nix has "bar" as its input, then in "foo"'s `haskellProject.default` entry you can import "bar" as follows: + +```nix +# foo's flake.nix's perSystem +{ + haskellProjects.default = { + imports = [ + inputs.bar.haskellFlakeProjectModules.output + ]; + packages = { + foo.root = ./.; + }; + }; +} +``` + +By importing "bar"'s `output` project module, you automatically get the overrides from "bar" (unless you use the `local` module) as well as the local packages[^bar]. This way you don't have to duplicate the `overrides` and manually specify the `source-overrides` in "foo"'s flake.nix. + +[^bar]: Local packages come from the `packages` option. So this is typically the "bar" package itself for single-package projects; or all the local projects if it is a multi-package project. + ## Examples - https://github.com/srid/nixpkgs-140774-workaround diff --git a/nix/flake-module.nix b/nix/flake-module.nix index d74335a..f91468b 100644 --- a/nix/flake-module.nix +++ b/nix/flake-module.nix @@ -1,9 +1,10 @@ # A flake-parts module for Haskell cabal projects. -{ self, config, lib, flake-parts-lib, ... }: +{ self, config, lib, flake-parts-lib, withSystem, ... }: let inherit (flake-parts-lib) - mkPerSystemOption; + mkPerSystemOption + mkSubmoduleOptions; inherit (lib) mkOption types; @@ -226,14 +227,6 @@ in type = types.attrsOf projectSubmodule; }; - haskellFlakeProjectModules = mkOption { - type = types.lazyAttrsOf types.deferredModule; - default = { }; - description = '' - An attrset of `haskellProjects.` modules that can be imported in - other flakes. - ''; - }; }; config = @@ -272,5 +265,44 @@ in config.haskellProjects; }; }); + + flake = mkSubmoduleOptions { + haskellFlakeProjectModules = mkOption { + type = types.lazyAttrsOf types.deferredModule; + description = '' + An attrset of `haskellProjects.` modules that can be imported in + other flakes. + ''; + defaultText = '' + Package and dependency information for this project exposed for reuse + in another flake, when using this project as a Haskell dependency. + + Typically the consumer of this flake will want to use one of the + following modules: + + - output: provides both local package and dependency overrides. + - local: provides only local package overrides (ignores dependency + overrides in this flake) + ''; + default = rec { + # The 'output' module provides both local package and dependency + # overrides. + output = { + imports = [ input local ]; + }; + # The 'local' module provides only local package overrides. + local = { pkgs, lib, ... }: withSystem pkgs.system ({ config, ... }: { + source-overrides = + lib.mapAttrs (_: v: v.root) + config.haskellProjects.default.packages; + }); + # The 'input' module contains only dependency overrides. + input = { pkgs, ... }: withSystem pkgs.system ({ config, ... }: { + inherit (config.haskellProjects.default) + source-overrides overrides; + }); + }; + }; + }; }; }