111 lines
4.5 KiB
Text
111 lines
4.5 KiB
Text
/-
|
||
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.Build.Job
|
||
import Lake.Build.Actions
|
||
import Lake.Build.Monad
|
||
|
||
open System
|
||
namespace Lake
|
||
|
||
/-! # General Utilities -/
|
||
|
||
@[inline] def inputFile (path : FilePath) : SchedulerM (BuildJob FilePath) :=
|
||
Job.async <| (path, ·) <$> computeTrace path
|
||
|
||
@[inline] def buildUnlessUpToDate [CheckExists ι] [GetMTime ι] (info : ι)
|
||
(depTrace : BuildTrace) (traceFile : FilePath) (build : JobM PUnit) : JobM PUnit := do
|
||
let isOldMode ← getIsOldMode
|
||
let upToDate ←
|
||
if isOldMode then
|
||
depTrace.checkAgainstTime info
|
||
else
|
||
depTrace.checkAgainstFile info traceFile
|
||
unless upToDate do
|
||
build
|
||
unless isOldMode do
|
||
depTrace.writeToFile traceFile
|
||
|
||
@[inline] def buildFileUnlessUpToDate (file : FilePath)
|
||
(depTrace : BuildTrace) (build : BuildM PUnit) : BuildM BuildTrace := do
|
||
let traceFile := FilePath.mk <| file.toString ++ ".trace"
|
||
buildUnlessUpToDate file depTrace traceFile build
|
||
computeTrace file
|
||
|
||
@[inline] def buildFileAfterDep
|
||
(file : FilePath) (dep : BuildJob α) (build : α → BuildM PUnit)
|
||
(extraDepTrace : BuildM _ := pure BuildTrace.nil) : SchedulerM (BuildJob FilePath) :=
|
||
dep.bindSync fun depInfo depTrace => do
|
||
let depTrace := depTrace.mix (← extraDepTrace)
|
||
let trace ← buildFileUnlessUpToDate file depTrace <| build depInfo
|
||
return (file, trace)
|
||
|
||
@[inline] def buildFileAfterDepList
|
||
(file : FilePath) (deps : List (BuildJob α)) (build : List α → BuildM PUnit)
|
||
(extraDepTrace : BuildM _ := pure BuildTrace.nil) : SchedulerM (BuildJob FilePath) := do
|
||
buildFileAfterDep file (← BuildJob.collectList deps) build extraDepTrace
|
||
|
||
@[inline] def buildFileAfterDepArray
|
||
(file : FilePath) (deps : Array (BuildJob α)) (build : Array α → BuildM PUnit)
|
||
(extraDepTrace : BuildM _ := pure BuildTrace.nil) : SchedulerM (BuildJob FilePath) := do
|
||
buildFileAfterDep file (← BuildJob.collectArray deps) build extraDepTrace
|
||
|
||
/-! # Common Builds -/
|
||
|
||
def buildLeanO (name : String)
|
||
(oFile : FilePath) (srcJob : BuildJob FilePath)
|
||
(args : Array String := #[]) : SchedulerM (BuildJob FilePath) :=
|
||
buildFileAfterDep oFile srcJob (extraDepTrace := computeHash args) fun srcFile => do
|
||
compileO name oFile srcFile args (← getLeanc)
|
||
|
||
def buildStaticLib (libFile : FilePath)
|
||
(oFileJobs : Array (BuildJob FilePath)) : SchedulerM (BuildJob FilePath) :=
|
||
let name := libFile.fileName.getD libFile.toString
|
||
buildFileAfterDepArray libFile oFileJobs fun oFiles => do
|
||
compileStaticLib name libFile oFiles (← getLeanAr)
|
||
|
||
def buildLeanSharedLib
|
||
(libFile : FilePath) (linkJobs : Array (BuildJob FilePath))
|
||
(linkArgs : Array String := #[]) : SchedulerM (BuildJob FilePath) :=
|
||
let name := libFile.fileName.getD libFile.toString
|
||
buildFileAfterDepArray libFile linkJobs
|
||
(extraDepTrace := computeHash linkArgs) fun links => do
|
||
compileSharedLib name libFile (links.map toString ++ linkArgs) (← getLeanc)
|
||
|
||
def buildLeanExe
|
||
(exeFile : FilePath) (linkJobs : Array (BuildJob FilePath))
|
||
(linkArgs : Array String := #[]) : SchedulerM (BuildJob FilePath) :=
|
||
let name := exeFile.fileName.getD exeFile.toString
|
||
buildFileAfterDepArray exeFile linkJobs
|
||
(extraDepTrace := computeHash linkArgs) fun links => do
|
||
compileExe name exeFile links linkArgs (← getLeanc)
|
||
|
||
def buildLeanSharedLibOfStatic
|
||
(staticLibJob : BuildJob FilePath) (linkArgs : Array String := #[])
|
||
: SchedulerM (BuildJob FilePath) :=
|
||
staticLibJob.bindSync fun staticLib staticTrace => do
|
||
let dynlib := staticLib.withExtension sharedLibExt
|
||
let trace ← buildFileUnlessUpToDate dynlib staticTrace do
|
||
let args :=
|
||
if System.Platform.isOSX then
|
||
#[s!"-Wl,-force_load,{staticLib}"]
|
||
else
|
||
#["-Wl,--whole-archive", staticLib.toString, "-Wl,--no-whole-archive"]
|
||
let name := dynlib.fileName.getD dynlib.toString
|
||
compileSharedLib name dynlib (args ++ linkArgs) (← getLeanc)
|
||
return (dynlib, trace)
|
||
|
||
def computeDynlibOfShared
|
||
(sharedLibTarget : BuildJob FilePath) : SchedulerM (BuildJob Dynlib) :=
|
||
sharedLibTarget.bindSync fun sharedLib trace => do
|
||
if let some stem := sharedLib.fileStem then
|
||
if Platform.isWindows then
|
||
return ((sharedLib.parent, stem), trace)
|
||
else if stem.startsWith "lib" then
|
||
return ((sharedLib.parent, stem.drop 3), trace)
|
||
else
|
||
error s!"shared library `{sharedLib}` does not start with `lib`; this is not supported on Unix"
|
||
else
|
||
error s!"shared library `{sharedLib}` has no file name"
|