Skip to content

Commit 819b5ea

Browse files
tydeukim-em
authored andcommitted
refactor: change postUpdate? config to a decl
1 parent 5e0f604 commit 819b5ea

File tree

9 files changed

+114
-53
lines changed

9 files changed

+114
-53
lines changed

RELEASES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ v4.3.0 (development in progress)
1111
---------
1212

1313
* [Cancel outstanding tasks on document edit in the language server](https://github.com/leanprover/lean4/pull/2648).
14+
* **Lake:** Changed `postUpdate?` configuration option to a `post_update` declaration. See the `post_update` syntax docstring for more information on the new syntax.
15+
16+
* [Lake: A manifest is automatically created on workspace load if one does not exists.](https://github.com/leanprover/lean4/pull/2680).
17+
18+
* **Lake:** The `:=` syntax for configuration declarations (i.e., `package`, `lean_lib`, and `lean_exe`) has been deprecated. For example, `package foo := {...}` is deprecated.
1419

1520
v4.2.0
1621
---------

src/lake/Lake/Build/Index.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Copyright (c) 2022 Mac Malone. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Mac Malone
55
-/
6+
import Lake.Build.Targets
67
import Lake.Build.Executable
78
import Lake.Build.Topological
89

@@ -104,5 +105,8 @@ export BuildInfo (build)
104105
@[inline] protected def LeanExe.build (self : LeanExe) : BuildM (BuildJob FilePath) :=
105106
self.exe.build
106107

108+
@[inline] protected def LeanExeConfig.build (self : LeanExeConfig) : BuildM (BuildJob FilePath) := do
109+
(← self.get).build
110+
107111
@[inline] protected def LeanExe.fetch (self : LeanExe) : IndexBuildM (BuildJob FilePath) :=
108112
self.exe.fetch

src/lake/Lake/Config/Package.lean

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -90,32 +90,6 @@ structure PackageConfig extends WorkspaceConfig, LeanConfig where
9090
/-- An `Array` of target names to build whenever the package is used. -/
9191
extraDepTargets : Array Name := #[]
9292

93-
/--
94-
A post-`lake update` hook. The monadic action is run after a successful
95-
`lake update` execution on this package or one of its downstream dependents.
96-
Defaults to `none`.
97-
98-
As an example, Mathlib can use this feature to synchronize the Lean toolchain
99-
and run `cache get`:
100-
101-
```
102-
package mathlib where
103-
postUpdate? := some do
104-
let some pkg ← findPackage? `mathlib
105-
| error "mathlib is missing from workspace"
106-
let wsToolchainFile := (← getRootPackage).dir / "lean-toolchain"
107-
let mathlibToolchain ← IO.FS.readFile <| pkg.dir / "lean-toolchain"
108-
IO.FS.writeFile wsToolchainFile mathlibToolchain
109-
let some exe := pkg.findLeanExe? `cache
110-
| error s!"{pkg.name}: cache is missing from the package"
111-
let exeFile ← runBuild (exe.build >>= (·.await))
112-
let exitCode ← env exeFile.toString #["get"]
113-
if exitCode ≠ 0 then
114-
error s!"{pkg.name}: failed to fetch cache"
115-
```
116-
-/
117-
postUpdate? : Option (LakeT LogIO PUnit) := none
118-
11993
/--
12094
Whether to compile each of the package's module into a native shared library
12195
that is loaded whenever the module is imported. This speeds up evaluation of
@@ -197,6 +171,9 @@ deriving Inhabited
197171
/-! # Package -/
198172
--------------------------------------------------------------------------------
199173

174+
175+
declare_opaque_type OpaquePostUpdateHook (pkg : Name)
176+
200177
/-- A Lake package -- its location plus its configuration. -/
201178
structure Package where
202179
/-- The path to the package's directory. -/
@@ -231,6 +208,8 @@ structure Package where
231208
(i.e., on a bare `lake run` of the package).
232209
-/
233210
defaultScripts : Array Script := #[]
211+
/-- Post-`lake update` hooks for the package. -/
212+
postUpdateHooks : Array (OpaquePostUpdateHook config.name) := #[]
234213

235214
instance : Nonempty Package :=
236215
have : Inhabited Environment := Classical.inhabited_of_nonempty inferInstance
@@ -263,6 +242,22 @@ instance : CoeDep Package pkg (NPackage pkg.name) := ⟨⟨pkg, rfl⟩⟩
263242
/-- The package's name. -/
264243
abbrev NPackage.name (_ : NPackage n) := n
265244

245+
/--
246+
The type of a post-update hooks monad.
247+
`IO` equipped with logging ability and information about the Lake configuration.
248+
-/
249+
abbrev PostUpdateFn (pkgName : Name) := NPackage pkgName → LakeT LogIO PUnit
250+
251+
structure PostUpdateHook (pkgName : Name) where
252+
fn : PostUpdateFn pkgName
253+
deriving Inhabited
254+
255+
hydrate_opaque_type OpaquePostUpdateHook PostUpdateHook name
256+
257+
structure PostUpdateHookDecl where
258+
pkg : Name
259+
fn : PostUpdateFn pkg
260+
266261
namespace Package
267262

268263
/-- The package's direct dependencies. -/
@@ -289,10 +284,6 @@ namespace Package
289284
@[inline] def extraDepTargets (self : Package) : Array Name :=
290285
self.config.extraDepTargets
291286

292-
/-- The package's `postUpdate?` configuration. -/
293-
@[inline] def postUpdate? (self : Package) :=
294-
self.config.postUpdate?
295-
296287
/-- The package's `releaseRepo?` configuration. -/
297288
@[inline] def releaseRepo? (self : Package) : Option String :=
298289
self.config.releaseRepo?

src/lake/Lake/DSL/Attributes.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ initialize packageAttr : OrderedTagAttribute ←
1414
initialize packageDepAttr : OrderedTagAttribute ←
1515
registerOrderedTagAttribute `package_dep "mark a definition as a Lake package dependency"
1616

17+
initialize postUpdateAttr : OrderedTagAttribute ←
18+
registerOrderedTagAttribute `post_update "mark a definition as a Lake package post-update hook"
19+
1720
initialize scriptAttr : OrderedTagAttribute ←
1821
registerOrderedTagAttribute `script "mark a definition as a Lake script"
1922

src/lake/Lake/DSL/Package.lean

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import Lake.DSL.DeclUtil
1010
namespace Lake.DSL
1111
open Lean Parser Command
1212

13+
/-! # Package Declarations
14+
DSL definitions for packages and hooks.
15+
-/
16+
1317
/-- The name given to the definition created by the `package` syntax. -/
1418
def packageDeclName := `_package
1519

@@ -33,3 +37,40 @@ doc?:optional(docComment) attrs?:optional(Term.attributes)
3337
let ty := mkCIdentFrom (← getRef) ``PackageConfig
3438
let attrs := #[attr] ++ expandAttrs attrs?
3539
mkConfigStructDecl packageDeclName doc? attrs ty sig
40+
41+
/--
42+
Declare a post-`lake update` hook for the package.
43+
Runs the monadic action is after a successful `lake update` execution
44+
in this package or one of its downstream dependents.
45+
46+
**Example**
47+
48+
This feature enables Mathlib to synchronize the Lean toolchain and run
49+
`cache get` after a `lake update`:
50+
51+
```
52+
lean_exe cache
53+
post_update pkg do
54+
let wsToolchainFile := (← getRootPackage).dir / "lean-toolchain"
55+
let mathlibToolchain ← IO.FS.readFile <| pkg.dir / "lean-toolchain"
56+
IO.FS.writeFile wsToolchainFile mathlibToolchain
57+
let exeFile ← runBuild cache.build >>= (·.await)
58+
let exitCode ← env exeFile.toString #["get"]
59+
if exitCode ≠ 0 then
60+
error s!"{pkg.name}: failed to fetch cache"
61+
```
62+
-/
63+
scoped syntax (name := postUpdateDecl)
64+
optional(docComment) optional(Term.attributes)
65+
"post_update " (ppSpace simpleBinder)? (declValSimple <|> declValDo) : command
66+
67+
macro_rules
68+
| `($[$doc?]? $[$attrs?]? post_update%$kw $[$pkg?]? do $seq $[$wds?]?) =>
69+
`($[$doc?]? $[$attrs?]? post_update%$kw $[$pkg?]? := do $seq $[$wds?]?)
70+
| `($[$doc?]? $[$attrs?]? post_update%$kw $[$pkg?]? := $defn $[$wds?]?) => do
71+
let pkg ← expandOptSimpleBinder pkg?
72+
let pkgName := mkIdentFrom pkg `_package.name
73+
let attr ← withRef kw `(Term.attrInstance| «post_update»)
74+
let attrs := #[attr] ++ expandAttrs attrs?
75+
`($[$doc?]? @[$attrs,*] def postUpdateHook : PostUpdateHookDecl :=
76+
{pkg := $pkgName, fn := fun $pkg => $defn} $[$wds?]?)

src/lake/Lake/DSL/Script.lean

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,29 @@ import Lake.Config.Package
77
import Lake.DSL.Attributes
88
import Lake.DSL.DeclUtil
99

10+
/-! # Script Declarations
11+
DSL definitions to define a Lake script for a package.
12+
-/
13+
1014
namespace Lake.DSL
1115
open Lean Parser Command
1216

1317
syntax scriptDeclSpec :=
1418
ident (ppSpace simpleBinder)? (declValSimple <|> declValDo)
1519

1620
/--
17-
Define a new Lake script for the package. Has two forms:
21+
Define a new Lake script for the package.
1822
19-
```lean
20-
script «script-name» (args) do /- ... -/
21-
script «script-name» (args) := ...
23+
**Example**
24+
25+
```
26+
/-- Display a greeting -/
27+
script «script-name» (args) do
28+
if h : 0 < args.length then
29+
IO.println s!"Hello, {args[0]'h}!"
30+
else
31+
IO.println "Hello, world!"
32+
return 0
2233
```
2334
-/
2435
scoped syntax (name := scriptDecl)

src/lake/Lake/Load/Main.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,13 @@ def buildUpdatedManifest (ws : Workspace)
131131
match res with
132132
| (.ok root, deps) =>
133133
let ws : Workspace ← {ws with root}.finalize
134-
LakeT.run ⟨ws⟩ <| ws.packages.forM fun pkg => do
135-
if let some postUpdate := pkg.postUpdate? then
136-
logInfo s!"{pkg.name}: running post-update hook"
137-
postUpdate
138134
let manifest : Manifest := {name? := ws.root.name, packagesDir? := ws.relPkgsDir}
139135
let manifest := deps.foldl (·.addPackage ·.manifestEntry) manifest
140136
manifest.saveToFile ws.manifestFile
137+
LakeT.run ⟨ws⟩ <| ws.packages.forM fun pkg => do
138+
unless pkg.postUpdateHooks.isEmpty do
139+
logInfo s!"{pkg.name}: running post-update hooks"
140+
pkg.postUpdateHooks.forM fun hook => hook.get.fn pkg
141141
return ws
142142
| (.error cycle, _) =>
143143
let cycle := cycle.map (s!" {·}")

src/lake/Lake/Load/Package.lean

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def Package.finalize (self : Package) (deps : Array Package) : LogIO Package :=
6969
let opts := self.leanOpts
7070
let strName := self.name.toString (escape := false)
7171

72-
-- Load Script, Facet, & Target Configurations
72+
-- Load Script, Facet, Target, and Hook Configurations
7373
let scripts ← mkTagMap env scriptAttr fun scriptName => do
7474
let name := strName ++ "/" ++ scriptName.toString (escape := false)
7575
let fn ← IO.ofExcept <| evalConstCheck env opts ScriptFn ``ScriptFn scriptName
@@ -98,12 +98,21 @@ def Package.finalize (self : Package) (deps : Array Package) : LogIO Package :=
9898
error s!"target was defined as `{decl.pkg}/{decl.name}`, but was registered as `{self.name}/{name}`"
9999
| .error e => error e
100100
let defaultTargets := defaultTargetAttr.getAllEntries env
101+
let postUpdateHooks ← postUpdateAttr.getAllEntries env |>.mapM fun name =>
102+
match evalConstCheck env opts PostUpdateHookDecl ``PostUpdateHookDecl name with
103+
| .ok decl =>
104+
if h : decl.pkg = self.config.name then
105+
return OpaquePostUpdateHook.mk ⟨h ▸ decl.fn⟩
106+
else
107+
error s!"post-update hook was defined in `{decl.pkg}`, but was registered in `{self.name}`"
108+
| .error e => error e
101109

102110
-- Fill in the Package
103111
return {self with
104112
opaqueDeps := deps.map (.mk ·)
105113
leanLibConfigs, leanExeConfigs, externLibConfigs
106-
opaqueTargetConfigs, defaultTargets, scripts, defaultScripts
114+
opaqueTargetConfigs, defaultTargets, scripts, defaultScripts,
115+
postUpdateHooks
107116
}
108117

109118
/--
Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import Lake
22
open Lake DSL
33

4-
package dep where
5-
postUpdate? := some do
6-
let some pkg ← findPackage? `dep
7-
| error "dep is missing from workspace"
8-
let wsToolchainFile := (← getRootPackage).dir / "toolchain"
9-
let depToolchain ← IO.FS.readFile <| pkg.dir / "toolchain"
10-
IO.FS.writeFile wsToolchainFile depToolchain
11-
let some exe := pkg.findLeanExe? `hello
12-
| error s!"{pkg.name}: hello is missing from the package"
13-
let exeFile ← runBuild (exe.build >>= (·.await))
14-
let exitCode ← env exeFile.toString #["get"]
15-
if exitCode ≠ 0 then
16-
error s!"{pkg.name}: failed to fetch hello"
4+
package dep
175

186
lean_exe hello
7+
8+
post_update pkg do
9+
let wsToolchainFile := (← getRootPackage).dir / "toolchain"
10+
let depToolchain ← IO.FS.readFile <| pkg.dir / "toolchain"
11+
IO.FS.writeFile wsToolchainFile depToolchain
12+
let exeFile ← runBuild hello.build >>= (·.await)
13+
let exitCode ← env exeFile.toString #["get"]
14+
if exitCode ≠ 0 then
15+
error s!"{pkg.name}: failed to fetch hello"

0 commit comments

Comments
 (0)