at master 5.0 kB view raw
1{ 2 stdenv, 3 lib, 4 idris2, 5 makeBinaryWrapper, 6}: 7# Usage: let 8# pkg = idris2Packages.buildIdris { 9# src = ...; 10# ipkgName = "my-pkg"; 11# idrisLibraries = [ ]; 12# }; 13# in { 14# lib1 = pkg.library { withSource = true; }; 15# 16# # implicitly without source: 17# lib2 = pkg.library'; 18# 19# bin = pkg.executable; 20# } 21# 22{ 23 src, 24 ipkgName, # ipkg filename without the extension 25 version ? "unversioned", 26 idrisLibraries, # Other libraries built with buildIdris 27 ... 28}@attrs: 29 30let 31 # loop over idrisLibraries and normalize them by turning any that are 32 # direct outputs of the buildIdris function into the `.library {}` 33 # property. 34 idrisLibraryLibs = map ( 35 idrisLib: 36 if lib.isDerivation idrisLib then 37 idrisLib 38 else if builtins.isFunction idrisLib then 39 idrisLib { } 40 else if (builtins.isAttrs idrisLib && idrisLib ? "library") then 41 idrisLib.library { } 42 else 43 throw "Found an Idris2 library dependency that was not the result of the buildIdris function" 44 ) idrisLibraries; 45 46 propagate = 47 libs: lib.unique (lib.concatMap (nextLib: [ nextLib ] ++ nextLib.propagatedIdrisLibraries) libs); 48 ipkgFileName = ipkgName + ".ipkg"; 49 idrName = "idris2-${idris2.version}"; 50 libSuffix = "lib/${idrName}"; 51 libDirs = libs: (lib.makeSearchPath libSuffix libs) + ":${idris2}/${idrName}"; 52 supportDir = "${idris2}/${idrName}/lib"; 53 drvAttrs = builtins.removeAttrs attrs [ 54 "ipkgName" 55 "idrisLibraries" 56 ]; 57 58 mkDerivation = 59 withSource: 60 let 61 applyWithSource = lib: if withSource then lib.withSource else lib; 62 propagatedIdrisLibraries = map applyWithSource (propagate idrisLibraryLibs); 63 in 64 stdenv.mkDerivation ( 65 finalAttrs: 66 drvAttrs 67 // { 68 pname = ipkgName; 69 inherit src version; 70 nativeBuildInputs = [ 71 idris2 72 makeBinaryWrapper 73 ] 74 ++ attrs.nativeBuildInputs or [ ]; 75 buildInputs = propagatedIdrisLibraries ++ attrs.buildInputs or [ ]; 76 77 env.IDRIS2_PACKAGE_PATH = libDirs propagatedIdrisLibraries; 78 79 buildPhase = '' 80 runHook preBuild 81 idris2 --build ${ipkgFileName} 82 runHook postBuild 83 ''; 84 85 passthru = { 86 inherit propagatedIdrisLibraries; 87 } 88 // (attrs.passthru or { }); 89 90 shellHook = '' 91 export IDRIS2_PACKAGE_PATH="${finalAttrs.env.IDRIS2_PACKAGE_PATH}" 92 ''; 93 } 94 ); 95 96 mkExecutable = 97 withSource: 98 let 99 derivation = mkDerivation withSource; 100 in 101 derivation.overrideAttrs { 102 installPhase = '' 103 runHook preInstall 104 mkdir -p $out/bin 105 scheme_app="$(find ./build/exec -name '*_app')" 106 if [ "$scheme_app" = ''' ]; then 107 mv -- build/exec/* $out/bin/ 108 chmod +x $out/bin/* 109 # ^ remove after Idris2 0.8.0 is released. will be superfluous: 110 # https://github.com/idris-lang/Idris2/pull/3189 111 else 112 cd build/exec/*_app 113 rm -f ./libidris2_support.{so,dylib} 114 for file in *.so; do 115 bin_name="''${file%.so}" 116 mv -- "$file" "$out/bin/$bin_name" 117 118 wrapProgram "$out/bin/$bin_name" \ 119 --prefix LD_LIBRARY_PATH : ${supportDir} \ 120 --prefix DYLD_LIBRARY_PATH : ${supportDir} 121 done 122 fi 123 runHook postInstall 124 ''; 125 126 # allow an executable's dependencies to be built with source. this is convenient when 127 # building a development shell for the executable using `mkShell`'s `inputsFrom`. 128 passthru = derivation.passthru // { 129 withSource = mkExecutable true; 130 }; 131 }; 132 133 mkLibrary = 134 withSource: 135 let 136 installCmd = if withSource then "--install-with-src" else "--install"; 137 derivation = mkDerivation withSource; 138 in 139 derivation.overrideAttrs { 140 installPhase = '' 141 runHook preInstall 142 mkdir -p $out/${libSuffix} 143 export IDRIS2_PREFIX=$out/lib 144 idris2 ${installCmd} ${ipkgFileName} 145 runHook postInstall 146 ''; 147 148 # allow a library built without source to be changed to one with source 149 # via a passthru attribute; i.e. `my-pkg.library'.withSource`. 150 # this is convenient because a library derivation can be distributed as 151 # without-source by default but downstream projects can still build it 152 # with-source. We surface this regardless of whether the original library 153 # was built with source because that allows downstream to call this 154 # property unconditionally. 155 passthru = derivation.passthru // { 156 withSource = mkLibrary true; 157 }; 158 }; 159 160in 161{ 162 executable = mkExecutable false; 163 164 library = 165 { 166 withSource ? false, 167 }: 168 mkLibrary withSource; 169 170 # Make a library without source; you can still use the `withSource` attribute 171 # on the resulting derivation to build the library with source at a later time. 172 library' = mkLibrary false; 173}