/
bootstrap.nix
168 lines (167 loc) · 7.38 KB
/
bootstrap.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
{ debug ? false, stage0debug ? false, extraCMakeFlags ? [],
stdenv, lib, cmake, gmp, gnumake, bash, buildLeanPackage, writeShellScriptBin, runCommand, symlinkJoin, lndir, perl,
... } @ args:
with builtins;
rec {
inherit stdenv;
buildCMake = args: stdenv.mkDerivation ({
nativeBuildInputs = [ cmake ];
buildInputs = [ gmp ];
# https://github.com/NixOS/nixpkgs/issues/60919
hardeningDisable = [ "all" ];
dontStrip = (args.debug or debug);
postConfigure = ''
patchShebangs .
'';
} // args // {
src = args.realSrc or (lib.sourceByRegex args.src [ "[a-z].*" "CMakeLists\.txt" ]);
cmakeFlags = (args.cmakeFlags or [ "-DSTAGE=1" "-DPREV_STAGE=./faux-prev-stage" "-DUSE_GITHASH=OFF" ]) ++ (args.extraCMakeFlags or extraCMakeFlags) ++ lib.optional (args.debug or debug) [ "-DCMAKE_BUILD_TYPE=Debug" ];
});
lean-bin-tools-unwrapped = buildCMake {
name = "lean-bin-tools";
outputs = [ "out" "leanc_src" ];
realSrc = lib.sourceByRegex ../src [ "CMakeLists\.txt" "bin.*" "include.*" ".*\.in" "Leanc\.lean" ];
preConfigure = ''
touch empty.cpp
sed -i 's/find_package.*//;s/add_subdirectory.*//;s/set(LEAN_OBJS.*/set(LEAN_OBJS empty.cpp)/' CMakeLists.txt
'';
dontBuild = true;
installPhase = ''
mkdir $out $leanc_src
mv bin/ include/ share/ $out/
mv leanc.sh $out/bin/leanc
mv leanc/Leanc.lean $leanc_src/
substituteInPlace $out/bin/leanc --replace '$root' "$out"
substituteInPlace $out/bin/leanmake --replace "make" "${gnumake}/bin/make"
substituteInPlace $out/share/lean/lean.mk --replace "/usr/bin/env bash" "${bash}/bin/bash"
'';
};
leancpp = buildCMake {
name = "leancpp";
src = ../src;
buildFlags = [ "leancpp" "leanrt" "leanrt_initial-exec" "shell" ];
installPhase = ''
mkdir -p $out
mv lib/ $out/
mv shell/CMakeFiles/shell.dir/lean.cpp.o $out/lib
mv runtime/libleanrt_initial-exec.a $out/lib
'';
};
# rename derivation so `nix run` uses the right executable name but we still see the stage in the build log
wrapStage = stage: runCommand "lean" {} ''
ln -s ${stage} $out
'';
stage0 = wrapStage (args.stage0 or (buildCMake {
name = "lean-stage0";
realSrc = ../stage0/src;
debug = stage0debug;
cmakeFlags = [ "-DSTAGE=0" ];
extraCMakeFlags = [];
preConfigure = ''
ln -s ${../stage0/stdlib} ../stdlib
'';
installPhase = ''
mkdir -p $out/bin $out/lib/lean
mv bin/lean $out/bin/
mv lib/lean/libleanshared.* $out/lib/lean
'' + lib.optionalString stdenv.isDarwin ''
for lib in $(otool -L $out/bin/lean | tail -n +2 | cut -d' ' -f1); do
if [[ "$lib" == *lean* ]]; then install_name_tool -change "$lib" "$out/lib/lean/$(basename $lib)" $out/bin/lean; fi
done
otool -L $out/bin/lean
'';
}));
stage = { stage, prevStage, self }:
let
desc = "stage${toString stage}";
build = args: buildLeanPackage.override {
lean = prevStage;
leanc = lean-bin-tools-unwrapped;
# use same stage for retrieving dependencies
lean-leanDeps = stage0;
lean-final = self;
} ({
src = ../src;
fullSrc = ../.;
inherit debug;
} // args);
in (all: all // all.lean) rec {
inherit (Lean) emacs-dev emacs-package vscode-dev vscode-package;
Init = build { name = "Init"; deps = []; };
Std = build { name = "Std"; deps = [ Init ]; };
Lean = build { name = "Lean"; deps = [ Init Std ]; };
stdlib = [ Init Std Lean ];
Leanpkg = build { name = "Leanpkg"; deps = stdlib; linkFlags = ["-L${gmp}/lib -L${leanshared}"]; };
extlib = stdlib ++ [ Leanpkg ];
Leanc = build { name = "Leanc"; src = lean-bin-tools-unwrapped.leanc_src; deps = stdlib; linkFlags = ["-L${gmp}/lib -L${leanshared}"]; };
stdlibLinkFlags = "-L${gmp}/lib -L${Init.staticLib} -L${Std.staticLib} -L${Lean.staticLib} -L${leancpp}/lib/lean";
leanshared = runCommand "leanshared" { buildInputs = [ stdenv.cc ]; } ''
mkdir $out
LEAN_CC=${stdenv.cc}/bin/cc ${lean-bin-tools-unwrapped}/bin/leanc -shared ${lib.optionalString stdenv.isLinux "-Bsymbolic"} \
${if stdenv.isDarwin then "-Wl,-force_load,${Init.staticLib}/libInit.a -Wl,-force_load,${Std.staticLib}/libStd.a -Wl,-force_load,${Lean.staticLib}/libLean.a -Wl,-force_load,${leancpp}/lib/lean/libleancpp.a ${leancpp}/lib/libleanrt_initial-exec.a -lc++"
else "-Wl,--whole-archive -lInit -lStd -lLean -lleancpp ${leancpp}/lib/libleanrt_initial-exec.a -Wl,--no-whole-archive -lstdc++"} -lm ${stdlibLinkFlags} \
-o $out/libleanshared${stdenv.hostPlatform.extensions.sharedLibrary}
'';
mods = Init.mods // Std.mods // Lean.mods;
leanc = writeShellScriptBin "leanc" ''
LEAN_CC=${stdenv.cc}/bin/cc ${Leanc.executable.withSharedStdlib}/bin/leanc -I${lean-bin-tools-unwrapped}/include ${stdlibLinkFlags} -L${leanshared} "$@"
'';
lean = runCommand "lean" {} ''
mkdir -p $out/bin
${leanc}/bin/leanc ${leancpp}/lib/lean.cpp.o ${leanshared}/* -o $out/bin/lean
'';
leanpkg = Leanpkg.executable.withSharedStdlib;
# derivation following the directory layout of the "basic" setup, mostly useful for running tests
lean-all = wrapStage(stdenv.mkDerivation {
name = "lean-${desc}";
buildCommand = ''
mkdir -p $out/bin $out/lib/lean
ln -sf ${leancpp}/lib/lean/* ${lib.concatMapStringsSep " " (l: "${l.modRoot}/* ${l.staticLib}/*") (lib.reverseList extlib)} $out/lib/lean/
# put everything in a single final derivation so `IO.appDir` references work
cp ${lean}/bin/lean ${leanpkg}/bin/leanpkg ${leanc}/bin/leanc $out/bin
# NOTE: `lndir` will not override existing `bin/leanc`
${lndir}/bin/lndir -silent ${lean-bin-tools-unwrapped} $out
'';
});
test = buildCMake {
name = "lean-test-${desc}";
realSrc = lib.sourceByRegex ../. [ "src.*" "tests.*" ];
buildInputs = [ gmp perl ];
preConfigure = ''
cd src
'';
postConfigure = ''
patchShebangs ../../tests
rm -r bin lib include share
ln -sf ${lean-all}/* .
'';
buildPhase = ''
ctest --output-on-failure -E 'leancomptest_(doc_example|foreign)' -j$NIX_BUILD_CORES
'';
installPhase = ''
touch $out
'';
};
update-stage0 =
let cTree = symlinkJoin { name = "cs"; paths = map (l: l.cTree) stdlib; }; in
writeShellScriptBin "update-stage0" ''
CSRCS=${cTree} CP_PARAMS="--dereference --no-preserve=all" ${../script/update-stage0}
'';
update-stage0-commit = writeShellScriptBin "update-stage0-commit" ''
set -euo pipefail
${update-stage0}/bin/update-stage0
git commit -m "chore: update stage0"
'';
benchmarks =
let
entries = attrNames (readDir ../tests/bench);
leanFiles = map (n: elemAt n 0) (filter (n: n != null) (map (match "(.*)\.lean") entries));
in lib.genAttrs leanFiles (n: (buildLeanPackage {
name = n;
src = filterSource (e: _: baseNameOf e == "${n}.lean") ../tests/bench;
}).executable);
};
stage1 = stage { stage = 1; prevStage = stage0; self = stage1; };
stage2 = stage { stage = 2; prevStage = stage1; self = stage2; };
stage3 = stage { stage = 3; prevStage = stage2; self = stage3; };
}