feat: improve Target API
This commit is contained in:
parent
a541f2054e
commit
aa1ca9c4b7
7 changed files with 116 additions and 20 deletions
|
|
@ -5,6 +5,8 @@ Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone
|
|||
-/
|
||||
import Lake.Cli
|
||||
import Lake.SearchPath
|
||||
-- API file not imported elsewhere; imported here to force build
|
||||
import Lake.BuildTargets
|
||||
|
||||
def main (args : List String) : IO UInt32 := do
|
||||
try
|
||||
|
|
|
|||
|
|
@ -70,10 +70,6 @@ def checkIfSameHash (hash : Hash) (file : FilePath) : IO Bool :=
|
|||
catch _ =>
|
||||
false
|
||||
|
||||
/-- Check if the artifact's `MTIme` is at least `depMTime`. -/
|
||||
def checkIfNewer [GetMTime a] (artifact : a) (depMTime : MTime) : IO Bool := do
|
||||
try (← getMTime artifact) >= depMTime catch _ => false
|
||||
|
||||
/-- Construct a no-op build task if the given condition holds, otherwise perform `build`. -/
|
||||
def skipIf [Pure m] (cond : Bool) (build : m BuildTask) : m BuildTask := do
|
||||
if cond then pure BuildTask.nop else build
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Authors: Mac Malone
|
|||
import Lake.BuildTask
|
||||
import Lake.BuildTrace
|
||||
|
||||
open System
|
||||
namespace Lake
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
@ -37,6 +38,15 @@ def discardArtifact (self : Target t m α) : Target t m PUnit :=
|
|||
def mtime (self : Target MTime m a) : MTime :=
|
||||
self.trace
|
||||
|
||||
def file (self : Target t m FilePath) : FilePath :=
|
||||
self.artifact
|
||||
|
||||
def filesList (self : Target t m (List FilePath)) : List FilePath :=
|
||||
self.artifact
|
||||
|
||||
def filesArray (self : Target t m (Array FilePath)) : Array FilePath :=
|
||||
self.artifact
|
||||
|
||||
end Target
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
@ -106,15 +116,26 @@ def spawn (self : BuildTarget t a) : IO (ActiveBuildTarget t a) := do
|
|||
def materialize (self : BuildTarget t a) : IO PUnit :=
|
||||
self.task
|
||||
|
||||
-- ### Combinators
|
||||
|
||||
def after (target : BuildTarget t a) (act : IO PUnit) : IO PUnit :=
|
||||
target.task *> act
|
||||
|
||||
def afterList (targets : List (BuildTarget t a)) (act : IO PUnit) : IO PUnit :=
|
||||
targets.forM (·.task) *> act
|
||||
|
||||
instance : HAndThen (BuildTarget t a) (IO PUnit) (IO PUnit) :=
|
||||
⟨BuildTarget.after⟩
|
||||
|
||||
instance : HAndThen (List (BuildTarget t a)) (IO PUnit) (IO PUnit) :=
|
||||
⟨BuildTarget.afterList⟩
|
||||
|
||||
end BuildTarget
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- # File Targets
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
section
|
||||
open System
|
||||
|
||||
-- ## File Target
|
||||
|
||||
abbrev FileTarget :=
|
||||
|
|
@ -125,11 +146,57 @@ namespace FileTarget
|
|||
def mk (file : FilePath) (depMTime : MTime) (task : IO PUnit) : FileTarget :=
|
||||
⟨file, depMTime, task⟩
|
||||
|
||||
def compute (file : FilePath) : IO FileTarget := do
|
||||
BuildTarget.pure file (← getMTime file)
|
||||
|
||||
protected def pure (file : FilePath) (depMTime : MTime) : FileTarget :=
|
||||
BuildTarget.pure file depMTime
|
||||
|
||||
end FileTarget
|
||||
|
||||
-- ## Files Target
|
||||
|
||||
abbrev FilesTarget :=
|
||||
BuildTarget MTime (Array FilePath)
|
||||
|
||||
namespace FilesTarget
|
||||
|
||||
def files (self : FilesTarget) : Array FilePath :=
|
||||
self.artifact
|
||||
|
||||
def filesAsList (self : FilesTarget) : List FilePath :=
|
||||
self.artifact.toList
|
||||
|
||||
def filesAsArray (self : FilesTarget) : Array FilePath :=
|
||||
self.artifact
|
||||
|
||||
def compute (files : Array FilePath) : IO FilesTarget := do
|
||||
BuildTarget.pure files (MTime.arrayMax <| ← files.mapM getMTime)
|
||||
|
||||
def singleton (target : FileTarget) : FilesTarget :=
|
||||
{target with artifact := #[target.file]}
|
||||
|
||||
def collectList (targets : List FileTarget) : FilesTarget :=
|
||||
let files := Array.mk <| targets.map (·.file)
|
||||
let mtime := MTime.listMax <| targets.map (·.mtime)
|
||||
BuildTarget.mk files mtime do
|
||||
(← targets.mapM (IOTask.spawn ·.task)).forM (·.await)
|
||||
|
||||
def collectArray (targets : Array FileTarget) : FilesTarget :=
|
||||
let files := targets.map (·.file)
|
||||
let mtime := MTime.arrayMax <| targets.map (·.mtime)
|
||||
BuildTarget.mk files mtime do
|
||||
(← targets.mapM (IOTask.spawn ·.task)).forM (·.await)
|
||||
|
||||
def collect (targets : Array FileTarget) : FilesTarget :=
|
||||
collectArray targets
|
||||
|
||||
end FilesTarget
|
||||
|
||||
instance : Coe FileTarget FilesTarget := ⟨FilesTarget.singleton⟩
|
||||
instance : Coe (List FileTarget) FilesTarget := ⟨FilesTarget.collectList⟩
|
||||
instance : Coe (Array FileTarget) FilesTarget := ⟨FilesTarget.collectArray⟩
|
||||
|
||||
-- ## Active File Target
|
||||
|
||||
abbrev ActiveFileTarget :=
|
||||
|
|
@ -144,7 +211,6 @@ protected def pure (file : FilePath) (depMTime : MTime) : ActiveFileTarget :=
|
|||
ActiveBuildTarget.pure file depMTime
|
||||
|
||||
end ActiveFileTarget
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- # Lean Target
|
||||
|
|
@ -155,6 +221,9 @@ abbrev LeanTarget a :=
|
|||
|
||||
namespace LeanTarget
|
||||
|
||||
def nil : LeanTarget PUnit :=
|
||||
ActiveBuildTarget.pure () Inhabited.default
|
||||
|
||||
def hash (self : LeanTarget a) := self.trace.hash
|
||||
def mtime (self : LeanTarget a) := self.trace.mtime
|
||||
|
||||
|
|
@ -167,4 +236,7 @@ def all (targets : List (LeanTarget a)) : IO (LeanTarget PUnit) := do
|
|||
def fromMTimeTarget (target : ActiveBuildTarget MTime a) : LeanTarget a :=
|
||||
{target with trace := LeanTrace.fromMTime target.trace}
|
||||
|
||||
def buildOpaqueFromFileTarget (target : FileTarget) : IO (LeanTarget PUnit) := do
|
||||
LeanTarget.fromMTimeTarget <| ← BuildTarget.spawn target.discardArtifact
|
||||
|
||||
end LeanTarget
|
||||
|
|
|
|||
23
Lake/BuildTargets.lean
Normal file
23
Lake/BuildTargets.lean
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/-
|
||||
Copyright (c) 2021 Mac Malone. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Mac Malone
|
||||
-/
|
||||
import Lake.Compile
|
||||
import Lake.BuildTarget
|
||||
|
||||
open System
|
||||
namespace Lake
|
||||
|
||||
def oFileTarget
|
||||
(oFile : FilePath) (srcTarget : FileTarget)
|
||||
(args : Array String := #[]) (cmd := "c++") : FileTarget :=
|
||||
FileTarget.mk oFile srcTarget.trace <|
|
||||
unless (← checkIfNewer oFile srcTarget.mtime) do
|
||||
srcTarget >> compileO oFile srcTarget.artifact args (cmd := "c++")
|
||||
|
||||
def staticLibTarget
|
||||
(libFile : FilePath) (oFilesTarget : FilesTarget) : FileTarget :=
|
||||
FileTarget.mk libFile oFilesTarget.trace do
|
||||
unless (← checkIfNewer libFile oFilesTarget.mtime) do
|
||||
oFilesTarget >> compileStaticLib libFile oFilesTarget.filesAsArray
|
||||
|
|
@ -32,7 +32,8 @@ instance : Ord MTime := inferInstanceAs (Ord SystemTime)
|
|||
instance : LT MTime := ltOfOrd
|
||||
instance : LE MTime := leOfOrd
|
||||
|
||||
def MTime.listMax (mtimes : List MTime) := mtimes.maximum?.getD 0
|
||||
def MTime.listMax (mtimes : List MTime) := mtimes.foldl max 0
|
||||
def MTime.arrayMax (mtimes : Array MTime) := mtimes.foldl max 0
|
||||
|
||||
class GetMTime (α) where
|
||||
getMTime : α → IO MTime
|
||||
|
|
@ -42,6 +43,10 @@ export GetMTime (getMTime)
|
|||
instance : GetMTime System.FilePath where
|
||||
getMTime file := do (← file.metadata).modified
|
||||
|
||||
/-- Check if the artifact's `MTIme` is at least `depMTime`. -/
|
||||
def checkIfNewer [GetMTime a] (artifact : a) (depMTime : MTime) : IO Bool := do
|
||||
try (← getMTime artifact) >= depMTime catch _ => false
|
||||
|
||||
-- # Combined Trace
|
||||
|
||||
structure LeanTrace where
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ structure PackageConfig where
|
|||
libName : String := moduleRoot.toString (escape := false)
|
||||
depsDir : FilePath := defaultDepsDir
|
||||
dependencies : List Dependency := []
|
||||
buildMoreDepsTarget : IO (ActiveBuildTarget LeanTrace PUnit) := ActiveBuildTarget.nil
|
||||
buildMoreDepsTarget : IO (LeanTarget PUnit) := LeanTarget.nil
|
||||
scripts : HashMap String Script := HashMap.empty
|
||||
deriving Inhabited
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import Lake.Build
|
||||
import Lake.Package
|
||||
import Lake.BuildTargets
|
||||
|
||||
open Lake System
|
||||
|
||||
def cDir : FilePath := "c"
|
||||
|
|
@ -9,14 +10,11 @@ def buildDir := defaultBuildDir
|
|||
def addO := buildDir / cDir / "add.o"
|
||||
def cLib := buildDir / cDir / "libadd.a"
|
||||
|
||||
def fetchAddOTarget : IO ActiveFileTarget := do
|
||||
skipIfNewer addO (← getMTime addSrc) <|
|
||||
BuildTask.spawn <| compileO addO addSrc (cmd := "c++")
|
||||
def computeAddOTarget : IO FileTarget := do
|
||||
oFileTarget addO <| ← FileTarget.compute addSrc
|
||||
|
||||
def fetchCLibTarget : IO ActiveFileTarget := do
|
||||
let oTarget ← fetchAddOTarget
|
||||
skipIfNewer cLib oTarget.mtime <|
|
||||
oTarget >> compileStaticLib cLib #[addO]
|
||||
def computeCLibTarget : IO FileTarget := do
|
||||
staticLibTarget cLib <| ← computeAddOTarget
|
||||
|
||||
def package : PackageConfig := {
|
||||
name := "ffi"
|
||||
|
|
@ -28,6 +26,6 @@ def package : PackageConfig := {
|
|||
-- specify path to the lib for linker
|
||||
linkArgs := #[cLib.toString]
|
||||
-- specify the lib target as an additional dependency
|
||||
buildMoreDepsTarget := fetchCLibTarget.map fun target =>
|
||||
LeanTarget.fromMTimeTarget <| target.discardArtifact
|
||||
buildMoreDepsTarget := do
|
||||
LeanTarget.buildOpaqueFromFileTarget <| ← computeCLibTarget
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue