on iko/ghcjs-patch-master help sign in
Add crossPlatforms arg to shellFor (#1089)

This makes it easier to get cross compilers for a project in a nix shell.

commit91adf5f97deb6cbc829867e17c20aff15b543a06 authorHamish Mackenzie <Hamish.Mackenzie@iohk.io> dateFri 16 Apr 2021, 17:50 (6 years ago) parent869272a
3 files changed+71−2
docs/reference/library.md+2−1 docs/tutorials/development.md+6 overlays/haskell.nix+63−1
docs/reference/library.md+2−1
@@ -165,7 +165,7 @@ Then feeding its result into [mkCabalProjectPkgSet](#mkcabalprojectpkgset) passi
165165| `shellFor` | Function | [`shellFor`](#shellfor) |
166166| `ghcWithHoogle` | Function | [`ghcWithHoogle`](#ghcwithhoogle) |
167167| `ghcWithPackages` | Function | [`ghcWithPackages`](#ghcwithpackages) |
168−| `projectCross` | Attrset | Like `pkgs.pkgsCross.X` from nixpkgs `p.projectCross.X` returns the project results for cross compilation to X. So `p.projectCross.ghcjs.hsPkgs` is the same as `hsPkgs` but compiled with ghcjs |
168+| `projectCross` | Attrset | Like `pkgs.pkgsCross.<system>` from nixpkgs `p.projectCross.<system>` returns the project results for cross compilation (where system is a member of nixpkgs lib.systems.examples). So `p.projectCross.ghcjs.hsPkgs` is the same as `hsPkgs` but compiled with ghcjs |
169169
170170## project, cabalProject and stackProject
171171
@@ -435,6 +435,7 @@ shellFor =
435435| `exactDeps` | Boolean | Prevents the Cabal solver from choosing any package dependency other than what are in the package set. |
436436| `tools` | Function | AttrSet of tools to make available e.g. `{ cabal = "3.2.0.0"; }` or `{ cabal = { version = "3.2.0.0"; }; }`. If an AttrSet is provided for a tool, the additional arguments will be passed to the function creating the derivation for that tool. So you can provide an `index-state` or a `materialized` argument like that `{ cabal = { version = "3.2.0.0"; index-state = "2020-10-30T00:00:00Z"; materialized = ./cabal.materialized; }; }` for example. You can specify and materialize the version of hoogle used to construct the hoogle index by including something like `{ hoogle = { version = "5.0.17.15"; index-state = "2020-05-31T00:00:00Z"; materialized = ./hoogle.materialized; }`. Uses a default version of hoogle if omitted. |
437437| `inputsFrom` | List | List of other shells to include in this one. The `buildInputs` and `nativeBuildInputs` of each will be included using [mkShell](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell).
438+| `crossPlatforms` | Function | Platform selection function for cross compilation targets to support eg. `ps: with ps; [ghcjs mingwW64]` (see nixpkgs lib.systems.examples for list of platform names). |
438439| `{ ... }` | Attrset | All the other arguments are passed to [`mkDerivation`](https://nixos.org/nixpkgs/manual/#sec-using-stdenv). |
439440
440441**Return value**: a derivation
docs/tutorials/development.md+6
@@ -62,6 +62,12 @@ in
6262 # Some you may need to get some other way.
6363 buildInputs = [ (import <nixpkgs> {}).git ];
6464
65+ # Sellect cross compilers to include.
66+ crossPlatforms = ps: with ps; [
67+ ghcjs # Adds support for `js-unknown-ghcjs-cabal build` in the shell
68+ # mingwW64 # Adds support for `x86_64-W64-mingw32-cabal build` in the shell
69+ ];
70+
6571 # Prevents cabal from choosing alternate plans, so that
6672 # *all* dependencies are provided by Nix.
6773 exactDeps = true;
overlays/haskell.nix+63−1
@@ -582,10 +582,72 @@ final: prev: {
582582
583583 projectCoverageReport = haskellLib.projectCoverageReport project (map (pkg: pkg.coverageReport) (final.lib.attrValues (haskellLib.selectProjectPackages hsPkgs)));
584584
585+ # `projectCross` is like `pkgsCross`, but for haskell.nix projects.
586+ # To get a cross platform version of the project use
587+ # `projectCross.<system>` where system is a member of nixpkgs lib.systems.examples.
588+ # See https://nixos.wiki/wiki/Cross_Compiling
585589 projectCross = (final.lib.mapAttrs (_: pkgs:
586590 rawProject.projectFunction pkgs.haskell-nix rawProject.projectModule
587591 ) final.pkgsCross) // { recurseForDerivations = false; };
588592
593+ # Add support for passing in `crossPlatforms` argument.
594+ # crossPlatforms is an easy way to include the inputs for a basic
595+ # cross platform shell in a native shell.
596+ #
597+ # For instance if `default.nix` is a project, then `shell.nix` can be:
598+ # (import ./. {}).shellFor {
599+ # tools.cabal = {};
600+ # crossPlatforms = p: [ p.ghcjs ];
601+ # }
602+ #
603+ # This adds support for compiling with ghcjs. To build use the cabal wrapper:
604+ # js-unknown-ghcjs-cabal build all
605+ #
606+ # ## How it Works
607+ #
608+ # The cross compilation shells are made using the `projectCross` attribute
609+ # to get the selected cross compilation projects (e.g. project.projectCross.ghcjs).
610+ #
611+ # The `shellFor` function for those projects is called with arguments based on the
612+ # ones used for the main shell (the `withHoogle` argument is set to `false`).
613+ #
614+ # These shells are added to the main shell using the `inputsFrom` argument.
615+ #
616+ # Without `crossPlatforms` the above example would be:
617+ # let project = import ./. {};
618+ # in project.shellFor {
619+ # tools.cabal = {};
620+ # inputsFrom = [
621+ # (project.platformCross.ghcjs.shellFor { withHoogle = false; })
622+ # ];
623+ # }
624+ #
625+ shellFor = shellArgs:
626+ let
627+ # These are the args we will pass to the main shell.
628+ args' = builtins.removeAttrs shellArgs [ "crossPlatforms" ];
629+ # These are the args we will pass to the shells for the corss compiler
630+ argsCross =
631+ # These things should match main shell
632+ final.lib.filterAttrs (n: _: builtins.elem n [
633+ "packages" "components" "additional" "exactDeps" "packageSetupDeps"
634+ ]) shellArgs // {
635+ # The main shell's hoogle will probably be faster to build.
636+ withHoogle = false;
637+ };
638+ # These are the cross compilation versions of the project we will include.
639+ selectedCrossProjects =
640+ if shellArgs ? crossPlatforms
641+ then shellArgs.crossPlatforms projectCross
642+ else [];
643+ # Shells for cross compilation
644+ crossShells = builtins.map (project: project.shellFor argsCross)
645+ selectedCrossProjects;
646+ in rawProject.hsPkgs.shellFor (args' // {
647+ # Add inputs from the cross compilation shells
648+ inputsFrom = args'.inputsFrom or [] ++ crossShells;
649+ });
650+
589651 # Like `.hsPkgs.${packageName}` but when compined with `getComponent` any
590652 # cabal configure errors are defered until the components derivation builds.
591653 getPackage = packageName:
@@ -681,7 +743,7 @@ final: prev: {
681743 (package.components.tests)
682744 ) packageNames);
683745 };
684− inherit (rawProject.hsPkgs) makeConfigFiles ghcWithHoogle ghcWithPackages shellFor;
746+ inherit (rawProject.hsPkgs) makeConfigFiles ghcWithHoogle ghcWithPackages;
685747 });
686748
687749 cabalProject = args: let p = cabalProject' args;