This repository has been archived by the owner on Oct 25, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathPackage.lean
417 lines (331 loc) · 13.1 KB
/
Package.lean
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
411
412
413
414
415
416
417
/-
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone
-/
import Lean.Data.Name
import Lean.Elab.Import
import Std.Data.HashMap
import Lake.LeanVersion
import Lake.BuildTarget
import Lake.Glob
open Std System
open Lean (Name NameMap)
namespace Lake
--------------------------------------------------------------------------------
-- # Defaults
--------------------------------------------------------------------------------
/-- The default setting for a `PackageConfig`'s `buildDir` option. -/
def defaultBuildDir : FilePath := "build"
/-- The default setting for a `PackageConfig`'s `binDir` option. -/
def defaultBinDir : FilePath := "bin"
/-- The default setting for a `PackageConfig`'s `libDir` option. -/
def defaultLibDir : FilePath := "lib"
/-- The default setting for a `PackageConfig`'s `oleanDir` option. -/
def defaultOleanDir : FilePath := "lib"
/-- The default setting for a `PackageConfig`'s `irDir` option. -/
def defaultIrDir : FilePath := "ir"
/-- The default setting for a `PackageConfig`'s `depsDir` option. -/
def defaultDepsDir : FilePath := "lean_packages"
/-- The default setting for a `PackageConfig`'s `binRoot` option. -/
def defaultBinRoot : Name := `Main
--------------------------------------------------------------------------------
-- # PackageConfig Helpers
--------------------------------------------------------------------------------
/--
The `src` of a `Dependency`.
In Lake, dependency sources currently come into flavors:
* Local `path`s relative to the package's directory.
* Remote `git` repositories that are download from a given `url`
into the packages's `depsDir`.
-/
inductive Source where
| path (dir : FilePath) : Source
| git (url rev : String) (branch : Option String := none) : Source
deriving Inhabited, Repr
/-- A `Dependency` of a package. -/
structure Dependency where
/--
A `Name` for the dependency.
The names of a package's dependencies cannot clash.
-/
name : Name
/--
The source of a dependency.
See the documentation of `Source` for more information.
-/
src : Source
/--
The subdirectory of the dependency's source where
the dependency's package configuration is located.
-/
dir : FilePath := "."
/--
Arguments to pass to the dependency's package configuration.
-/
args : List String := []
deriving Inhabited, Repr
/--
A package `Script` is an arbitrary function that is
indexed by a `String` key and can be be run by `lake run <key> [-- <args>]`.
-/
abbrev Script := (args : List String) → IO UInt32
/-- Converts a snake case, kebab case, or lower camel case `String` to upper camel case. -/
def toUpperCamelCaseString (str : String) : String :=
let parts := str.split fun chr => chr == '_' || chr == '-'
String.join <| parts.map (·.capitalize)
/-- Converts a snake case, kebab case, or lower camel case `Name` to upper camel case. -/
def toUpperCamelCase (name : Name) : Name :=
if let Name.str p s _ := name then
Name.mkStr (toUpperCamelCase p) <| toUpperCamelCaseString s
else
name
--------------------------------------------------------------------------------
-- # PackageConfig
--------------------------------------------------------------------------------
/-- A package's declarative configuration. -/
structure PackageConfig where
/--
The `Name` of the package.
-/
name : Name
/-
An `Array` of the package's dependencies.
See the documentation of `Dependency` for more information.
-/
dependencies : Array Dependency := #[]
/--
The directory to which Lake should download dependencies.
Defaults to `defaultDepsDir` (i.e., `lean_packages`).
-/
depsDir : FilePath := defaultDepsDir
/--
An extra `OpaqueTarget` that should be built before the package.
`OpaqueTarget.collectList/collectArray` can be used combine multiple
targets into a single `extraDepTarget`.
-/
extraDepTarget : OpaqueTarget := Target.nil
/--
The directory containing the package's Lean source files.
Defaults to the package's directory.
(This will be passed to `lean` as the `-R` option.)
-/
srcDir : FilePath := "."
/--
The directory to which Lake should output the package's build results.
Defaults to `defaultBuildDir` (i.e., `build`).
-/
buildDir : FilePath := defaultBuildDir
/--
The build subdirectory to which Lake should output the package's `.olean` files.
Defaults to `defaultOleanDir` (i.e., `lib`).
-/
oleanDir : FilePath := defaultOleanDir
/-
The root module(s) of the package's library.
Submodules of these roots (e.g., `Pkg.Foo` of `Pkg`) are considered
part of the package.
Defaults to a single root of the package's upper camel case `name`.
-/
libRoots : Array Name := #[toUpperCamelCase name]
/--
An `Array` of module `Glob`s to build for the package's library.
Defaults to a `Glob.one` of each of the module's `libRoots`.
Submodule globs build every source file within their directory.
Local imports of glob'ed files (i.e., fellow modules of the package) are
also recursively built.
-/
libGlobs : Array Glob := libRoots.map Glob.one
/--
Additional arguments to pass to `lean` while compiling Lean source files.
-/
leanArgs : Array String := #[]
/--
Additional arguments to pass to `leanc`
while compiling the C source files generated by `lean`.
Defaults to `-O3` and `-DNDEBUG`.
-/
leancArgs : Array String := #["-O3", "-DNDEBUG"]
/--
The build subdirectory to which Lake should output
the package's intermediary results (e.g., `.c` and `.o` files).
Defaults to `defaultIrDir` (i.e., `ir`).
-/
irDir : FilePath := defaultIrDir
/--
The name of the package's static library.
Defaults to the package's upper camel case `name`.
-/
libName : String := toUpperCamelCase name |>.toString (escape := false)
/--
The build subdirectory to which Lake should output the package's static library.
Defaults to `defaultLibDir` (i.e., `lib`).
-/
libDir : FilePath := defaultLibDir
/--
The name of the package's binary executable.
Defaults to the package's `name` with any `.` replaced with a `-`.
-/
binName : String := name.toStringWithSep "-" (escape := false)
/--
The build subdirectory to which Lake should output the package's binary executable.
Defaults to `defaultBinDir` (i.e., `bin`).
-/
binDir : FilePath := defaultBinDir
/--
The root module of the package's binary executable.
Defaults to `defaultBinRoot` (i.e., `Main`).
The root is built by recursively building its
local imports (i.e., fellow modules of the package).
This setting is most useful for packages that are distributing both a
library and a binary (like Lake itself). In such cases, it is common for
there to be code (e.g., `main`) that is needed for the binary but should
not be included in the library proper.
-/
binRoot : Name := defaultBinRoot
/--
Additional library `FileTarget`s
(beyond the package's and its dependencies' libraries)
to build and link to the package's binary executable
(and/or to dependent package's executables).
-/
moreLibTargets : Array FileTarget := #[]
/--
Additional arguments to pass to `leanc`
while compiling the package's binary executable.
These will come *after* the paths of libraries built with `moreLibTargets`.
-/
linkArgs : Array String := #[]
deriving Inhabited
--------------------------------------------------------------------------------
-- # Package
--------------------------------------------------------------------------------
/-- A Lake package -- its location plus its configuration. -/
structure Package where
/-- The path to the package's directory. -/
dir : FilePath
/-- The package's configuration. -/
config : PackageConfig
/--
A `NameMap` of scripts for the package.
A `Script` is a `(args : List String) → IO UInt32` definition with
a `@[script]` tag that can be run by `lake run <script> [-- <args>]`.
-/
scripts : NameMap Script := {}
deriving Inhabited
/--
An alternate signature for package configurations
that permits more dynamic configurations, but is still pure.
-/
def Packager := (pkgDir : FilePath) → (args : List String) → PackageConfig
/--
An alternate signature for package configurations
that permits more dynamic configurations, including performing `IO`.
-/
def IOPackager := (pkgDir : FilePath) → (args : List String) → IO PackageConfig
namespace Package
/-- The package's `name` configuration. -/
def name (self : Package) : Name :=
self.config.name
/-- The package's `dependencies` configuration. -/
def dependencies (self : Package) : Array Dependency :=
self.config.dependencies
/-- The package's `extraDepTarget` configuration. -/
def extraDepTarget (self : Package) : OpaqueTarget :=
self.config.extraDepTarget
/-- The package's `dir` joined with its `depsDir` configuration. -/
def depsDir (self : Package) : FilePath :=
self.dir / self.config.depsDir
/-- The package's `dir` joined with its `srcDir` configuration. -/
def srcDir (self : Package) : FilePath :=
self.dir / self.config.srcDir
/-- The package's root directory for Lean (i.e., `srcDir`). -/
def rootDir (self : Package) : FilePath :=
self.srcDir
/-- The path to a module's `.lean` source file within the package. -/
def modToSrc (mod : Name) (self : Package) : FilePath :=
Lean.modToFilePath self.srcDir mod "lean"
/-- The package's `dir` joined with its `buildDir` configuration. -/
def buildDir (self : Package) : FilePath :=
self.dir / self.config.buildDir
/-- The package's `buildDir` joined with its `oleanDir` configuration. -/
def oleanDir (self : Package) : FilePath :=
self.buildDir / self.config.oleanDir
/-- The package's `leanArgs` configuration. -/
def leanArgs (self : Package) : Array String :=
self.config.leanArgs
/-- The path to a module's `.olean` file within the package. -/
def modToOlean (mod : Name) (self : Package) : FilePath :=
Lean.modToFilePath self.oleanDir mod "olean"
/-- The path to module's `.hash` file within the package. -/
def modToHashFile (mod : Name) (self : Package) : FilePath :=
Lean.modToFilePath self.oleanDir mod "hash"
/-- The package's `libRoots` configuration. -/
def libRoots (self : Package) : Array Name :=
self.config.libRoots
/-- The package's `libGlobs` configuration. -/
def libGlobs (self : Package) : Array Glob :=
self.config.libGlobs
/-- Whether the given module is local to the package. -/
def isLocalModule (mod : Name) (self : Package) : Bool :=
self.libRoots.any fun root => root.isPrefixOf mod
/-- Get an `Array` of the package's module. -/
def getModuleArray (self : Package) : IO (Array Name) := do
let mut mods := #[]
for glob in self.libGlobs do
mods ← glob.pushModules self.srcDir mods
return mods
/-- The package's `leancArgs` configuration. -/
def leancArgs (self : Package) : Array String :=
self.config.leancArgs
/-- The package's `buildDir` joined with its `irDir` configuration. -/
def irDir (self : Package) : FilePath :=
self.buildDir / self.config.irDir
/-- To which Lake should output the package's `.c` files (.e., `irDir`). -/
def cDir (self : Package) : FilePath :=
self.irDir
/-- The path to a module's `.c` file within the package. -/
def modToC (mod : Name) (self : Package) : FilePath :=
Lean.modToFilePath self.cDir mod "c"
/-- To which Lake should output the package's `.o` files (.e., `irDir`). -/
def oDir (self : Package) : FilePath :=
self.irDir
/-- The path to a module's `.o` file within the package. -/
def modToO (mod : Name) (self : Package) : FilePath :=
Lean.modToFilePath self.oDir mod "o"
/-- The package's `buildDir` joined with its `libDir` configuration. -/
def libDir (self : Package) : FilePath :=
self.buildDir / self.config.libDir
/-- The package's `libName` configuration. -/
def staticLibName (self : Package) : FilePath :=
self.config.libName
/-- The file name of package's static library (i.e., `lib{staticLibName}.a`) -/
def staticLibFileName (self : Package) : FilePath :=
s!"lib{self.staticLibName}.a"
/-- The path to the package's static library. -/
def staticLibFile (self : Package) : FilePath :=
self.libDir / self.staticLibFileName
/-- The package's `binRoot` configuration. -/
def binRoot (self : Package) : Name :=
self.config.binRoot
/-- The package's `buildDir` joined with its `binDir` configuration. -/
def binDir (self : Package) : FilePath :=
self.buildDir / self.config.binDir
/-- The package's `binName` configuration. -/
def binName (self : Package) : FilePath :=
self.config.binName
/--
The file name of package's binary executable
(i.e., `binName` plus the platform's `exeExtension`).
-/
def binFileName (self : Package) : FilePath :=
FilePath.withExtension self.binName FilePath.exeExtension
/-- The path to the package's executable. -/
def binFile (self : Package) : FilePath :=
self.binDir / self.binFileName
/-- The package's `moreLibTargets` configuration. -/
def moreLibTargets (self : Package) : Array FileTarget :=
self.config.moreLibTargets
/-- The package's `linkArgs` configuration. -/
def linkArgs (self : Package) : Array String :=
self.config.linkArgs