Skip to content

Commit

Permalink
idris2Packages.buildIdris: add retroactive support for building a who…
Browse files Browse the repository at this point in the history
…le dependency tree with source
  • Loading branch information
mattpolzin committed Oct 26, 2024
1 parent e3b7ada commit 8079c8b
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 64 deletions.
160 changes: 101 additions & 59 deletions pkgs/development/compilers/idris2/build-idris.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
# 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
...
Expand All @@ -44,78 +48,91 @@ let
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 propagatedIdrisLibraries;

env.IDRIS2_PACKAGE_PATH = libDirs;
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 = ''
Expand All @@ -125,5 +142,30 @@ in
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;
}
87 changes: 82 additions & 5 deletions pkgs/development/compilers/idris2/tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ let
{
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}"
{
Expand Down Expand Up @@ -140,7 +141,7 @@ in
EOF
'';
};
makeExecutable = false;
transformBuildIdrisOutput = pkg: pkg.library { withSource = false; };
expectedTree = ''
`-- lib
`-- idris2-0.7.0
Expand All @@ -153,6 +154,82 @@ in
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 = {
Expand All @@ -176,7 +253,7 @@ in
EOF
'';
};
makeExecutable = true;
transformBuildIdrisOutput = pkg: pkg.executable;
expectedTree = ''
`-- bin
`-- mypkg
Expand Down

0 comments on commit 8079c8b

Please sign in to comment.