idris2Packages.buildIdris: add retroactive support for building a whole dependency tree with source

Changed files
+183 -64
pkgs
development
compilers
+101 -59
pkgs/development/compilers/idris2/build-idris.nix
···
# idrisLibraries = [ ];
# };
# in {
-
# lib = pkg.library { withSource = true; };
+
# lib1 = pkg.library { withSource = true; };
+
#
+
# # implicitly without source:
+
# lib2 = pkg.library';
+
#
# bin = pkg.executable;
# }
#
{
src,
-
ipkgName,
+
ipkgName, # ipkg filename without the extension
version ? "unversioned",
idrisLibraries, # Other libraries built with buildIdris
...
···
ipkgFileName = ipkgName + ".ipkg";
idrName = "idris2-${idris2.version}";
libSuffix = "lib/${idrName}";
-
propagatedIdrisLibraries = propagate idrisLibraryLibs;
-
libDirs = (lib.makeSearchPath libSuffix propagatedIdrisLibraries) + ":${idris2}/${idrName}";
+
libDirs = libs: (lib.makeSearchPath libSuffix libs) + ":${idris2}/${idrName}";
supportDir = "${idris2}/${idrName}/lib";
drvAttrs = builtins.removeAttrs attrs [
"ipkgName"
"idrisLibraries"
];
-
derivation = stdenv.mkDerivation (
-
finalAttrs:
-
drvAttrs
-
// {
-
pname = ipkgName;
-
inherit version;
-
src = src;
-
nativeBuildInputs = [
-
idris2
-
makeBinaryWrapper
-
] ++ attrs.nativeBuildInputs or [ ];
-
buildInputs = propagatedIdrisLibraries ++ attrs.buildInputs or [ ];
+
mkDerivation =
+
withSource:
+
let
+
applyWithSource = lib: if withSource then lib.withSource else lib;
+
propagatedIdrisLibraries = map applyWithSource (propagate idrisLibraryLibs);
+
in
+
stdenv.mkDerivation (
+
finalAttrs:
+
drvAttrs
+
// {
+
pname = ipkgName;
+
inherit src version;
+
nativeBuildInputs = [
+
idris2
+
makeBinaryWrapper
+
] ++ attrs.nativeBuildInputs or [ ];
+
buildInputs = propagatedIdrisLibraries ++ attrs.buildInputs or [ ];
-
env.IDRIS2_PACKAGE_PATH = libDirs;
+
env.IDRIS2_PACKAGE_PATH = libDirs propagatedIdrisLibraries;
-
buildPhase = ''
-
runHook preBuild
-
idris2 --build ${ipkgFileName}
-
runHook postBuild
-
'';
+
buildPhase = ''
+
runHook preBuild
+
idris2 --build ${ipkgFileName}
+
runHook postBuild
+
'';
-
passthru = {
-
inherit propagatedIdrisLibraries;
-
} // (attrs.passthru or { });
+
passthru = {
+
inherit propagatedIdrisLibraries;
+
} // (attrs.passthru or { });
-
shellHook = ''
-
export IDRIS2_PACKAGE_PATH="${finalAttrs.env.IDRIS2_PACKAGE_PATH}"
+
shellHook = ''
+
export IDRIS2_PACKAGE_PATH="${finalAttrs.env.IDRIS2_PACKAGE_PATH}"
+
'';
+
}
+
);
+
+
mkExecutable =
+
withSource:
+
let
+
derivation = mkDerivation withSource;
+
in
+
derivation.overrideAttrs {
+
installPhase = ''
+
runHook preInstall
+
mkdir -p $out/bin
+
scheme_app="$(find ./build/exec -name '*_app')"
+
if [ "$scheme_app" = ''' ]; then
+
mv -- build/exec/* $out/bin/
+
chmod +x $out/bin/*
+
# ^ remove after Idris2 0.8.0 is released. will be superfluous:
+
# https://github.com/idris-lang/Idris2/pull/3189
+
else
+
cd build/exec/*_app
+
rm -f ./libidris2_support.{so,dylib}
+
for file in *.so; do
+
bin_name="''${file%.so}"
+
mv -- "$file" "$out/bin/$bin_name"
+
+
wrapProgram "$out/bin/$bin_name" \
+
--prefix LD_LIBRARY_PATH : ${supportDir} \
+
--prefix DYLD_LIBRARY_PATH : ${supportDir}
+
done
+
fi
+
runHook postInstall
'';
-
}
-
);
-
in
-
{
-
executable = derivation.overrideAttrs {
-
installPhase = ''
-
runHook preInstall
-
mkdir -p $out/bin
-
scheme_app="$(find ./build/exec -name '*_app')"
-
if [ "$scheme_app" = ''' ]; then
-
mv -- build/exec/* $out/bin/
-
chmod +x $out/bin/*
-
# ^ remove after Idris2 0.8.0 is released. will be superfluous:
-
# https://github.com/idris-lang/Idris2/pull/3189
-
else
-
cd build/exec/*_app
-
rm -f ./libidris2_support.so
-
for file in *.so; do
-
bin_name="''${file%.so}"
-
mv -- "$file" "$out/bin/$bin_name"
-
wrapProgram "$out/bin/$bin_name" \
-
--prefix LD_LIBRARY_PATH : ${supportDir} \
-
--prefix DYLD_LIBRARY_PATH : ${supportDir}
-
done
-
fi
-
runHook postInstall
-
'';
-
};
+
# allow an executable's dependencies to be built with source. this is convenient when
+
# building a development shell for the exectuable using `mkShell`'s `inputsFrom`.
+
passthru = derivation.passthru // {
+
withSource = mkExecutable true;
+
};
+
};
-
library =
-
{
-
withSource ? false,
-
}:
+
mkLibrary =
+
withSource:
let
installCmd = if withSource then "--install-with-src" else "--install";
+
derivation = mkDerivation withSource;
in
derivation.overrideAttrs {
installPhase = ''
···
idris2 ${installCmd} ${ipkgFileName}
runHook postInstall
'';
+
+
# allow a library built without source to be changed to one with source
+
# via a passthru attribute; i.e. `my-pkg.library'.withSource`.
+
# this is convenient because a library derivation can be distributed as
+
# without-source by default but downstream projects can still build it
+
# with-source. We surface this regardless of whether the original library
+
# was built with source because that allows downstream to call this
+
# property unconditionally.
+
passthru = derivation.passthru // {
+
withSource = mkLibrary true;
+
};
};
+
+
in
+
{
+
executable = mkExecutable false;
+
+
library =
+
{
+
withSource ? false,
+
}:
+
mkLibrary withSource;
+
+
# Make a library without source; you can still use the `withSource` attribute
+
# on the resulting derivation to build the library with source at a later time.
+
library' = mkLibrary false;
}
+82 -5
pkgs/development/compilers/idris2/tests.nix
···
{
testName,
buildIdrisArgs,
-
makeExecutable,
+
# function that takes result of `buildIdris` and transforms it (commonly
+
# by calling `.executable` or `.library {}` upon it):
+
transformBuildIdrisOutput,
expectedTree,
}:
let
-
final = pkg: if makeExecutable then pkg.executable else pkg.library { };
-
idrisPkg = final (idris2Packages.buildIdris buildIdrisArgs);
+
idrisPkg = transformBuildIdrisOutput (idris2Packages.buildIdris buildIdrisArgs);
in
runCommand "${pname}-${testName}"
{
···
EOF
'';
};
-
makeExecutable = false;
+
transformBuildIdrisOutput = pkg: pkg.library { withSource = false; };
expectedTree = ''
`-- lib
`-- idris2-0.7.0
···
5 directories, 3 files'';
};
+
buildLibraryWithSource = testBuildIdris {
+
testName = "library-with-source-package";
+
buildIdrisArgs = {
+
ipkgName = "pkg";
+
idrisLibraries = [ idris2Packages.idris2Api ];
+
src = runCommand "library-package-src" { } ''
+
mkdir $out
+
+
cat > $out/Main.idr <<EOF
+
module Main
+
+
import Compiler.ANF -- from Idris2Api
+
+
hello : String
+
hello = "world"
+
EOF
+
+
cat > $out/pkg.ipkg <<EOF
+
package pkg
+
modules = Main
+
depends = idris2
+
EOF
+
'';
+
};
+
transformBuildIdrisOutput = pkg: pkg.library { withSource = true; };
+
expectedTree = ''
+
`-- lib
+
`-- idris2-0.7.0
+
`-- pkg-0
+
|-- 2023090800
+
| |-- Main.ttc
+
| `-- Main.ttm
+
|-- Main.idr
+
`-- pkg.ipkg
+
+
5 directories, 4 files'';
+
};
+
+
buildLibraryWithSourceRetroactively = testBuildIdris {
+
testName = "library-with-source-retro-package";
+
buildIdrisArgs = {
+
ipkgName = "pkg";
+
idrisLibraries = [ idris2Packages.idris2Api ];
+
src = runCommand "library-package-src" { } ''
+
mkdir $out
+
+
cat > $out/Main.idr <<EOF
+
module Main
+
+
import Compiler.ANF -- from Idris2Api
+
+
hello : String
+
hello = "world"
+
EOF
+
+
cat > $out/pkg.ipkg <<EOF
+
package pkg
+
modules = Main
+
depends = idris2
+
EOF
+
'';
+
};
+
transformBuildIdrisOutput = pkg: pkg.library'.withSource;
+
expectedTree = ''
+
`-- lib
+
`-- idris2-0.7.0
+
`-- pkg-0
+
|-- 2023090800
+
| |-- Main.ttc
+
| `-- Main.ttm
+
|-- Main.idr
+
`-- pkg.ipkg
+
+
5 directories, 4 files'';
+
};
+
buildExecutable = testBuildIdris {
testName = "executable-package";
buildIdrisArgs = {
···
EOF
'';
};
-
makeExecutable = true;
+
transformBuildIdrisOutput = pkg: pkg.executable;
expectedTree = ''
`-- bin
`-- mypkg