lean4-htt/src/lake/Lake/Config/Package.lean
Mac Malone 0639d49a4c
feat: scope output cache by platform & toolchain (#10730)
This PR changes the Lake's remote cache interface to scope cache outputs
by toolchain and/or platform were useful.

Packages that set `platformIndependent = true` will not be scoped by
platform and the core build (i.e., `bootstrap = true`) will not be
scoped by toolchain. Lake's detected platform and toolchain can be
overridden with the new `--platform` and `--toolchain` options to `cache
get` and `cache put`.

Lake no longer accepts the `--scope` option when using `cache get` with
Reservoir.. The `--repo` option must be used instead.
2025-10-11 02:17:39 +00:00

380 lines
14 KiB
Text

/-
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
-/
module
prelude
public import Lake.Config.Cache
public import Lake.Config.Script
public import Lake.Config.ConfigDecl
public import Lake.Config.Dependency
public import Lake.Config.PackageConfig
public import Lake.Util.FilePath -- use scoped instance downstream
public import Lake.Util.OrdHashSet
public import Lake.Util.Name
meta import all Lake.Util.OpaqueType
open System Lean
namespace Lake
public nonempty_type OpaquePostUpdateHook (pkg : Name)
/-- A Lake package -- its location plus its configuration. -/
public structure Package where
/-- The name of the package. -/
name : Name
/-- The name specified by the package. -/
origName : Name
/-- The absolute path to the package's directory. -/
dir : FilePath
/-- The path to the package's directory relative to the workspace. -/
relDir : FilePath
/-- The package's user-defined configuration. -/
config : PackageConfig name origName
/-- The absolute path to the package's configuration file. -/
configFile : FilePath
/-- The path to the package's configuration file (relative to `dir`). -/
relConfigFile : FilePath
/-- The path to the package's JSON manifest of remote dependencies (relative to `dir`). -/
relManifestFile : FilePath := config.manifestFile.getD defaultManifestFile |>.normalize
/-- The package's scope (e.g., in Reservoir). -/
scope : String
/-- The URL to this package's Git remote. -/
remoteUrl : String
/-- Dependency configurations for the package. -/
depConfigs : Array Dependency := #[]
/-- Target configurations in the order declared by the package. -/
targetDecls : Array (PConfigDecl name) := #[]
/-- Name-declaration map of target configurations in the package. -/
targetDeclMap : DNameMap (NConfigDecl name) :=
targetDecls.foldl (fun m d => m.insert d.name (.mk d rfl)) {}
/--
The names of the package's targets to build by default
(i.e., on a bare `lake build` of the package).
-/
defaultTargets : Array Name := #[]
/-- Scripts for the package. -/
scripts : NameMap Script := {}
/--
The names of the package's scripts run by default
(i.e., on a bare `lake run` of the package).
-/
defaultScripts : Array Script := #[]
/-- Post-`lake update` hooks for the package. -/
postUpdateHooks : Array (OpaquePostUpdateHook name) := #[]
/-- The package's `buildArchive`/`buildArchive?` configuration. -/
buildArchive : String :=
if let some n := config.buildArchive then n else defaultBuildArchive name
/-- The driver used for `lake test` when this package is the workspace root. -/
testDriver : String := config.testDriver
/-- The driver used for `lake lint` when this package is the workspace root. -/
lintDriver : String := config.lintDriver
/--
Input-to-output(s) map for hashes of package artifacts.
If `none`, the artifact cache is disabled for the package.
-/
inputsRef? : Option CacheRef := none
/--
Input-to-output(s) map for hashes of package artifacts.
If `none`, the artifact cache is disabled for the package.
-/
outputsRef? : Option CacheRef := none
deriving Inhabited
public instance : Hashable Package where hash pkg := hash pkg.name
public instance : BEq Package where beq p1 p2 := p1.name == p2.name
public abbrev PackageSet := Std.HashSet Package
@[inline] public def PackageSet.empty : PackageSet := ∅
public abbrev OrdPackageSet := OrdHashSet Package
@[inline] public def OrdPackageSet.empty : OrdPackageSet := OrdHashSet.empty
public instance : ToJson Package := ⟨(toJson ·.name)⟩
public instance : ToString Package := ⟨(·.name.toString)⟩
/-- A package with a name known at type-level. -/
public structure NPackage (n : Name) extends Package where
name_eq : toPackage.name = n
attribute [simp] NPackage.name_eq
public instance : CoeOut (NPackage n) Package := ⟨NPackage.toPackage⟩
public instance : CoeDep Package pkg (NPackage pkg.name) := ⟨⟨pkg, rfl⟩⟩
/--
The type of a post-update hooks monad.
`IO` equipped with logging ability and information about the Lake configuration.
-/
public abbrev PostUpdateFn (pkgName : Name) := NPackage pkgName → LakeT LogIO PUnit
public structure PostUpdateHook (pkgName : Name) where
fn : PostUpdateFn pkgName
deriving Inhabited
public hydrate_opaque_type OpaquePostUpdateHook PostUpdateHook name
public structure PostUpdateHookDecl where
pkg : Name
fn : PostUpdateFn pkg
deriving TypeName
namespace Package
/-- **For internal use.** Whether this package is Lean itself. -/
@[inline] public def bootstrap (self : Package) : Bool :=
self.config.bootstrap
/-- The package version. -/
@[inline] public def version (self : Package) : LeanVer :=
self.config.version
/-- The package's `versionTags` configuration. -/
@[inline] public def versionTags (self : Package) : StrPat :=
self.config.versionTags
/-- The package's `description` configuration. -/
@[inline] public def description (self : Package) : String :=
self.config.description
/-- The package's `keywords` configuration. -/
@[inline] public def keywords (self : Package) : Array String :=
self.config.keywords
/-- The package's `homepage` configuration. -/
@[inline] public def homepage (self : Package) : String :=
self.config.homepage
/-- The package's `reservoir` configuration. -/
@[inline] public def reservoir (self : Package) : Bool :=
self.config.reservoir
/-- The package's `license` configuration. -/
@[inline] public def license (self : Package) : String :=
self.config.license
/-- The package's `licenseFiles` configuration. -/
@[inline] public def relLicenseFiles (self : Package) : Array FilePath :=
self.config.licenseFiles.map (·.normalize)
/-- The package's `dir` joined with each of its `relLicenseFiles`. -/
@[inline] public def licenseFiles (self : Package) : Array FilePath :=
self.relLicenseFiles.map (self.dir / ·.normalize)
/-- The package's `readmeFile` configuration. -/
@[inline] public def relReadmeFile (self : Package) : FilePath :=
self.config.readmeFile.normalize
/-- The package's `dir` joined with its `relReadmeFile`. -/
@[inline] public def readmeFile (self : Package) : FilePath :=
self.dir / self.relReadmeFile
/-- The path to the package's Lake directory relative to `dir` (e.g., `.lake`). -/
@[inline] public def relLakeDir (_ : Package) : FilePath :=
defaultLakeDir
/-- The full path to the package's Lake directory (i.e, `dir` joined with `relLakeDir`). -/
@[inline] public def lakeDir (self : Package) : FilePath :=
self.dir / self.relLakeDir
/-- The path for storing the package's remote dependencies relative to `dir` (i.e., `packagesDir`). -/
@[inline] public def relPkgsDir (self : Package) : FilePath :=
self.config.packagesDir.normalize
/-- The package's `dir` joined with its `relPkgsDir`. -/
@[inline] public def pkgsDir (self : Package) : FilePath :=
self.dir / self.relPkgsDir
/-- The path to the package's JSON manifest of remote dependencies. -/
@[inline] public def manifestFile (self : Package) : FilePath :=
self.dir / self.relManifestFile
/-- The package's `dir` joined with its `buildDir` configuration. -/
@[inline] public def buildDir (self : Package) : FilePath :=
self.dir / self.config.buildDir.normalize
/-- The package's `testDriverArgs` configuration. -/
@[inline] public def testDriverArgs (self : Package) : Array String :=
self.config.testDriverArgs
/-- The package's `lintDriverArgs` configuration. -/
@[inline] public def lintDriverArgs (self : Package) : Array String :=
self.config.lintDriverArgs
/-- The package's `extraDepTargets` configuration. -/
@[inline] public def extraDepTargets (self : Package) : Array Name :=
self.config.extraDepTargets
/-- The package's `platformIndependent` configuration. -/
@[inline] public def platformIndependent (self : Package) : Option Bool :=
self.config.platformIndependent
/-- Whether the package's has been configured with `platformIndependent = true`. -/
@[inline] public def isPlatformIndependent (self : Package) : Bool :=
self.config.platformIndependent == some true
/-- The package's `releaseRepo`/`releaseRepo?` configuration. -/
@[inline] public def releaseRepo? (self : Package) : Option String :=
self.config.releaseRepo
/-- The packages `remoteUrl` as an `Option` (`none` if empty). -/
@[inline] public def remoteUrl? (self : Package) : Option String :=
if self.remoteUrl.isEmpty then some self.remoteUrl else none
/-- The package's `lakeDir` joined with its `buildArchive`. -/
@[inline] public def buildArchiveFile (self : Package) : FilePath :=
self.lakeDir / self.buildArchive
/-- The path where Lake stores the package's barrel (downloaded from Reservoir). -/
@[inline] public def barrelFile (self : Package) : FilePath :=
self.lakeDir / "build.barrel"
/-- The package's `preferReleaseBuild` configuration. -/
@[inline] public def preferReleaseBuild (self : Package) : Bool :=
self.config.preferReleaseBuild
/-- The package's `precompileModules` configuration. -/
@[inline] public def precompileModules (self : Package) : Bool :=
self.config.precompileModules
/-- The package's `moreGlobalServerArgs` configuration. -/
@[inline] public def moreGlobalServerArgs (self : Package) : Array String :=
self.config.moreGlobalServerArgs
/-- The package's `moreServerOptions` configuration appended to its `leanOptions` configuration. -/
@[inline] public def moreServerOptions (self : Package) : LeanOptions :=
LeanOptions.ofArray self.config.leanOptions ++ self.config.moreServerOptions
/-- The package's `buildType` configuration. -/
@[inline] public def buildType (self : Package) : BuildType :=
self.config.buildType
/-- The package's `backend` configuration. -/
@[inline] public def backend (self : Package) : Backend :=
self.config.backend
/-- The package's `allowImportAll` configuration. -/
@[inline] public def allowImportAll (self : Package) : Bool :=
self.config.allowImportAll
/-- The package's `dynlibs` configuration. -/
@[inline] public def dynlibs (self : Package) : TargetArray Dynlib :=
self.config.dynlibs
/-- The package's `plugins` configuration. -/
@[inline] public def plugins (self : Package) : TargetArray Dynlib :=
self.config.plugins
/-- The package's `leanOptions` configuration. -/
@[inline] public def leanOptions (self : Package) : LeanOptions :=
.ofArray self.config.leanOptions
/-- The package's `moreLeanArgs` configuration. -/
@[inline] public def moreLeanArgs (self : Package) : Array String :=
self.config.moreLeanArgs
/-- The package's `weakLeanArgs` configuration. -/
@[inline] public def weakLeanArgs (self : Package) : Array String :=
self.config.weakLeanArgs
/-- The package's `moreLeancArgs` configuration. -/
@[inline] public def moreLeancArgs (self : Package) : Array String :=
self.config.moreLeancArgs
/-- The package's `weakLeancArgs` configuration. -/
@[inline] public def weakLeancArgs (self : Package) : Array String :=
self.config.weakLeancArgs
/-- The package's `moreLinkObjs` configuration. -/
@[inline] public def moreLinkObjs (self : Package) : TargetArray FilePath :=
self.config.moreLinkObjs
/-- The package's `moreLinkLibs` configuration. -/
@[inline] public def moreLinkLibs (self : Package) : TargetArray Dynlib :=
self.config.moreLinkLibs
/-- The package's `moreLinkArgs` configuration. -/
@[inline] public def moreLinkArgs (self : Package) : Array String :=
self.config.moreLinkArgs
/-- The package's `weakLinkArgs` configuration. -/
@[inline] public def weakLinkArgs (self : Package) : Array String :=
self.config.weakLinkArgs
/-- The package's `dir` joined with its `srcDir` configuration. -/
@[inline] public def srcDir (self : Package) : FilePath :=
self.dir / self.config.srcDir.normalize
/-- The package's root directory for `lean` (i.e., `srcDir`). -/
@[inline] public def rootDir (self : Package) : FilePath :=
self.srcDir
/-- The package's `buildDir` joined with its `leanLibDir` configuration. -/
@[inline] public def leanLibDir (self : Package) : FilePath :=
self.buildDir / self.config.leanLibDir.normalize
/--
Where static libraries for the package are located.
The package's `buildDir` joined with its `nativeLibDir` configuration.
-/
@[inline] public def staticLibDir (self : Package) : FilePath :=
self.buildDir / self.config.nativeLibDir.normalize
/--
Where shared libraries for the package are located.
The package's `buildDir` joined with its `nativeLibDir` configuration.
-/
@[inline] public def sharedLibDir (self : Package) : FilePath :=
self.buildDir / self.config.nativeLibDir.normalize
/-- The package's `buildDir` joined with its `nativeLibDir` configuration. -/
@[inline, deprecated "Use staticLibDir or sharedLibDir instead." (since := "2025-03-29")]
public def nativeLibDir (self : Package) : FilePath :=
self.buildDir / self.config.nativeLibDir.normalize
/-- The package's `buildDir` joined with its `binDir` configuration. -/
@[inline] public def binDir (self : Package) : FilePath :=
self.buildDir / self.config.binDir.normalize
/-- The package's `buildDir` joined with its `irDir` configuration. -/
@[inline] public def irDir (self : Package) : FilePath :=
self.buildDir / self.config.irDir.normalize
/-- The package's `libPrefixOnWindows` configuration. -/
@[inline] public def libPrefixOnWindows (self : Package) : Bool :=
self.config.libPrefixOnWindows
/-- The package's `enableArtifactCache?` configuration. -/
@[inline] public def enableArtifactCache? (self : Package) : Option Bool :=
self.config.enableArtifactCache?
/-- The package's `restoreAllArtifacts` configuration. -/
@[inline] public def restoreAllArtifacts (self : Package) : Bool :=
self.config.restoreAllArtifacts
/-- The directory within the Lake cache were package-scoped files are stored. -/
public def cacheScope (self : Package) :=
self.name.toString (escape := false)
/-- Try to find a target configuration in the package with the given name. -/
public def findTargetDecl? (name : Name) (self : Package) : Option (NConfigDecl self.name name) :=
self.targetDeclMap.get? name
/-- Whether the given module is considered local to the package. -/
public def isLocalModule (mod : Name) (self : Package) : Bool :=
self.targetDecls.any (·.leanLibConfig?.any (·.isLocalModule mod))
/-- Whether the given module is in the package (i.e., can build it). -/
public def isBuildableModule (mod : Name) (self : Package) : Bool :=
self.targetDecls.any fun t =>
t.leanLibConfig?.any (·.isBuildableModule mod) ||
t.leanExeConfig?.any (·.root == mod)
/-- Remove the package's build outputs (i.e., delete its build directory). -/
public def clean (self : Package) : IO PUnit := do
if (← self.buildDir.pathExists) then
IO.FS.removeDirAll self.buildDir