-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathlakefile.lean
More file actions
189 lines (147 loc) · 6.26 KB
/
lakefile.lean
File metadata and controls
189 lines (147 loc) · 6.26 KB
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
import Lake
open System Lake DSL
package ix where
version := v!"0.1.0"
require LSpec from git
"https://github.com/argumentcomputer/LSpec" @ "d3c15b93a1dd4e7c8d5c0c3825c9555737e55c3e"
require Blake3 from git
"https://github.com/argumentcomputer/Blake3.lean" @ "aaf530784082a2c00b0a93648741429d274102ca"
require Cli from git
"https://github.com/leanprover/lean4-cli" @ "v4.29.0"
require batteries from git
"https://github.com/leanprover-community/batteries" @ "v4.29.0"
/-! ## FFI
The Rust static libraries use `target` + `moreLinkObjs` instead of `extern_lib` because different Lean executables need different Cargo features:
- `ix` uses `ix_rs_net` (`parallel,net`) for networking support (iroh).
- `IxTests` uses `ix_rs_test` (`parallel,test-ffi`) for test-only FFI code.
- Everything else inherits `ix_rs` (`parallel` only) from the `Ix` `lean_lib`.
The `ix_rs_test` and `ix_rs_net` targets fetch `ix_rs` first to guarantee ordering
before overwriting the lib, since they write to the same lib path. The second cargo build is incremental — only the feature-affected crates recompile.
`extern_lib` only runs at link time, so `lake build` on a `lean_lib` alone wouldn't trigger the Cargo build. With `target` + `moreLinkObjs`, the Rust static lib is built during module compilation on the default `Ix` lib, allowing Lake to conditional compile the Rust lib per build target.
-/
section FFI
/-- Build args for `cargo build --release` with feature flags from env vars.
Cargo output is visible with `lake -v build`. -/
def cargoArgs (testFfi : Bool := false) (net : Bool := false) : IO (Array String) := do
-- IX_NO_PAR=1 disables parallel
let ixNoPar ← IO.getEnv "IX_NO_PAR"
let mut features : Array String := #[]
if ixNoPar != some "1" then features := features.push "parallel"
if net && !System.Platform.isOSX then features := features.push "net"
if testFfi then features := features.push "test-ffi"
let buildArgs := #["build", "--release"]
if features.isEmpty then return buildArgs
else return buildArgs ++ #["--features", ",".intercalate features.toList]
/-- Build the Rust static lib with default features (`parallel`). -/
target ix_rs pkg : FilePath := do
let args ← cargoArgs
proc { cmd := "cargo", args, cwd := pkg.dir } (quiet := true)
inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_rs"
/-- Rebuild the Rust static lib with `test-ffi`.
Only triggered by `lake test` (via `moreLinkObjs` on `IxTests`).
Fetches `ix_rs` first to guarantee ordering before overwriting the lib. -/
target ix_rs_test pkg : FilePath := do
let _ ← ix_rs.fetch
let args ← cargoArgs (testFfi := true)
proc { cmd := "cargo", args, cwd := pkg.dir } (quiet := true)
inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_rs"
/-- Build the Rust static lib with `net` for the `ix` CLI.
Fetches `ix_rs` first to guarantee ordering before overwriting the lib. -/
target ix_rs_net pkg : FilePath := do
let _ ← ix_rs.fetch
let args ← cargoArgs (net := true)
proc { cmd := "cargo", args, cwd := pkg.dir } (quiet := true)
inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_rs"
end FFI
@[default_target]
lean_lib Ix where
moreLinkObjs := #[ix_rs]
precompileModules := true
lean_exe ix where
root := `Main
supportInterpreter := true
moreLinkObjs := #[ix_rs_net]
section Tests
lean_lib Tests
@[test_driver]
lean_exe IxTests where
root := `Tests.Main
supportInterpreter := true
moreLinkObjs := #[ix_rs_test]
lean_exe kernel where
root := `Kernel
supportInterpreter := true
end Tests
section Benchmarks
lean_exe «bench-aiur» where
root := `Benchmarks.Aiur
lean_exe «bench-blake3» where
root := `Benchmarks.Blake3
lean_exe «bench-sha256» where
root := `Benchmarks.Sha256
lean_exe «bench-ixvm» where
root := `Benchmarks.IxVM
supportInterpreter := true
lean_exe «bench-shardmap» where
root := `Benchmarks.ShardMap
lean_exe «bench-check-nat-add-comm» where
root := `Benchmarks.CheckNatAddComm
supportInterpreter := true
end Benchmarks
section IxApplications
lean_lib Apps
lean_exe Apps.ZKVoting.Prover where
supportInterpreter := true
lean_exe Apps.ZKVoting.Verifier
end IxApplications
section Scripts
open IO in
script install := do
println! "Building ix"
let out ← Process.output { cmd := "lake", args := #["build", "ix"]}
if out.exitCode ≠ 0 then
eprintln out.stderr; return out.exitCode
-- Get the target directory for the ix binary
let binDir ← match ← getEnv "HOME" with
| some homeDir =>
let binDir : FilePath := homeDir / ".local" / "bin"
print s!"Target directory for the ix binary? (default={binDir}) "
let input := (← (← getStdin).getLine).trimAscii.toString
pure $ if input.isEmpty then binDir else ⟨input⟩
| none =>
print s!"Target directory for the ix binary? "
let input := (← (← getStdin).getLine).trimAscii.toString
if input.isEmpty then
eprintln "Target directory can't be empty."; return 1
pure ⟨input⟩
-- Copy the ix binary into the target directory
let tgtPath := binDir / "ix"
let srcBytes ← FS.readBinFile $ ".lake" / "build" / "bin" / "ix"
FS.writeBinFile tgtPath srcBytes
-- Set access rights for the newly created file
let fullAccess := { read := true, write := true, execution := true }
let noWriteAccess := { fullAccess with write := false }
let fileRight := { user := fullAccess, group := fullAccess, other := noWriteAccess }
setAccessRights tgtPath fileRight
return 0
script "get-exe-targets" := do
let pkg ← getRootPackage
let exeTargets := pkg.configTargets LeanExe.configKind
for tgt in exeTargets do
IO.println <| tgt.name.toString |>.dropPrefix "«" |>.dropSuffix "»" |>.toString
return 0
@[lint_driver]
script "build-all" (args) := do
let pkg ← getRootPackage
let libNames := pkg.configTargets LeanLib.configKind |>.map (·.name.toString)
let exeNames := pkg.configTargets LeanExe.configKind |>.map (·.name.toString)
let allNames := libNames ++ exeNames |>.toList
for name in allNames do
IO.println s!"Building: {name}"
let child ← IO.Process.spawn {
cmd := "lake", args := #["build", name] ++ args
stdout := .inherit, stderr := .inherit }
let exitCode ← child.wait
if exitCode != 0 then return exitCode
return 0
end Scripts