forked from haskell/haskell-language-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flake.nix
384 lines (348 loc) · 16.2 KB
/
flake.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# Maintaining this file:
#
# - Bump the inputs version using `nix flake update`
# - Edit `sourceDirs` to update the set of local packages
#
# For more details: https://nixos.wiki/wiki/Flakes
{
description = "haskell language server flake";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
flake-utils.url = "github:numtide/flake-utils";
pre-commit-hooks = {
url = "github:cachix/pre-commit-hooks.nix";
};
gitignore = {
url = "github:hercules-ci/gitignore.nix";
flake = false;
};
# List of hackage dependencies
lsp = {
url = "https://hackage.haskell.org/package/lsp-1.4.0.0/lsp-1.4.0.0.tar.gz";
flake = false;
};
lsp-types = {
url = "https://hackage.haskell.org/package/lsp-types-1.4.0.1/lsp-types-1.4.0.1.tar.gz";
flake = false;
};
lsp-test = {
url = "https://hackage.haskell.org/package/lsp-test-0.14.0.2/lsp-test-0.14.0.2.tar.gz";
flake = false;
};
ghc-exactprint = {
url = "https://hackage.haskell.org/package/ghc-exactprint-1.4.1/ghc-exactprint-1.4.1.tar.gz";
flake = false;
};
constraints-extras = {
url = "https://hackage.haskell.org/package/constraints-extras-0.3.2.1/constraints-extras-0.3.2.1.tar.gz";
flake = false;
};
retrie = {
url = "https://hackage.haskell.org/package/retrie-1.2.0.1/retrie-1.2.0.1.tar.gz";
flake = false;
};
fourmolu = {
url = "https://hackage.haskell.org/package/fourmolu-0.5.0.1/fourmolu-0.5.0.1.tar.gz";
flake = false;
};
hlint = {
url = "https://hackage.haskell.org/package/hlint-3.3.6/hlint-3.3.6.tar.gz";
flake = false;
};
implicit-hie-cradle = {
url = "https://hackage.haskell.org/package/implicit-hie-cradle-0.3.0.5/implicit-hie-cradle-0.3.0.5.tar.gz";
flake = false;
};
hie-bios = {
url = "https://hackage.haskell.org/package/hie-bios-0.9.1/hie-bios-0.9.1.tar.gz";
flake = false;
};
};
outputs =
inputs@{ self, nixpkgs, flake-compat, flake-utils, pre-commit-hooks, gitignore, ... }:
{
overlay = final: prev:
with prev;
let
haskellOverrides = hself: hsuper: {
# we override mkDerivation here to apply the following
# tweak to each haskell package:
# if the package is broken, then we disable its check and relax the cabal bounds;
# otherwise, we leave it unchanged.
# hopefully, this could fix packages marked as broken by nix due to check failures
# or the build failure because of tight cabal bounds
mkDerivation = args:
let
broken = args.broken or false;
check = args.doCheck or true;
jailbreak = args.jailbreak or false;
in hsuper.mkDerivation (args // {
jailbreak = if broken then true else jailbreak;
doCheck = if broken then false else check;
});
};
gitignoreSource = (import gitignore { inherit lib; }).gitignoreSource;
# List all subdirectories under `./plugins`, except `./plugins/default`
pluginsDir = ./plugins;
pluginSourceDirs = builtins.removeAttrs (lib.mapAttrs'
(name: _: lib.nameValuePair name (pluginsDir + ("/" + name)))
(builtins.readDir pluginsDir)) [ "default" ];
# Source directories of our packages, should be consistent with cabal.project
sourceDirs = {
haskell-language-server = ./.;
ghcide = ./ghcide;
hls-graph = ./hls-graph;
shake-bench = ./shake-bench;
hie-compat = ./hie-compat;
hls-plugin-api = ./hls-plugin-api;
hls-test-utils = ./hls-test-utils;
} // pluginSourceDirs;
# Tweak our packages
# Don't use `callHackage`, it requires us to override `all-cabal-hashes`
tweaks = hself: hsuper:
with haskell.lib; {
# Patches don't apply
github = overrideCabal hsuper.github (drv: { patches = []; });
# GHCIDE requires hie-bios ^>=0.9.1
hie-bios = hself.callCabal2nix "hie-bios" inputs.hie-bios {};
# We need an older version
hiedb = hself.hiedb_0_4_1_0;
lsp = hsuper.callCabal2nix "lsp" inputs.lsp {};
lsp-types = hsuper.callCabal2nix "lsp-types" inputs.lsp-types {};
lsp-test = hsuper.callCabal2nix "lsp-test" inputs.lsp-test {};
implicit-hie-cradle = hself.callCabal2nix "implicit-hie-cradle" inputs.implicit-hie-cradle {};
# https://github.com/NixOS/nixpkgs/issues/140774
ormolu =
if final.system == "aarch64-darwin"
then overrideCabal hsuper.ormolu (_: { enableSeparateBinOutput = false; })
else hsuper.ormolu;
};
hlsSources =
builtins.mapAttrs (_: dir: gitignoreSource dir) sourceDirs;
extended = hpkgs:
(hpkgs.override (old: {
overrides = lib.composeExtensions (old.overrides or (_: _: { }))
haskellOverrides;
})).extend (hself: hsuper:
# disable all checks for our packages
builtins.mapAttrs (_: drv: haskell.lib.dontCheck drv)
(lib.composeExtensions
(haskell.lib.packageSourceOverrides hlsSources) tweaks hself
hsuper));
in {
inherit hlsSources;
# Haskell packages extended with our packages
hlsHpkgs = compiler: extended haskell.packages.${compiler};
# Support of GenChangelogs.hs
gen-hls-changelogs = hpkgs:
let myGHC = hpkgs.ghcWithPackages (p: with p; [ github ]);
in runCommand "gen-hls-changelogs" {
passAsFile = [ "text" ];
preferLocalBuild = true;
allowSubstitutes = false;
buildInputs = [ git myGHC ];
} ''
dest=$out/bin/gen-hls-changelogs
mkdir -p $out/bin
echo "#!${runtimeShell}" >> $dest
echo "${myGHC}/bin/runghc ${./GenChangelogs.hs}" >> $dest
chmod +x $dest
'';
};
} // (flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ])
(system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ self.overlay ];
config = { allowBroken = true; };
};
# Pre-commit hooks to run stylish-haskell
pre-commit-check = hpkgs: pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = {
stylish-haskell.enable = true;
# use stylish-haskell with our target ghc
stylish-haskell.entry = pkgs.lib.mkForce "${hpkgs.stylish-haskell}/bin/stylish-haskell --inplace";
stylish-haskell.excludes = [
# Ignored files
"^Setup.hs$"
"test/testdata/.*$"
"test/data/.*$"
"test/manual/lhs/.*$"
"^hie-compat/.*$"
"^plugins/hls-tactics-plugin/.*$"
# Temporarily ignored files
# Stylish-haskell (and other formatters) does not work well with some CPP usages in these files
"^ghcide/src/Development/IDE/GHC/Compat.hs$"
"^ghcide/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs$"
"^ghcide/src/Development/IDE/GHC/Compat/Core.hs$"
"^ghcide/src/Development/IDE/Spans/Pragmas.hs$"
"^ghcide/src/Development/IDE/LSP/Outline.hs$"
"^plugins/hls-splice-plugin/src/Ide/Plugin/Splice.hs$"
"^ghcide/test/exe/Main.hs$"
"ghcide/src/Development/IDE/Core/Rules.hs"
"^hls-test-utils/src/Test/Hls/Util.hs$"
];
};
};
ghc901Config = (import ./configuration-ghc-901.nix) { inherit pkgs; };
ghc921Config = (import ./configuration-ghc-921.nix) { inherit pkgs inputs; };
# GHC versions
ghcDefault = pkgs.hlsHpkgs ("ghc"
+ pkgs.lib.replaceStrings [ "." ] [ "" ]
pkgs.haskellPackages.ghc.version);
ghc884 = pkgs.hlsHpkgs "ghc884";
ghc8107 = pkgs.hlsHpkgs "ghc8107";
ghc901 = ghc901Config.tweakHpkgs (pkgs.hlsHpkgs "ghc901");
ghc921 = ghc921Config.tweakHpkgs (pkgs.hlsHpkgs "ghc921");
# For markdown support
myst-parser = pkgs.python3Packages.callPackage ./myst-parser.nix {};
sphinx_rtd_theme = pkgs.python3Packages.sphinx_rtd_theme.overrideAttrs (oldAttrs: {
# For https://github.com/readthedocs/sphinx_rtd_theme/pull/1185, otherwise lists are broken locally
src = pkgs.fetchFromGitHub {
owner = "readthedocs";
repo = "sphinx_rtd_theme";
rev = "34f81daaf52466366c80003db293d50075c1b896";
sha256 = "0rkrsvvqr6g2p3v5vq88jhfp5sd0r1jqjh3vc5y26jn30z8s4fkz";
};
});
pythonWithPackages = pkgs.python3.withPackages (ps: [ps.sphinx myst-parser sphinx_rtd_theme ps.pip]);
docs = pkgs.stdenv.mkDerivation {
name = "hls-docs";
src = pkgs.lib.sourceFilesBySuffices ./. [ ".py" ".rst" ".md" ".png" ".gif" ".svg" ".cabal" ];
buildInputs = [ pythonWithPackages ];
# -n gives warnings on missing link targets, -W makes warnings into errors
buildPhase = ''cd docs; sphinx-build -n -W . $out'';
dontInstall = true;
};
mkDevShell = hpkgs: cabalProject: with pkgs; mkShell {
name = "haskell-language-server-dev-ghc${hpkgs.ghc.version}";
# For theses tools packages, we use ghcDefault
# This removes a rebuild with a different GHC version
# Theses programs are tools, used as binary, independently of the
# version of GHC.
# The drawback of this approach is that our shell may pull two GHC
# version in scope (the default one, and the one defined in
# `hpkgs`.)
# The advantage is that we won't have to rebuild theses tools (and
# dependencies) with a recent GHC which may not be supported by
# them.
buildInputs = [
# our compiling toolchain
hpkgs.ghc
pkgs.cabal-install
# @guibou: I'm not sure hie-bios is needed
ghcDefault.hie-bios
# Dependencies needed to build some parts of hackage
gmp zlib ncurses
# Changelog tooling
(gen-hls-changelogs ghcDefault)
# For the documentation
pythonWithPackages
# @guibou: I'm not sure this is needed.
hlint
ghcDefault.opentelemetry-extra
capstone tracy
# ormolu
# stylish-haskell
];
shellHook = ''
# @guibou: I'm not sure theses lines are needed
export LD_LIBRARY_PATH=${gmp}/lib:${zlib}/lib:${ncurses}/lib:${capstone}/lib
export DYLD_LIBRARY_PATH=${gmp}/lib:${zlib}/lib:${ncurses}/lib:${capstone}/lib
export PATH=$PATH:$HOME/.local/bin
# Enable the shell hooks
${(pre-commit-check ghcDefault).shellHook}
# If the cabal project file is not the default one.
# Print a warning and generate an alias.
if [ ${cabalProject} != "cabal.project" ]
then
echo "Cabal won't be able to build your project without using the project file "${cabalProject}", such as:"
echo " cabal --project-file=${cabalProject}"
echo "An alias "cabal_project" is available. Use it like:"
echo " cabal_project build"
alias cabal_project='cabal --project-file=${cabalProject}'
fi
'';
};
# Create a development shell of hls project
# See https://github.com/NixOS/nixpkgs/blob/5d4a430472cafada97888cc80672fab255231f57/pkgs/development/haskell-modules/make-package-set.nix#L319
mkDevShellWithNixDeps = hpkgs: cabalProject:
with pkgs;
let simpleShell = mkDevShell hpkgs cabalProject;
in
hpkgs.shellFor {
name = "haskell-language-server-dev-nix-ghc${hpkgs.ghc.version}";
inherit (simpleShell) shellHook buildInputs;
doBenchmark = true;
packages = p:
with builtins;
map (name: p.${name}) (attrNames
# Disable dependencies should not be part of the shell.
(removeAttrs hlsSources (hpkgs.hlsDisabledPlugins or [])));
src = null;
};
# Create a hls executable
# Copied from https://github.com/NixOS/nixpkgs/blob/210784b7c8f3d926b7db73bdad085f4dc5d79418/pkgs/development/tools/haskell/haskell-language-server/withWrapper.nix#L16
mkExe = hpkgs:
with pkgs.haskell.lib;
(enableSharedExecutables (overrideCabal hpkgs.haskell-language-server
(_: {
postInstall = ''
remove-references-to -t ${hpkgs.shake.data} $out/bin/haskell-language-server
remove-references-to -t ${hpkgs.js-jquery.data} $out/bin/haskell-language-server
remove-references-to -t ${hpkgs.js-dgtable.data} $out/bin/haskell-language-server
remove-references-to -t ${hpkgs.js-flot.data} $out/bin/haskell-language-server
'';
}))).overrideAttrs(old: {
pname = old.pname + "-ghc${hpkgs.ghc.version}";
});
in with pkgs; rec {
# Developement shell with only compiler
simpleDevShells = {
haskell-language-server-dev = mkDevShell ghcDefault "cabal.project";
haskell-language-server-884-dev = mkDevShell ghc884 "cabal.project";
haskell-language-server-8107-dev = mkDevShell ghc8107 "cabal.project";
haskell-language-server-901-dev = mkDevShell ghc901 "cabal-ghc90.project";
haskell-language-server-921-dev = mkDevShell ghc921 "cabal-ghc921.project";
};
# Developement shell, haskell packages are also provided by nix
nixDevShells = {
haskell-language-server-dev-nix = mkDevShellWithNixDeps ghcDefault "cabal.project";
haskell-language-server-884-dev-nix = mkDevShellWithNixDeps ghc884 "cabal.project";
haskell-language-server-8107-dev-nix = mkDevShellWithNixDeps ghc8107 "cabal.project";
haskell-language-server-901-dev-nix = mkDevShellWithNixDeps ghc901 "cabal-ghc90.project";
haskell-language-server-921-dev-nix = mkDevShellWithNixDeps ghc921 "cabal-ghc921.project";
};
allPackages = {
haskell-language-server = mkExe ghcDefault;
haskell-language-server-884 = mkExe ghc884;
haskell-language-server-8107 = mkExe ghc8107;
haskell-language-server-901 = mkExe ghc901;
haskell-language-server-921 = mkExe ghc921;
};
devShells = simpleDevShells // nixDevShells;
packages = allPackages // {
# See https://github.com/NixOS/nix/issues/5591
# nix flake cannot build a list/set of derivation in one command.
# Using a linkFarmFromDrvs, I'm creating a unique entry point to
# build all HLS versions.
# This is used in CI to test and populate cache for packages
# distributed using nix.
all-haskell-language-server = linkFarmFromDrvs "all-haskell-language-server" (lib.unique (builtins.attrValues allPackages));
# Same for all shells
# We try to build as much as possible, but not much shells are
# working (especially on darwing), so this list is limited.
all-nix-dev-shells = linkFarmFromDrvs "all-dev-shells" (builtins.map (shell: shell.inputDerivation) (lib.unique [nixDevShells.haskell-language-server-dev-nix]));
all-simple-dev-shells = linkFarmFromDrvs "all-dev-shells" (builtins.map (shell: shell.inputDerivation) (lib.unique (builtins.attrValues simpleDevShells)));
docs = docs;
};
defaultPackage = packages.haskell-language-server;
devShell = devShells.haskell-language-server-dev;
});
}