at master 8.3 kB view raw
1# Generic builder for lua packages 2{ 3 lib, 4 lua, 5 wrapLua, 6 luarocks_bootstrap, 7 writeTextFile, 8 9 # Whether the derivation provides a lua module or not. 10 luarocksCheckHook, 11 luaLib, 12}: 13 14{ 15 pname, 16 version, 17 # we need rockspecVersion to find the .rockspec even when version changes 18 rockspecVersion ? version, 19 20 # by default prefix `name` e.g. "lua5.2-${name}" 21 namePrefix ? "${lua.pname}${lib.versions.majorMinor lua.version}-", 22 23 # Dependencies for building the package 24 buildInputs ? [ ], 25 26 # Dependencies needed for running the checkPhase. 27 # These are added to nativeBuildInputs when doCheck = true. 28 nativeCheckInputs ? [ ], 29 30 # propagate build dependencies so in case we have A -> B -> C, 31 # C can import package A propagated by B 32 propagatedBuildInputs ? [ ], 33 34 # used to disable derivation, useful for specific lua versions 35 # TODO move from this setting meta.broken to a 'disabled' attribute on the 36 # package, then use that to skip/include in each lua${ver}Packages set? 37 disabled ? false, 38 39 # Additional arguments to pass to the makeWrapper function, which wraps 40 # generated binaries. 41 makeWrapperArgs ? [ ], 42 43 # Skip wrapping of lua programs altogether 44 dontWrapLuaPrograms ? false, 45 doCheck ? false, 46 # Non-Lua / system (e.g. C library) dependencies. Is a list of deps, where 47 # each dep is either a derivation, or an attribute set like 48 # { name = "rockspec external_dependencies key"; dep = derivation; } 49 # The latter is used to work-around luarocks having a problem with 50 # multiple-output derivations as external deps: 51 # https://github.com/luarocks/luarocks/issues/766<Paste> 52 externalDeps ? [ ], 53 54 # Appended to the generated luarocks config 55 extraConfig ? "", 56 57 # transparent mapping nix <-> lua used as LUAROCKS_CONFIG 58 # Refer to https://github.com/luarocks/luarocks/wiki/Config-file-format for specs 59 luarocksConfig ? { }, 60 61 # relative to srcRoot, path to the rockspec to use when using rocks 62 rockspecFilename ? null, 63 64 # must be set for packages that don't have a rock 65 knownRockspec ? null, 66 67 ... 68}@attrs: 69 70# Keep extra attributes from `attrs`, e.g., `patchPhase', etc. 71 72let 73 74 # TODO fix warnings "Couldn't load rockspec for ..." during manifest 75 # construction -- from initial investigation, appears it will require 76 # upstream luarocks changes to fix cleanly (during manifest construction, 77 # luarocks only looks for rockspecs in the default/system tree instead of all 78 # configured trees) 79 luarocks_config = "luarocks-config.lua"; 80 81 luarocksDrv = luaLib.toLuaModule ( 82 lua.stdenv.mkDerivation ( 83 self: 84 attrs 85 // { 86 87 name = namePrefix + self.pname + "-" + self.version; 88 inherit rockspecVersion; 89 90 __structuredAttrs = true; 91 env = { 92 LUAROCKS_CONFIG = self.configFile; 93 } 94 // attrs.env or { }; 95 96 generatedRockspecFilename = "./${self.pname}-${self.rockspecVersion}.rockspec"; 97 98 nativeBuildInputs = [ 99 lua # for lua.h 100 wrapLua 101 luarocks_bootstrap 102 ]; 103 104 inherit 105 doCheck 106 extraConfig 107 rockspecFilename 108 knownRockspec 109 externalDeps 110 nativeCheckInputs 111 ; 112 113 buildInputs = 114 let 115 # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ] 116 externalDeps' = lib.filter (dep: !lib.isDerivation dep) self.externalDeps; 117 in 118 [ luarocks_bootstrap ] 119 ++ buildInputs 120 ++ lib.optionals self.doCheck ([ luarocksCheckHook ] ++ self.nativeCheckInputs) 121 ++ (map (d: d.dep) externalDeps'); 122 123 # propagate lua to active setup-hook in nix-shell 124 propagatedBuildInputs = propagatedBuildInputs ++ [ lua ]; 125 126 # @-patterns do not capture formal argument default values, so we need to 127 # explicitly inherit this for it to be available as a shell variable in the 128 # builder 129 rocksSubdir = "${self.pname}-${self.version}-rocks"; 130 131 configFile = writeTextFile { 132 name = self.pname + "-luarocks-config.lua"; 133 text = self.luarocks_content; 134 }; 135 136 luarocks_content = (lib.generators.toLua { asBindings = true; } self.luarocksConfig) + '' 137 138 ${self.extraConfig} 139 ''; 140 141 # TODO make it the default variable 142 luarocksConfig = 143 let 144 externalDepsGenerated = lib.filter (drv: !drv ? luaModule) ( 145 self.nativeBuildInputs ++ self.propagatedBuildInputs ++ self.buildInputs 146 ); 147 148 generatedConfig = luaLib.generateLuarocksConfig { 149 externalDeps = lib.unique (self.externalDeps ++ externalDepsGenerated); 150 local_cache = ""; 151 152 # To prevent collisions when creating environments, we install the rock 153 # files into per-package subdirectories 154 rocks_subdir = self.rocksSubdir; 155 156 # Filter out the lua derivation itself from the Lua module dependency 157 # closure, as it doesn't have a rock tree :) 158 # luaLib.hasLuaModule 159 requiredLuaRocks = lib.filter luaLib.hasLuaModule ( 160 lua.pkgs.requiredLuaModules (self.nativeBuildInputs ++ self.propagatedBuildInputs) 161 ); 162 }; 163 164 luarocksConfig' = lib.recursiveUpdate luarocksConfig ( 165 lib.optionalAttrs (attrs ? extraVariables) ( 166 lib.warn "extraVariables in buildLuarocksPackage is deprecated, use luarocksConfig instead" { 167 variables = attrs.extraVariables; 168 } 169 ) 170 ); 171 in 172 lib.recursiveUpdate generatedConfig luarocksConfig'; 173 174 configurePhase = '' 175 runHook preConfigure 176 '' 177 + lib.optionalString (self.rockspecFilename == null) '' 178 rockspecFilename="${self.generatedRockspecFilename}" 179 '' 180 + lib.optionalString (self.knownRockspec != null) '' 181 # prevents the following type of error: 182 # Inconsistency between rockspec filename (42fm1b3d7iv6fcbhgm9674as3jh6y2sh-luv-1.22.0-1.rockspec) and its contents (luv-1.22.0-1.rockspec) 183 rockspecFilename="$TMP/$(stripHash ${self.knownRockspec})" 184 cp ${self.knownRockspec} "$rockspecFilename" 185 '' 186 + '' 187 runHook postConfigure 188 ''; 189 190 buildPhase = '' 191 runHook preBuild 192 193 source ${lua}/nix-support/utils.sh 194 nix_debug "Using LUAROCKS_CONFIG=$LUAROCKS_CONFIG" 195 196 LUAROCKS_EXTRA_ARGS="" 197 if (( ''${NIX_DEBUG:-0} >= 1 )); then 198 LUAROCKS_EXTRA_ARGS=" --verbose" 199 fi 200 201 runHook postBuild 202 ''; 203 204 postFixup = 205 lib.optionalString (!dontWrapLuaPrograms) '' 206 wrapLuaPrograms 207 '' 208 + attrs.postFixup or ""; 209 210 installPhase = '' 211 runHook preInstall 212 213 # work around failing luarocks test for Write access 214 mkdir -p $out 215 216 # luarocks make assumes sources are available in cwd 217 # After the build is complete, it also installs the rock. 218 # If no argument is given, it looks for a rockspec in the current directory 219 # but some packages have several rockspecs in their source directory so 220 # we force the use of the upper level since it is 221 # the sole rockspec in that folder 222 # maybe we could reestablish dependency checking via passing --rock-trees 223 224 nix_debug "ROCKSPEC $rockspecFilename" 225 luarocks $LUAROCKS_EXTRA_ARGS make --deps-mode=all --tree=$out ''${rockspecFilename} 226 227 runHook postInstall 228 ''; 229 230 checkPhase = '' 231 runHook preCheck 232 luarocks test 233 runHook postCheck 234 ''; 235 236 shellHook = '' 237 runHook preShell 238 export LUAROCKS_CONFIG="$PWD/${luarocks_config}"; 239 runHook postShell 240 ''; 241 242 passthru = { 243 inherit lua; 244 } 245 // attrs.passthru or { }; 246 247 meta = { 248 platforms = lua.meta.platforms; 249 # add extra maintainer(s) to every package 250 maintainers = (attrs.meta.maintainers or [ ]) ++ [ ]; 251 broken = disabled; 252 } 253 // attrs.meta or { }; 254 } 255 ) 256 ); 257in 258luarocksDrv