{ pkgs ? import {} }: with pkgs; rec { eggCache = { name ? "eggs", eggs, hash, includeDependencies ? true, includeTestDependencies ? false, }: runCommand name { buildInputs = [ chicken ]; outputHash = hash; outputHashMode = "recursive"; CHICKEN_EGG_CACHE = "eggs"; } '' chicken-install -retrieve \ ${lib.optionalString (includeDependencies) "-recursive"} \ ${lib.optionalString (includeTestDependencies) "-test"} \ ${if builtins.typeOf eggs == "path" then "-from-list ${eggs}" else if builtins.typeOf eggs == "list" then lib.concatStringsSep " " (map (egg: "${egg.name}:${egg.version}") eggs) else ""} mv -T $CHICKEN_EGG_CACHE $out rm -f $out/*/STATUS rm -f $out/*/TIMESTAMP ''; eggRepository = { name ? "eggs", src ? null, eggCache ? src, buildInputs ? [], shellHook ? "", repositoryPath ? "lib/chicken/${toString chicken.binaryVersion}", ... } @ args: let isEgg = with builtins; file: pathExists "${eggCache}/${file}/VERSION"; cachedEggs = with builtins; filter isEgg (attrNames (readDir eggCache)); setupEnvironmentPhase = '' export CHICKEN_EGG_CACHE=$TMPDIR/cache export CHICKEN_INSTALL_PREFIX=$TMPDIR/build export CHICKEN_INSTALL_REPOSITORY=$TMPDIR/build/${repositoryPath} export CHICKEN_REPOSITORY_PATH=$TMPDIR/build/${repositoryPath}:$CHICKEN_REPOSITORY_PATH export CHICKEN_INCLUDE_PATH=$TMPDIR/build/share:$CHICKEN_INCLUDE_PATH ''; offlineChickenInstall = writeShellScriptBin "chicken-install" '' test -d $TMPDIR/eggs || cp -R -L ${eggCache} $TMPDIR/eggs test -f $TMPDIR/setup.defaults || cat > $TMPDIR/setup.defaults <)) EOF exec ${chicken}/bin/chicken-install -defaults $TMPDIR/setup.defaults "$@" ''; in stdenv.mkDerivation (args // { inherit name setupEnvironmentPhase; buildInputs = [ offlineChickenInstall chicken makeWrapper ] ++ buildInputs; shellHook = setupEnvironmentPhase + shellHook; prePhases = [ "saveEnvironmentPhase" ]; preBuildPhases = [ "setupEnvironmentPhase" ]; preInstallPhases = [ "restoreEnvironmentPhase" ]; saveEnvironmentPhase = '' declare -p CHICKEN_REPOSITORY_PATH CHICKEN_INCLUDE_PATH > $TMPDIR/.env ''; restoreEnvironmentPhase = '' source $TMPDIR/.env ''; buildPhase = '' runHook preBuild if chicken-install -dry-run >/dev/null 2>error.log then chicken-install elif [ $? -eq 3 ] then chicken-install ${lib.escapeShellArgs cachedEggs} else cat error.log false fi runHook postBuild ''; installPhase = '' runHook preInstall mv -T $CHICKEN_INSTALL_PREFIX $out if [ -d $out/${repositoryPath} ]; then for f in $out/${repositoryPath}/*.egg-info; do substituteInPlace $f --replace $CHICKEN_INSTALL_PREFIX $out done fi if [ -d $out/bin ]; then for bin in $out/bin/*; do wrapProgram $bin \ --prefix CHICKEN_INCLUDE_PATH : $out/share:$CHICKEN_INCLUDE_PATH \ --prefix CHICKEN_REPOSITORY_PATH : $out/${repositoryPath}:$CHICKEN_REPOSITORY_PATH \ --prefix LD_LIBRARY_PATH : ${chicken}/lib:$LD_LIBRARY_PATH done fi runHook postInstall ''; }); eggProgram = { name, postInstall ? "", repositoryPath ? "lib/${name}", ... } @ args: eggRepository (args // { inherit name repositoryPath; postInstall = '' if [ -d $out/${repositoryPath} ]; then find $out/${repositoryPath} -type f -not -name \*.so -delete fi '' + postInstall; }); }