-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdefault.nix
410 lines (372 loc) · 14.4 KB
/
default.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
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# See TODO nix: for current status.
# Run tools/cachix-push to update the cache.
# Examples:
# nix-shell --attr buildEnv --run '$setup'
# or tools/nix-enter
# nix build -L -f default.nix buildEnv
#
# nix-instantiate default.nix -A ghc.aeson
# Building lilypond drags in all of texlive. It's also marked broken on
# darwin for 19.09.
{ withLilypond ? false
, withEkg ? false # ekg is really heavy
, withDocs ? false # deps to build documentation
, withDevelopment ? false # include some binaries that I use during development
, useSystemCc ? false # if false use the nixpkgs c++ compiler
, useSystemSupercollider ? true # if false use one declared here
, useGhcVersion ? "9.2"
# Enable profiling in hackage libraries. Generally we want this to be able to
# profile, but it's much faster to build without it.
, profiling ? true
# Whether to do auto-scc stuff in hackage. I prefer manual SCCs since auto
# ones defeat inlining and change performance too much, but it can be useful
# to see into hackage libraries sometimes.
# https://cabal.readthedocs.io/en/3.4/cabal-project.html#cfg-field-profiling-detail
, profilingDetail ? "none"
, isCi ? false
}:
let
nixpkgs = import nix/nixpkgs.nix { inherit config; };
nixpkgs-orig = import nix/nixpkgs.nix {};
# Some things must use system versions, not my pinned versions.
# However in CI, there is no system, or rather it's whatever version of
# nixpkgs the github action uses, and I don't want to be broken by that.
nixpkgs-sys = if isCi then nixpkgs else import <nixpkgs> {};
hackage = import nix/hackage.nix {
inherit ghcVersion profilingDetail;
inherit profiling;
# I could do this to reduce builds in CI, but then it makes it miss the
# cache I use for development.
# profiling = if isCi then false else profiling;
};
faust = import nix/faust.nix {};
inherit (nixpkgs) lib;
nixpkgsVersion = builtins.head
(builtins.match "([0-9]+\\.[0-9]+).*" nixpkgs.lib.version);
# I don't think all these old nixpkgs versions still work, due to
# hackage deps not in nix/hackage.
nixGhcVersions = {
"20.09" = { "8.10" = "8.10.3"; };
"21.11" = {
"8.10" = "8.10.7";
"9.2" = "9.2.1";
};
"22.11" = {
"9.2" = "9.2.5";
"9.4" = "9.4.3"; # TODO untested, probably doesn't work
};
"23.11" = {
"9.2" = "9.2.8";
"9.4" = "9.4.8"; # TODO untested, probably doesn't work
};
};
ghcVersionDots =
let v = nixGhcVersions.${nixpkgsVersion}.${useGhcVersion} or null;
in if v != null then v
else abort "ghc ${useGhcVersion} not in nixpkgs ${nixpkgsVersion}";
ghcVersion = "ghc" + builtins.replaceStrings ["."] [""] ghcVersionDots;
ghc = nixpkgs.haskell.packages.${ghcVersion};
# This should just hit the nixos cache. The benefit is that it won't reuse
# my pinned library versions, so I don't have to make sure they're
# compatible. The drawback is that it won't use my pinned library versions,
# so lots of more downloading.
haskellBinary = name: nixpkgs-orig.haskellPackages.${name};
# Minimal compile just for build-time binary deps.
sharedHaskellBinary = name: with nixpkgs.haskell.lib;
dontCheck (disableLibraryProfiling
(disableExecutableProfiling ghc."${name}"));
config = {
# For nixpkgs.mkl, for mesh2faust.
allowUnfree = true;
packageOverrides = pkgs: {
haskell = pkgs.haskell // {
packages = pkgs.haskell.packages // {
"${ghcVersion}" = pkgs.haskell.packages.${ghcVersion}.override {
overrides = new: old: hackage.overrides old;
};
};
};
};
# Not working for some reason.
# overlays = [overlay];
};
# TODO: not used, couldn't get it to work
_overlay = nixpkgsSelf: nixpkgsSuper:
let
inherit (nixpkgsSelf) pkgs;
# pkgs = self.pkgs;
hsPkgs = nixpkgsSuper.haskell.packages.${ghcVersion}.override {
overrides = self: super: {
Diff = pkgs.haskell.lib.dontCheck (
self.callHackage "Diff" "0.4.0" {}
);
};
};
in {
haskell = nixpkgsSuper.haskell // {
packages = nixpkgsSuper.haskell.packages // {
"${ghcVersion}" = hsPkgs;
};
};
};
# util
guard = bool: list: if bool then list else [];
split = sep: str:
builtins.filter builtins.isString (builtins.split sep str);
lines = str: builtins.filter (s: s != "") (split "\n" str);
readLines = fn: lines (builtins.readFile fn);
hsBool = b: if b then "True" else "False";
inherit (nixpkgs.stdenv) isDarwin isLinux;
in rec {
# Put some things in here for convenience from `nix repl default.nix`.
inherit nixpkgs ghc hackage;
inherit nixpkgs-orig;
inherit nixpkgs-sys;
inherit (hackage) nixFiles;
jacks = {
# Make sure to compile against the system version of jack, not my pinned
# nixpkgs one. Jack apparently has no version control in the protocol, so
# version mismatches show up as random "Unknown request" junk. So I need
# the same one as the system. For nixos I can get it from <nixpkgs>, but
# for other distros I'll probably need to have a list of versions and
# manually pick the one that's the same as the system.
nixos = nixpkgs-sys.libjack2;
# Untested.
v1_9_22 = nixpkgs.libjack2.overrideAttrs (old: {
src = nixpkgs.fetchFromGitHub {
owner = "jackaudio";
repo = "jack2";
rev = "v1.9.22";
sha256 = "sha256-Cslfys5fcZDy0oee9/nM5Bd1+Cg4s/ayXjJJOSQCL4E=";
};
prePatch = "";
# svnversion_regenerate.sh doesn't seem to exist.
# postPatch = ''
# patchShebangs --build svnversion_regenerate.sh
# '';
});
};
# TODO: for non-nixos, have a way to choose 1.9.22, assuming the system uses
# that version? I don't have any non-nixos linux, or reasons to test on
# them, so I'll leave it here until such a system comes along.
libjack2 = jacks.nixos;
# This may be desirable to get a consistent supercollider, especially
# one with a consistent jack version. But the default is to assume
# there is already a system supercollider which works.
supercollider = nixpkgs.libsForQt512.callPackage nix/supercollider.nix {
fftw = nixpkgs.fftwSinglePrec;
useIDE = false;
inherit libjack2;
};
# nixpkgs.rubberband only works on linux.
rubberband = if isDarwin
then nixpkgs.callPackage nix/rubberband-darwin.nix {
inherit (nixpkgs.darwin.apple_sdk.frameworks)
Accelerate CoreGraphics CoreVideo;
}
else nixpkgs.rubberband;
# I want some unreleased fixes, for mousewheel and Fl_Image_Surface.
fltk =
let
commit = "84c09ae7b2de0ad9142551ebd4f53a7e113902b4";
name = "fltk-1.4-${commit}";
src = builtins.fetchGit {
url = "https://github.com/fltk/fltk.git";
rev = commit;
ref = "master";
};
# It's 21.11 but winds up being 21.11pre-git which is considered < 21.11
in if builtins.compareVersions lib.version "21.10" >= 0 then
(nixpkgs.fltk14-minimal.override {
withShared = false;
}).overrideAttrs (old: { inherit name src; })
else
nixpkgs.fltk14.overrideAttrs (old: {
inherit name src;
nativeBuildInputs = [nixpkgs.autoconf] ++ old.nativeBuildInputs;
# TODO The nixpkgs version has deps on GL, freetype, libtiff, which
# I think I can omit.
configureFlags = [];
# dontUseCmakeConfigure = true; # only necessary for new cmake build
});
hackageGhc =
let wantPkg = pkg:
# nix gets the "ghc" package confused with the compiler.
pkg != "ghc" ;
in ghc.ghcWithPackages (pkgs: map (pkg: pkgs."${pkg}") (
builtins.filter wantPkg (builtins.concatLists [
(readLines doc/cabal/nix-packages)
(guard withEkg ["ekg"])
])
));
midiDeps = if isLinux then [
# Make sure to compile against the system version of jack, not my pinned
# nixpkgs one. Jack apparently has no version control in the protocol,
# so version mismatches show up as random "Unknown request" junk.
libjack2
] else if isDarwin then (with nixpkgs.darwin.apple_sdk.frameworks; [
Cocoa
CoreAudio
CoreFoundation
CoreMIDI
]) else abort "not linux or darwin, don't know how to do midi";
# You always need these deps.
basicDeps = [
# fltk has to be in basicDeps, so it gets in buildEnv buildInputs, so the
# magic nix hook puts it in NIX_LDFLAGS, so the magic nix gcc wrapper puts
# the -L flag on.
fltk
hackageGhc
(sharedHaskellBinary "cpphs")
midiDeps
# Many scripts are in zsh, I can't be bothered to put ""s everywhere.
nixpkgs.zsh
] ++ guard isCi [
nixpkgs.coreutils # at least one test uses cat
] ++ guard (!useSystemCc) [
nixpkgs.stdenv.cc
] ++ guard (!useSystemSupercollider) [
supercollider
];
fontDeps = with nixpkgs; [
# I don't really use these, but there they are in case I do someday.
# noto-fonts
openlilylib-fonts.bravura
];
# Dependencies to actually use karya. CI can omit them.
interactiveDeps = fontDeps ++ [
nixpkgs.git
];
developmentDeps = [
# (sharedHaskellBinary "cabal-install") # needed for nix/c2n
# These haskell binaries will pull in a whole new ghc compiler because of
# the nixpkgs bug with dynamic linking.
(haskellBinary "fast-tags")
# (haskellBinary "weeder")
(haskellBinary "profiterole")
(haskellBinary "ghc-prof-flamegraph")
(haskellBinary "hp2html")
nixpkgs.ripgrep
];
docDeps = [
nixpkgs-orig.pandoc
];
libsamplerate = nixpkgs.stdenv.mkDerivation {
# libsamplerate with my patches to save and resume. The official one is
# nixpkgs.libsamplerate. I compile without libsndfile and none of the
# utils, so deps on e.g. CoreServices are not needed.
name = "libsamplerate-elaforge";
src = builtins.fetchGit {
url = "https://github.com/elaforge/libsamplerate.git";
rev = "cb783007e114531911ec4f2f081a27733c84b45c";
ref = "save-state";
};
nativeBuildInputs = with nixpkgs; [autoreconfHook pkgconfig];
configureFlags = ["--enable-shared=no" "--enable-static=yes"];
};
imDeps = [
faust.faust
libsamplerate
nixpkgs.libsndfile
nixpkgs.flac.dev nixpkgs.flac # libflac 1.3.3
rubberband
# This is a build dep, not a library dep.
ghc.c2hs
] ++ guard isLinux [
# TODO for some reason the nixpkgs depends on fftw, but doesn't put it in
# nix-support/propagated-build-inputs, which means the insane nixpkgs hooks
# magic doesn't get it into NIX_LDFLAGS, which means the gcc wrapper
# doesn't get the -L flag for it. See NOTE [nix-ldflags]
nixpkgs.fftw
];
mod_to_sexpr = nixpkgs.callPackage nix/mod_to_sexpr.nix {};
#### aggregate deps
deps = builtins.concatLists [
basicDeps
imDeps
(guard (!isCi) interactiveDeps)
(guard withDevelopment developmentDeps)
(guard withDocs docDeps)
(guard withLilypond [nixpkgs.lilypond])
];
generatedByNix = "-- Generated by nix, delete or this will be overwritten!";
# Make a nix-shell that can run `mkmk` and `mk`.
shakeConfig =
let
extraFrameworkPaths = if isDarwin then ''
-- nixpkgs bug on darwin: https://github.com/NixOS/nixpkgs/issues/24237
-- I previously used /System/Library/Frameworks, but it stopped working.
, extraFrameworkPaths =
["${nixpkgs.darwin.cf-private}/Library/Frameworks"]
''
else "";
in nixpkgs.writeText "ShakeConfig.hs" ''
${generatedByNix}
{-# OPTIONS_GHC -Wno-unused-imports #-}
module Local.ShakeConfig where
import qualified Shake.C as C
import Shake.Config
localConfig = defaultConfig
{ useCabalV2 = False -- we're using nix, not cabal
, enableEkg = ${hsBool withEkg}
${extraFrameworkPaths}
}
'';
buildEnv = nixpkgs.stdenv.mkDerivation {
name = "buildEnv";
builder = "${nixpkgs.bash}/bin/bash";
# TODO I use this with nix-shell, which doesn't run the build, so this is a
# placeholder that just keeps the deps as GC roots. In the future this
# could do a `mkmk && mk typecheck` or something, and run in CI. It can't
# do that because it doesn't have any of the srcs. I'm not sure the best
# way to get those, perhaps a builtins.filterSource on ./. for *.hs, and
# then link those into the build dir? This would make a non-incremental CI
# though, which would be really inefficient, or maybe I can just cache the
# build directory, and have shake use fingerprints instead of mtime.
args = ["-eu" (builtins.toFile "buildEnv-builder.sh" ''
$coreutils/bin/mkdir -p $out/nix-support
echo "$buildInputs" >$out/nix-support/deps
'')];
# srcs = ... TODO
coreutils = nixpkgs.coreutils;
# These wind up in PATH in nix-shell, since it runs $stdenv/setup.
buildInputs = deps;
# The ghc generated by nix doesn't need this, but GHC API as run by seq
# does.
GHC_PACKAGE_PATH = "${hackageGhc}/lib/ghc-${ghcVersionDots}/package.conf.d";
# tools/nix-enter will run this.
shellHook = nixpkgs.writeScript "setup.sh" ''
# Don't replace an explicit config.
cfg=Local/ShakeConfig.hs
if [[ ! -e $cfg || "$(head -1 $cfg)" = "${generatedByNix}" ]]; then
if ! cmp --silent ${shakeConfig} $cfg; then
echo Adding generated $cfg
# I do cp instead of link so that shake, which uses mtimes, will
# notice that it changes. Shake shouldn't use mtimes, but
# unfortunately ghci uses mtimes, so I have to configure shake to do
# that too.
cp -f ${shakeConfig} $cfg
fi
else
echo "not replacing since not generated by nix: $cfg"
fi
'';
};
}
# NOTE [nix-ldflags]
#
# $stdenv/setup is supposed to collect -L flags for depended-on libraries and
# stuff them into $NIX_LDFLAGS. If you use the nixpkgs "wrapped" gcc, it will
# then inject that into its commandline. How this works (I think):
#
# . nix-support/setup-hook is run for all deps. gcc-wrapper has one that
# adds a ccWrapper_addCVars function to the set of "env hooks".
# binutil-wrapper adds bintoolsWrapper_addLDVars.
# . Each input, if it has nix-support/propagated-build-inputs, chases down
# all transitive deps, and runs all the hooks on them.
# . bintoolsWrapper_addLDVars just looks for a `lib` subdir and stuffs it in
# NIX_LDFLAGS.
# . Wrapped gcc sees that etc.
#
# There is apparently some other magic that puts things in
# propagated-build-inputs, and it sometimes doesn't work.