177 lines
6.9 KiB
Text
177 lines
6.9 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 Lean.Util.Paths
|
||
import Lake.Config.FacetConfig
|
||
import Lake.Config.TargetConfig
|
||
import Lake.Config.Env
|
||
|
||
open System
|
||
open Lean (LeanPaths)
|
||
|
||
namespace Lake
|
||
|
||
/-- The file name of a workspace's package manifest (i.e., `manifest.json`). -/
|
||
def manifestFileName := "manifest.json"
|
||
|
||
/-- A Lake workspace -- the top-level package directory. -/
|
||
structure Workspace : Type where
|
||
/-- The root package of the workspace. -/
|
||
root : Package
|
||
/-- The detect `Lake.Env` of the workspace. -/
|
||
lakeEnv : Lake.Env
|
||
/-- Name-package map of packages within the workspace. -/
|
||
packageMap : NameMap Package := {}
|
||
/--
|
||
Name-configuration map of (opaque references to)
|
||
module facets defined in the workspace.
|
||
-/
|
||
moduleFacetConfigs : DNameMap ModuleFacetConfig := {}
|
||
/--
|
||
Name-configuration map of (opaque references to)
|
||
module facets defined in the workspace.
|
||
-/
|
||
packageFacetConfigs : DNameMap PackageFacetConfig := {}
|
||
deriving Inhabited
|
||
|
||
hydrate_opaque_type OpaqueWorkspace Workspace
|
||
|
||
namespace Workspace
|
||
|
||
/-- The path to the workspace's directory (i.e., the directory of the root package). -/
|
||
def dir (self : Workspace) : FilePath :=
|
||
self.root.dir
|
||
|
||
/-- The workspace's configuration. -/
|
||
def config (self : Workspace) : WorkspaceConfig :=
|
||
self.root.config.toWorkspaceConfig
|
||
|
||
/-- The workspace's `dir` joined with its `packagesDir` configuration. -/
|
||
def packagesDir (self : Workspace) : FilePath :=
|
||
self.dir / self.config.packagesDir
|
||
|
||
/-- The workspace's JSON manifest of packages. -/
|
||
def manifestFile (self : Workspace) : FilePath :=
|
||
self.packagesDir / manifestFileName
|
||
|
||
/-- The `List` of packages to the workspace. -/
|
||
def packageList (self : Workspace) : List Package :=
|
||
self.packageMap.revFold (fun pkgs _ pkg => pkg :: pkgs) []
|
||
|
||
/-- The `Array` of packages to the workspace. -/
|
||
def packageArray (self : Workspace) : Array Package :=
|
||
self.packageMap.fold (fun pkgs _ pkg => pkgs.push pkg) #[]
|
||
|
||
/-- Add a package to the workspace. -/
|
||
def addPackage (pkg : Package) (self : Workspace) : Workspace :=
|
||
{self with packageMap := self.packageMap.insert pkg.name pkg}
|
||
|
||
/-- Get a package within the workspace by name. -/
|
||
def findPackage? (pkg : Name) (self : Workspace) : Option Package :=
|
||
self.packageMap.find? pkg
|
||
|
||
/-- Check if the module is local to any package in the workspace. -/
|
||
def isLocalModule (mod : Name) (self : Workspace) : Bool :=
|
||
self.packageMap.any fun _ pkg => pkg.isLocalModule mod
|
||
|
||
/-- Check if the module is buildable by any package in the workspace. -/
|
||
def isBuildableModule (mod : Name) (self : Workspace) : Bool :=
|
||
self.packageMap.any fun _ pkg => pkg.isBuildableModule mod
|
||
|
||
/-- Locate the named module in the workspace (if it is local to it). -/
|
||
def findModule? (mod : Name) (self : Workspace) : Option Module :=
|
||
self.packageArray.findSome? (·.findModule? mod)
|
||
|
||
/-- Try to find a Lean library in the workspace with the given name. -/
|
||
def findLeanLib? (name : Name) (self : Workspace) : Option LeanLib :=
|
||
self.packageArray.findSome? fun pkg => pkg.findLeanLib? name
|
||
|
||
/-- Try to find a Lean executable in the workspace with the given name. -/
|
||
def findLeanExe? (name : Name) (self : Workspace) : Option LeanExe :=
|
||
self.packageArray.findSome? fun pkg => pkg.findLeanExe? name
|
||
|
||
/-- Try to find an external library in the workspace with the given name. -/
|
||
def findExternLib? (name : Name) (self : Workspace) : Option ExternLib :=
|
||
self.packageArray.findSome? fun pkg => pkg.findExternLib? name
|
||
|
||
/-- Try to find a target configuration in the workspace with the given name. -/
|
||
def findTargetConfig? (name : Name) (self : Workspace) : Option (Package × TargetConfig) :=
|
||
self.packageArray.findSome? fun pkg => pkg.findTargetConfig? name <&> (⟨pkg, ·⟩)
|
||
|
||
/-- Add a module facet to the workspace. -/
|
||
def addModuleFacetConfig (cfg : ModuleFacetConfig name) (self : Workspace) : Workspace :=
|
||
{self with moduleFacetConfigs := self.moduleFacetConfigs.insert cfg.name cfg}
|
||
|
||
/-- Try to find a module facet configuration in the workspace with the given name. -/
|
||
def findModuleFacetConfig? (name : Name) (self : Workspace) : Option (ModuleFacetConfig name) :=
|
||
self.moduleFacetConfigs.find? name
|
||
|
||
/-- Add a package facet to the workspace. -/
|
||
def addPackageFacetConfig (cfg : PackageFacetConfig name) (self : Workspace) : Workspace :=
|
||
{self with packageFacetConfigs := self.packageFacetConfigs.insert cfg.name cfg}
|
||
|
||
/-- Try to find a package facet configuration in the workspace with the given name. -/
|
||
def findPackageFacetConfig? (name : Name) (self : Workspace) : Option (PackageFacetConfig name) :=
|
||
self.packageFacetConfigs.find? name
|
||
|
||
/-- The `LEAN_PATH` of the workspace. -/
|
||
def leanPath (self : Workspace) : SearchPath :=
|
||
self.packageList.map (·.oleanDir)
|
||
|
||
/-- The `LEAN_SRC_PATH` of the workspace. -/
|
||
def leanSrcPath (self : Workspace) : SearchPath :=
|
||
self.packageList.map (·.srcDir)
|
||
|
||
/--
|
||
The shared library path of the workspace (e.g., for `--load-dynlib`).
|
||
This is added to the `sharedLibPathEnvVar` by `lake env`.
|
||
-/
|
||
def libPath (self : Workspace) : SearchPath :=
|
||
self.packageList.map (·.libDir)
|
||
|
||
/-- The `LeanPaths` of the workspace. -/
|
||
def leanPaths (self : Workspace) : LeanPaths where
|
||
oleanPath := self.packageList.map (·.oleanDir)
|
||
srcPath := self.packageList.map (·.srcDir)
|
||
|
||
/--
|
||
Rhe detected `LEAN_PATH` of the environment
|
||
augmented with the workspace's `leanPath` and Lake's `libDir`.
|
||
|
||
We include Lake's `oleanDir` at the end to ensure that same Lake package being
|
||
used to build is available to the environment (and thus, e.g., the Lean server).
|
||
Otherwise, it may fall back on whatever the default Lake instance is.
|
||
-/
|
||
def augmentedLeanPath (self : Workspace) : SearchPath :=
|
||
self.lakeEnv.leanPath ++ self.leanPath ++ [self.lakeEnv.lake.libDir]
|
||
|
||
/--
|
||
The detected `LEAN_SRC_PATH` of the environment
|
||
augmented with the workspace's `leanSrcPath` and Lake's `srcDir`.
|
||
|
||
We include Lake's `srcDir` at the end to ensure that same Lake package being
|
||
used to build is available to the environment (and thus, e.g., the Lean server).
|
||
Otherwise, it may fall back on whatever the default Lake instance is.
|
||
-/
|
||
def augmentedLeanSrcPath (self : Workspace) : SearchPath :=
|
||
self.lakeEnv.leanSrcPath ++ self.leanSrcPath ++ [self.lakeEnv.lake.srcDir]
|
||
|
||
/-
|
||
The detected `sharedLibPathEnv` value of the environment
|
||
augmented with the workspace's `libPath`.
|
||
-/
|
||
def augmentedSharedLibPath (self : Workspace) : SearchPath :=
|
||
self.lakeEnv.sharedLibPath ++ self.libPath
|
||
|
||
/--
|
||
The detected environment augmented with the Workspace's paths.
|
||
These are the settings use by `lake env` / `Lake.env` to run executables.
|
||
-/
|
||
def augmentedEnvVars (self : Workspace) : Array (String × Option String) :=
|
||
self.lakeEnv.installVars ++ #[
|
||
("LEAN_PATH", some self.augmentedLeanPath.toString),
|
||
("LEAN_SRC_PATH", some self.augmentedLeanSrcPath.toString),
|
||
(sharedLibPathEnvVar, some self.augmentedSharedLibPath.toString)
|
||
]
|