biglybt: 3.5.0.0 -> 3.6.0.0
[NixPkgs.git] / pkgs / development / tools / haskell / haskell-language-server / withWrapper.nix
blob14cc0760be222fbd191c87b73291f360c186ef49
1 { lib
2 , stdenv
3 , haskellPackages
4 , haskell
6 # Which GHC versions this hls can support.
7 # These are looked up in nixpkgs as `pkgs.haskell.packages."ghc${version}`.
8 # Run
9 #  $ nix-instantiate --eval -E 'with import <nixpkgs> {}; builtins.attrNames pkgs.haskell.packages'
10 # to list for your nixpkgs version.
11 , supportedGhcVersions ? [ "96" ]
13 # Whether to build hls with the dynamic run-time system.
14 # See https://haskell-language-server.readthedocs.io/en/latest/troubleshooting.html#static-binaries for more information.
15 , dynamic ? true
17 # Which formatters are supported. Pass `[]` to remove all formatters.
19 # Maintainers: if a new formatter is added, add it here and down in knownFormatters
20 , supportedFormatters ? [ "ormolu" "fourmolu" "floskell" "stylish-haskell" ]
23 # make sure the user only sets GHC versions that actually exist
24 assert supportedGhcVersions != [];
25 assert
26   lib.asserts.assertEachOneOf
27     "supportedGhcVersions"
28     supportedGhcVersions
29     (lib.pipe haskell.packages [
30       lib.attrNames
31       (lib.filter (lib.hasPrefix "ghc"))
32       (map (lib.removePrefix "ghc"))
33     ]);
35 let
36   # A mapping from formatter name to
37   # - cabal flag to disable
38   # - formatter-specific packages that can be stripped from the build of hls if it is disabled
39   knownFormatters = {
40     ormolu = {
41       cabalFlag = "ormolu";
42       packages = [
43         "hls-ormolu-plugin"
44       ];
45     };
46     fourmolu = {
47       cabalFlag = "fourmolu";
48       packages = [
49         "hls-fourmolu-plugin"
50       ];
51     };
52     floskell = {
53       cabalFlag = "floskell";
54       packages = [
55         "hls-floskell-plugin"
56       ];
57     };
58     stylish-haskell = {
59       cabalFlag = "stylishhaskell";
60       packages = [
61         "hls-stylish-haskell-plugin"
62       ];
63     };
64   };
68 # make sure any formatter that is set is actually supported by us
69 assert
70   lib.asserts.assertEachOneOf
71     "supportedFormatters"
72     supportedFormatters
73     (lib.attrNames knownFormatters);
76 # The recommended way to override this package is
78 # pkgs.haskell-language-server.override { supportedGhcVersions = [ "90" "92"]; }
80 # for example. Read more about this in the haskell-language-server section of the nixpkgs manual.
82 let
83   inherit (haskell.lib.compose)
84     justStaticExecutables
85     overrideCabal
86     enableCabalFlag
87     disableCabalFlag
88     ;
90   getPackages = version: haskell.packages."ghc${version}";
92   # Given the list of `supportedFormatters`, remove every formatter that we know of (knownFormatters)
93   # by disabling the cabal flag and also removing the formatter libraries.
94   removeUnnecessaryFormatters =
95     let
96       # only formatters that were not requested
97       unwanted = lib.pipe knownFormatters [
98         (lib.filterAttrs (fmt: _: ! (lib.elem fmt supportedFormatters)))
99         lib.attrsToList
100       ];
101       # all flags to disable
102       flags = map (fmt: fmt.value.cabalFlag) unwanted;
103       # all dependencies to remove from hls
104       deps = lib.concatMap (fmt: fmt.value.packages) unwanted;
106       # remove nulls from a list
107       stripNulls = lib.filter (x: x != null);
109       # remove all unwanted dependencies of formatters we don’t want
110       stripDeps = overrideCabal (drv: {
111         libraryHaskellDepends = lib.pipe (drv.libraryHaskellDepends or []) [
112           # the existing list may contain nulls, so let’s strip them first
113           stripNulls
114           (lib.filter (dep: ! (lib.elem dep.pname deps)))
115         ];
116       });
118     in drv: lib.pipe drv ([stripDeps] ++ map disableCabalFlag flags);
120   tunedHls = hsPkgs:
121     lib.pipe hsPkgs.haskell-language-server ([
122       (haskell.lib.compose.overrideCabal (old: {
123         enableSharedExecutables = dynamic;
124         ${if !dynamic then "postInstall" else null} = ''
125           ${old.postInstall or ""}
127           remove-references-to -t ${hsPkgs.ghc} $out/bin/haskell-language-server
128         '';
129       }))
130       ((if dynamic then enableCabalFlag else disableCabalFlag) "dynamic")
131       removeUnnecessaryFormatters
132     ]
133     ++ lib.optionals (!dynamic) [
134       justStaticExecutables
135     ]);
137   targets = version:
138     let packages = getPackages version;
139     in [ "haskell-language-server-${packages.ghc.version}" ];
141   makeSymlinks = version:
142     lib.concatMapStringsSep "\n"
143       (x:
144         "ln -s ${
145           tunedHls (getPackages version)
146         }/bin/haskell-language-server $out/bin/${x}")
147       (targets version);
149 in stdenv.mkDerivation {
150   pname = "haskell-language-server";
151   version = haskellPackages.haskell-language-server.version;
153   buildCommand = ''
154     mkdir -p $out/bin
155     ln -s ${tunedHls (getPackages (builtins.head supportedGhcVersions))}/bin/haskell-language-server-wrapper $out/bin/haskell-language-server-wrapper
156     ${lib.concatMapStringsSep "\n" makeSymlinks supportedGhcVersions}
157   '';
159   meta = haskellPackages.haskell-language-server.meta // {
160     maintainers = [ lib.maintainers.maralorn ];
161     longDescription = ''
162       This package provides the executables ${
163         lib.concatMapStringsSep ", " (x: lib.concatStringsSep ", " (targets x))
164         supportedGhcVersions
165       } and haskell-language-server-wrapper.
166       You can choose for which ghc versions to install hls with pkgs.haskell-language-server.override { supportedGhcVersions = [ "90" "92" ]; }.
167     '';
168   };