on iko/ghcjs-patch-master help sign in
Add cross compilation and devShell to project.flake (#1141)

The default shell `devShell` works by adding a default `shell` to all projects. You can pass the shell arguments to the project function using the new `shell` argument: ``` let myProject = haskell-nix.project { src = ./.; shell.tools = { cabal = {}; }; shell.crossPlatforms = p: [ p.cross ]; }; ``` This will include js-unknown-ghcjs-cabal in the `devShell`. To add cross compiled outputs to the flake pass `crossPlatforms` to the `flake` function. ``` myProject.flake { crossPlatforms = p: [ p.cross ]; } ``` To cross compile a component include the platforms `config` string to the output name like this ``` nix build .#js-unknown-ghcjs:pkg-name:lib:pkg-name ```

commitc3841b4208f4529827316e3c81af6142b9094a1f authorHamish Mackenzie <Hamish.Mackenzie@iohk.io> dateThu 17 Jun 2021, 19:07 (5 years ago) parent1c2c9cd
4 files changed+83−43
flake.nix+5−10 modules/cabal-project.nix+13 modules/stack-project.nix+13 overlays/haskell.nix+52−33
flake.nix+5−10
@@ -4,9 +4,8 @@
44 inputs = {
55 # Note: keep this in sync with sources.json!
66 nixpkgs.url = github:NixOS/nixpkgs/f02bf8ffb9a5ec5e8f6f66f1e5544fd2aa1a0693;
7− nixpkgs-2003.url = github:NixOS/nixpkgs/7f73e46625f508a793700f5110b86f1a53341d6e;
87 nixpkgs-2009.url = github:NixOS/nixpkgs/f02bf8ffb9a5ec5e8f6f66f1e5544fd2aa1a0693;
9− nixpkgs-unstable.url = github:NixOS/nixpkgs/410bbd828cdc6156aecd5bc91772ad3a6b1099c7;
8+ nixpkgs-unstable.url = github:NixOS/nixpkgs/d8eb97e3801bde96491535f40483d550b57605b9;
109 };
1110
1211 outputs = { self, nixpkgs, ... }:
@@ -14,14 +13,10 @@
1413
1514 internal = rec {
1615 config = import ./config.nix;
17− # We can't import ./nix/sources.nix directly, because that uses nixpkgs to fetch by default,
18− # and importing nixpkgs without specifying localSystem doesn't work on flakes.
19− sources = let
20− sourcesInfo =
21− builtins.fromJSON (builtins.readFile ./nix/sources.json);
22− fetch = sourceInfo:
23− builtins.fetchTarball { inherit (sourceInfo) url sha256; };
24− in builtins.mapAttrs (_: fetch) sourcesInfo;
16+ # Use a shim for pkgs that does not depend on `builtins.currentSystem`.
17+ sources = import ./nix/sources.nix {
18+ pkgs = { fetchzip = builtins.fetchTarball; };
19+ };
2520
2621 nixpkgsArgs = {
2722 inherit config;
modules/cabal-project.nix+13
@@ -8,6 +8,7 @@ let readIfExists = src: fileName:
88 then __readFile (origSrcDir + "/${fileName}")
99 else null;
1010in {
11+ _file = "haskell.nix/modules/cabal-project.nix";
1112 options = {
1213 # Used by callCabalProjectToNix
1314 name = mkOption {
@@ -136,5 +137,17 @@ in {
136137 type = nullOr (listOf unspecified);
137138 default = [];
138139 };
140+
141+ # Default shell arguments
142+ shell = mkOption {
143+ # TODO make this a submodule
144+ type = unspecified;
145+ default = {};
146+ description = ''
147+ Arguments to use for the default shell `p.shell` (these are passed to p.shellFor).
148+ For instance to include `cabal` and `ghcjs` support use
149+ shell = { tools.cabal = {}; crossPlatforms = p: [ p.ghcjs ]; }
150+ '';
151+ };
139152 };
140153}
modules/stack-project.nix+13
@@ -2,6 +2,7 @@
22with lib;
33with types;
44{
5+ _file = "haskell.nix/modules/stack-project.nix";
56 options = {
67 # Used by callStackToNix
78 name = mkOption {
@@ -108,5 +109,17 @@ with types;
108109 default = null;
109110 description = "Deprecated in favour of `compiler-nix-name`";
110111 };
112+
113+ # Default shell arguments
114+ shell = mkOption {
115+ # TODO make this a submodule
116+ type = unspecified;
117+ default = {};
118+ description = ''
119+ Arguments to use for the default shell `p.shell` (these are passed to p.shellFor).
120+ For instance to include `cabal` and `ghcjs` support use
121+ shell = { tools.cabal = {}; crossPlatforms = p: [ p.ghcjs ]; }
122+ '';
123+ };
111124 };
112125}
overlays/haskell.nix+52−33
@@ -543,6 +543,9 @@ final: prev: {
543543 final.lib.fix (project':
544544 let project = project' // { recurseForDerivations = false; };
545545 in rawProject // rec {
546+ # It is often handy to be able to get nix pkgs from the project.
547+ pkgs = final;
548+ # Haskell packages
546549 hsPkgs = final.lib.mapAttrs (packageName: package':
547550 if package' == null
548551 then null
@@ -648,6 +651,9 @@ final: prev: {
648651 inputsFrom = args'.inputsFrom or [] ++ crossShells;
649652 });
650653
654+ # Default shell
655+ shell = shellFor rawProject.args.shell;
656+
651657 # Like `.hsPkgs.${packageName}` but when compined with `getComponent` any
652658 # cabal configure errors are defered until the components derivation builds.
653659 getPackage = packageName:
@@ -697,51 +703,64 @@ final: prev: {
697703 # `checks` and `apps` output attributes.
698704 flake = {
699705 packages ? haskellLib.selectProjectPackages
706+ , crossPlatforms ? p: []
700707 }:
701− let packageNames = builtins.attrNames (packages project.hsPkgs);
708+ let packageNames = project: builtins.attrNames (packages project.hsPkgs);
709+ packagesForProject = prefix: project:
710+ final.lib.concatMap (packageName:
711+ let package = project.hsPkgs.${packageName};
712+ in final.lib.optional (package.components ? library)
713+ { name = "${prefix}${packageName}:lib:${packageName}"; value = package.components.library; }
714+ ++ final.lib.mapAttrsToList (n: v:
715+ { name = "${prefix}${packageName}:lib:${n}"; value = v; })
716+ (package.components.sublibs)
717+ ++ final.lib.mapAttrsToList (n: v:
718+ { name = "${prefix}${packageName}:exe:${n}"; value = v; })
719+ (package.components.exes)
720+ ++ final.lib.mapAttrsToList (n: v:
721+ { name = "${prefix}${packageName}:test:${n}"; value = v; })
722+ (package.components.tests)
723+ ) (packageNames project);
724+ checksForProject = prefix: project:
725+ final.lib.concatMap (packageName:
726+ let package = project.hsPkgs.${packageName};
727+ in final.lib.mapAttrsToList (n: v:
728+ { name = "${packageName}:test:${n}"; value = v; })
729+ (final.lib.filterAttrs (_: v: final.lib.isDerivation v) (package.checks))
730+ ) (packageNames project);
731+ appsForProject = prefix: project:
732+ final.lib.concatMap (packageName:
733+ let package = project.hsPkgs.${packageName};
734+ in final.lib.mapAttrsToList (n: v:
735+ { name = "${packageName}:exe:${n}"; value = { type = "app"; program = v.exePath; }; })
736+ (package.components.exes)
737+ ++ final.lib.mapAttrsToList (n: v:
738+ { name = "${packageName}:test:${n}"; value = { type = "app"; program = v.exePath; }; })
739+ (package.components.tests)
740+ ) (packageNames project);
741+ attrsForAllProjects = f: builtins.listToAttrs (
742+ f "" project
743+ ++ final.lib.concatMap (project:
744+ f (project.pkgs.stdenv.hostPlatform.config + ":") project)
745+ (crossPlatforms project.projectCross)
746+ );
702747 in {
703748 # Used by:
704749 # `nix build .#pkg-name:lib:pkg-name`
705750 # `nix build .#pkg-name:lib:sublib-name`
706751 # `nix build .#pkg-name:exe:exe-name`
707752 # `nix build .#pkg-name:test:test-name`
708− packages = builtins.listToAttrs (
709− final.lib.concatMap (packageName:
710− let package = project.hsPkgs.${packageName};
711− in final.lib.optional (package.components ? library)
712− { name = "${packageName}:lib:${packageName}"; value = package.components.library; }
713− ++ final.lib.mapAttrsToList (n: v:
714− { name = "${packageName}:lib:${n}"; value = v; })
715− (package.components.sublibs)
716− ++ final.lib.mapAttrsToList (n: v:
717− { name = "${packageName}:exe:${n}"; value = v; })
718− (package.components.exes)
719− ++ final.lib.mapAttrsToList (n: v:
720− { name = "${packageName}:test:${n}"; value = v; })
721− (package.components.tests)
722− ) packageNames);
753+ packages = attrsForAllProjects packagesForProject;
723754 # Used by:
724755 # `nix check .#pkg-name:test:test-name`
725− checks = builtins.listToAttrs (
726− final.lib.concatMap (packageName:
727− let package = project.hsPkgs.${packageName};
728− in final.lib.mapAttrsToList (n: v:
729− { name = "${packageName}:test:${n}"; value = v; })
730− (final.lib.filterAttrs (_: v: final.lib.isDerivation v) (package.checks))
731− ) packageNames);
756+ checks = attrsForAllProjects checksForProject;
732757 # Used by:
733758 # `nix run .#pkg-name:exe:exe-name`
734759 # `nix run .#pkg-name:test:test-name`
735− apps = builtins.listToAttrs (
736− final.lib.concatMap (packageName:
737− let package = project.hsPkgs.${packageName};
738− in final.lib.mapAttrsToList (n: v:
739− { name = "${packageName}:exe:${n}"; value = { type = "app"; program = v.exePath; }; })
740− (package.components.exes)
741− ++ final.lib.mapAttrsToList (n: v:
742− { name = "${packageName}:test:${n}"; value = { type = "app"; program = v.exePath; }; })
743− (package.components.tests)
744− ) packageNames);
760+ apps = attrsForAllProjects appsForProject;
761+ # Used by:
762+ # `nix develop`
763+ devShell = project.shell;
745764 };
746765 inherit (rawProject.hsPkgs) makeConfigFiles ghcWithHoogle ghcWithPackages;
747766 });