feat: improve Target API

This commit is contained in:
tydeu 2021-08-04 14:07:28 -04:00
parent a541f2054e
commit aa1ca9c4b7
7 changed files with 116 additions and 20 deletions

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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
}