237 lines
7.1 KiB
Nix
237 lines
7.1 KiB
Nix
# buildLakePackage: build Lean 4 projects that use the Lake build system.
|
|
#
|
|
# Dependencies can be provided in two ways:
|
|
# - `leanDeps`: nix-packaged Lean libraries, injected via
|
|
# `lake --packages` and propagated transitively via LEAN_PATH.
|
|
# - `lakeHash`: SRI hash for a fetchLakeDeps FOD that clones git
|
|
# dependencies listed in lake-manifest.json (like buildGoModule's
|
|
# vendorHash). Not needed when all deps are in `leanDeps`.
|
|
{
|
|
lib,
|
|
stdenv,
|
|
lean4,
|
|
gitMinimal,
|
|
cacert,
|
|
jq,
|
|
writeText,
|
|
stdenvNoCC,
|
|
}:
|
|
|
|
let
|
|
fetchLakeDeps = import ./fetch-lake-deps.nix {
|
|
inherit
|
|
lib
|
|
stdenvNoCC
|
|
gitMinimal
|
|
cacert
|
|
jq
|
|
;
|
|
};
|
|
in
|
|
|
|
lib.extendMkDerivation {
|
|
constructDrv = stdenv.mkDerivation;
|
|
excludeDrvArgNames = [
|
|
"lakeHash"
|
|
"lakeDeps"
|
|
"leanDeps"
|
|
"buildTargets"
|
|
"isLibrary"
|
|
"leanPackageName"
|
|
"overrideLakeDepsAttrs"
|
|
];
|
|
extendDrvArgs =
|
|
finalAttrs:
|
|
{
|
|
pname,
|
|
version,
|
|
nativeBuildInputs ? [ ],
|
|
passthru ? { },
|
|
|
|
# SRI hash for the Lake dependencies FOD (null = all deps nix-managed).
|
|
lakeHash ? null,
|
|
# Pre-built Lake dependencies derivation (overrides lakeHash).
|
|
lakeDeps ? null,
|
|
# Nix-packaged Lean libraries, injected via lake --packages.
|
|
leanDeps ? [ ],
|
|
# Lake package name as declared in lakefile (defaults to pname).
|
|
leanPackageName ? finalAttrs.pname,
|
|
# Lake build targets (empty = default targets).
|
|
buildTargets ? [ ],
|
|
# Library (install .olean tree) or executable (install binaries only).
|
|
isLibrary ? true,
|
|
# Override the FOD derivation attrs.
|
|
overrideLakeDepsAttrs ? (finalAttrs: previousAttrs: { }),
|
|
|
|
meta ? { },
|
|
|
|
...
|
|
}@args:
|
|
let
|
|
leanPackageName = args.leanPackageName or finalAttrs.pname;
|
|
|
|
allLeanDeps = lib.unique (
|
|
builtins.concatMap (dep: [ dep ] ++ (dep.passthru.allLeanDeps or [ ])) leanDeps
|
|
);
|
|
|
|
computedLakeDeps =
|
|
if lakeDeps != null then
|
|
lakeDeps
|
|
else if lakeHash == null then
|
|
null
|
|
else
|
|
(fetchLakeDeps {
|
|
inherit (finalAttrs) src pname version;
|
|
hash = lakeHash;
|
|
sourceRoot = finalAttrs.sourceRoot or "";
|
|
patches = finalAttrs.patches or [ ];
|
|
prePatch = finalAttrs.prePatch or "";
|
|
postPatch = finalAttrs.postPatch or "";
|
|
excludePackages = builtins.map (dep: dep.passthru.lakePackageName or dep.pname) allLeanDeps;
|
|
}).overrideAttrs
|
|
(lib.toExtension overrideLakeDepsAttrs);
|
|
|
|
# Nix-managed dep overrides, generated at eval time.
|
|
# --packages takes precedence over .lake/package-overrides.json.
|
|
overridesFile = writeText "lake-overrides.json" (
|
|
builtins.toJSON {
|
|
schemaVersion = "1.2.0";
|
|
packages = map (dep: {
|
|
type = "path";
|
|
name = dep.passthru.lakePackageName or dep.pname;
|
|
inherited = false;
|
|
dir = "${dep}";
|
|
}) allLeanDeps;
|
|
}
|
|
);
|
|
in
|
|
{
|
|
strictDeps = true;
|
|
__structuredAttrs = true;
|
|
|
|
nativeBuildInputs = nativeBuildInputs ++ [
|
|
lean4
|
|
gitMinimal
|
|
jq
|
|
];
|
|
|
|
propagatedBuildInputs = lib.optionals isLibrary leanDeps;
|
|
buildInputs = lib.optionals (!isLibrary) leanDeps;
|
|
|
|
configurePhase =
|
|
args.configurePhase or ''
|
|
runHook preConfigure
|
|
|
|
export HOME="$TMPDIR"
|
|
|
|
# Disable cloud caching and Reservoir lookups.
|
|
export LAKE_NO_CACHE=1
|
|
export RESERVOIR_API_URL=""
|
|
export LEAN_CC="${stdenv.cc}/bin/cc"
|
|
|
|
if [ -n "''${LEAN_PATH:-}" ]; then
|
|
echo "buildLakePackage: LEAN_PATH=$LEAN_PATH"
|
|
fi
|
|
|
|
${lib.optionalString (computedLakeDeps != null) ''
|
|
mkdir -p .lake/packages
|
|
for dep in ${computedLakeDeps}/*; do
|
|
depName="$(basename "$dep")"
|
|
cp -r "$dep" ".lake/packages/$depName"
|
|
chmod -R u+w ".lake/packages/$depName"
|
|
done
|
|
|
|
# FOD deps use package-overrides.json (the on-disk mechanism).
|
|
# Nix-managed deps use --packages (the CLI mechanism, takes precedence).
|
|
jq -n --argjson pkgs "$(
|
|
for dep in .lake/packages/*/; do
|
|
[ -d "$dep" ] || continue
|
|
depName="$(basename "$dep")"
|
|
jq -n --arg name "$depName" --arg dir ".lake/packages/$depName" \
|
|
'{type: "path", name: $name, inherited: false, dir: $dir}'
|
|
done | jq -s '.'
|
|
)" '{schemaVersion: "1.2.0", packages: $pkgs}' > .lake/package-overrides.json
|
|
''}
|
|
|
|
runHook postConfigure
|
|
'';
|
|
|
|
buildPhase =
|
|
args.buildPhase or ''
|
|
runHook preBuild
|
|
|
|
local targets="${lib.concatStringsSep " " buildTargets}"
|
|
echo "buildLakePackage: building ''${targets:-default targets}"
|
|
|
|
lake build --no-ansi --packages=${overridesFile} $targets
|
|
|
|
runHook postBuild
|
|
'';
|
|
|
|
installPhase =
|
|
args.installPhase or (
|
|
if isLibrary then
|
|
''
|
|
runHook preInstall
|
|
|
|
# Install the complete Lake package tree.
|
|
cp -rT . "$out"
|
|
|
|
# Remove build-time artifacts.
|
|
rm -rf "$out/.lake/packages"
|
|
rm -f "$out/.lake/package-overrides.json"
|
|
|
|
# Reconcile config trace directory naming.
|
|
if [ -d "$out/.lake/config/[anonymous]" ]; then
|
|
mv "$out/.lake/config/[anonymous]" "$out/.lake/config/${leanPackageName}"
|
|
fi
|
|
|
|
if [ -d "$out/.lake/build/ir" ]; then
|
|
find "$out/.lake/build/ir" -name '*.setup.json' -delete
|
|
fi
|
|
|
|
rm -rf "$out/.lake/config"
|
|
|
|
# Setup hook propagates LEAN_PATH to downstream packages.
|
|
mkdir -p "$out/nix-support"
|
|
cp ${./setup-hook.sh} "$out/nix-support/setup-hook"
|
|
|
|
if [ -d "$out/.lake/build/bin" ]; then
|
|
mkdir -p "$out/bin"
|
|
for exe in "$out/.lake/build/bin"/*; do
|
|
if [ -f "$exe" ] && [ -x "$exe" ]; then
|
|
ln -s "../.lake/build/bin/$(basename "$exe")" "$out/bin/$(basename "$exe")"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
runHook postInstall
|
|
''
|
|
else
|
|
''
|
|
runHook preInstall
|
|
|
|
if [ -d .lake/build/bin ]; then
|
|
mkdir -p "$out/bin"
|
|
find .lake/build/bin -type f -executable \
|
|
-exec install -Dm755 {} "$out/bin/" \;
|
|
fi
|
|
|
|
runHook postInstall
|
|
''
|
|
);
|
|
|
|
passthru = passthru // {
|
|
inherit computedLakeDeps lean4 allLeanDeps;
|
|
lakePackageName = leanPackageName;
|
|
overrideLakeDepsAttrs = lib.toExtension overrideLakeDepsAttrs;
|
|
};
|
|
|
|
meta = meta // {
|
|
# Note: This conflates the platforms that the Lean compiler can run on (a package build system) and the platforms the Lean compiler
|
|
# can target (build host)
|
|
platforms = meta.platforms or lean4.meta.platforms;
|
|
};
|
|
};
|
|
}
|