nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1# Generic builder for lua packages
2{ lib
3, lua
4, wrapLua
5# Whether the derivation provides a lua module or not.
6, toLuaModule
7}:
8
9{
10name ? "${attrs.pname}-${attrs.version}"
11
12, version
13
14# by default prefix `name` e.g. "lua5.2-${name}"
15, namePrefix ? if lua.pkgs.isLuaJIT
16 then lua.name + "-"
17 else "lua" + lua.luaversion + "-"
18
19# Dependencies for building the package
20, buildInputs ? []
21
22# Dependencies needed for running the checkPhase.
23# These are added to buildInputs when doCheck = true.
24, checkInputs ? []
25
26# propagate build dependencies so in case we have A -> B -> C,
27# C can import package A propagated by B
28, propagatedBuildInputs ? []
29, propagatedNativeBuildInputs ? []
30
31# used to disable derivation, useful for specific lua versions
32# TODO move from this setting meta.broken to a 'disabled' attribute on the
33# package, then use that to skip/include in each lua${ver}Packages set?
34, disabled ? false
35
36# Additional arguments to pass to the makeWrapper function, which wraps
37# generated binaries.
38, makeWrapperArgs ? []
39
40# Skip wrapping of lua programs altogether
41, dontWrapLuaPrograms ? false
42
43, meta ? {}
44
45, passthru ? {}
46, doCheck ? false
47
48# Non-Lua / system (e.g. C library) dependencies. Is a list of deps, where
49# each dep is either a derivation, or an attribute set like
50# { name = "rockspec external_dependencies key"; dep = derivation; }
51# The latter is used to work-around luarocks having a problem with
52# multiple-output derivations as external deps:
53# https://github.com/luarocks/luarocks/issues/766<Paste>
54, externalDeps ? lib.unique (lib.filter (drv: !drv ? luaModule) (propagatedBuildInputs ++ buildInputs))
55
56# Appended to the generated luarocks config
57, extraConfig ? ""
58# Inserted into the generated luarocks config in the "variables" table
59, extraVariables ? {}
60# The two above arguments have access to builder variables -- e.g. to $out
61
62# relative to srcRoot, path to the rockspec to use when using rocks
63, rockspecFilename ? "../*.rockspec"
64
65# must be set for packages that don't have a rock
66, knownRockspec ? null
67
68, ... } @ attrs:
69
70
71# Keep extra attributes from `attrs`, e.g., `patchPhase', etc.
72
73let
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 luarocks_content = let
81 extraVariablesStr = lib.concatStringsSep "\n "
82 (lib.mapAttrsToList (k: v: "${k}='${v}';") extraVariables);
83 in ''
84 local_cache = ""
85 -- To prevent collisions when creating environments, we install the rock
86 -- files into per-package subdirectories
87 rocks_subdir = '${rocksSubdir}'
88 -- Then we need to tell luarocks where to find the rock files per
89 -- dependency
90 rocks_trees = {
91 ${lib.concatStringsSep "\n, " rocksTrees}
92 }
93 '' + lib.optionalString lua.pkgs.isLuaJIT ''
94 -- Luajit provides some additional functionality built-in; this exposes
95 -- that to luarock's dependency system
96 rocks_provided = {
97 jit='${lua.luaversion}-1';
98 ffi='${lua.luaversion}-1';
99 luaffi='${lua.luaversion}-1';
100 bit='${lua.luaversion}-1';
101 }
102 '' + ''
103 -- For single-output external dependencies
104 external_deps_dirs = {
105 ${lib.concatStringsSep "\n, " externalDepsDirs}
106 }
107 variables = {
108 -- Some needed machinery to handle multiple-output external dependencies,
109 -- as per https://github.com/luarocks/luarocks/issues/766
110 ${lib.optionalString (lib.length depVariables > 0) ''
111 ${lib.concatStringsSep "\n " depVariables}''}
112 ${extraVariablesStr}
113 }
114 ${extraConfig}
115 '';
116
117 rocksSubdir = "${attrs.pname}-${version}-rocks";
118
119 externalDepsDirs = map
120 (x: "'${builtins.toString x}'")
121 (lib.filter (lib.isDerivation) externalDeps);
122
123 rocksTrees = lib.imap0
124 (i: dep: "{ name = [[dep-${toString i}]], root = '${dep}', rocks_dir = '${dep}/${dep.rocksSubdir}' }")
125 requiredLuaRocks;
126
127 # Filter out the lua derivation itself from the Lua module dependency
128 # closure, as it doesn't have a rock tree :)
129 requiredLuaRocks = lib.filter (d: d ? luaModule)
130 (lua.pkgs.requiredLuaModules propagatedBuildInputs);
131
132 # Explicitly point luarocks to the relevant locations for multiple-output
133 # derivations that are external dependencies, to work around an issue it has
134 # (https://github.com/luarocks/luarocks/issues/766)
135 depVariables = lib.concatMap ({name, dep}: [
136 "${name}_INCDIR='${lib.getDev dep}/include';"
137 "${name}_LIBDIR='${lib.getLib dep}/lib';"
138 "${name}_BINDIR='${lib.getBin dep}/bin';"
139 ]) externalDeps';
140
141 # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ]
142 externalDeps' = lib.filter (dep: !lib.isDerivation dep) externalDeps;
143in
144toLuaModule ( lua.stdenv.mkDerivation (
145builtins.removeAttrs attrs ["disabled" "checkInputs" "externalDeps" "extraVariables"] // {
146
147 name = namePrefix + name;
148
149 buildInputs = [ wrapLua lua.pkgs.luarocks ]
150 ++ buildInputs
151 ++ lib.optionals doCheck checkInputs
152 ++ (map (d: d.dep) externalDeps')
153 ;
154
155 # propagate lua to active setup-hook in nix-shell
156 propagatedBuildInputs = propagatedBuildInputs ++ [ lua ];
157 inherit doCheck;
158
159 # @-patterns do not capture formal argument default values, so we need to
160 # explicitly inherit this for it to be available as a shell variable in the
161 # builder
162 inherit rockspecFilename;
163 inherit rocksSubdir;
164
165 # enabled only for src.rock
166 setSourceRoot= let
167 name_only= lib.getName name;
168 in
169 lib.optionalString (knownRockspec == null) ''
170 # format is rockspec_basename/source_basename
171 # rockspec can set it via spec.source.dir
172 folder=$(find . -mindepth 2 -maxdepth 2 -type d -path '*${name_only}*/*'|head -n1)
173 sourceRoot="$folder"
174 '';
175
176 configurePhase = ''
177 runHook preConfigure
178
179 cat > ${luarocks_config} <<EOF
180 ${luarocks_content}
181 EOF
182 export LUAROCKS_CONFIG="$PWD/${luarocks_config}";
183 ''
184 + lib.optionalString (knownRockspec != null) ''
185
186 # prevents the following type of error:
187 # Inconsistency between rockspec filename (42fm1b3d7iv6fcbhgm9674as3jh6y2sh-luv-1.22.0-1.rockspec) and its contents (luv-1.22.0-1.rockspec)
188 rockspecFilename="$TMP/$(stripHash ''${knownRockspec})"
189 cp ''${knownRockspec} "$rockspecFilename"
190 ''
191 + ''
192 runHook postConfigure
193 '';
194
195 buildPhase = ''
196 runHook preBuild
197
198 nix_debug "Using LUAROCKS_CONFIG=$LUAROCKS_CONFIG"
199
200 LUAROCKS=luarocks
201 if (( ''${NIX_DEBUG:-0} >= 1 )); then
202 LUAROCKS="$LUAROCKS --verbose"
203 fi
204
205 runHook postBuild
206 '';
207
208 postFixup = lib.optionalString (!dontWrapLuaPrograms) ''
209 wrapLuaPrograms
210 '' + attrs.postFixup or "";
211
212 installPhase = attrs.installPhase or ''
213 runHook preInstall
214
215 # work around failing luarocks test for Write access
216 mkdir -p $out
217
218 # luarocks make assumes sources are available in cwd
219 # After the build is complete, it also installs the rock.
220 # If no argument is given, it looks for a rockspec in the current directory
221 # but some packages have several rockspecs in their source directory so
222 # we force the use of the upper level since it is
223 # the sole rockspec in that folder
224 # maybe we could reestablish dependency checking via passing --rock-trees
225
226 nix_debug "ROCKSPEC $rockspecFilename"
227 nix_debug "cwd: $PWD"
228 $LUAROCKS make --deps-mode=all --tree=$out ''${rockspecFilename}
229
230 runHook postInstall
231 '';
232
233
234 checkPhase = attrs.checkPhase or ''
235 runHook preCheck
236 $LUAROCKS test
237 runHook postCheck
238 '';
239
240 passthru = {
241 inherit lua; # The lua interpreter
242 inherit externalDeps;
243 } // passthru;
244
245 meta = with lib.maintainers; {
246 platforms = lua.meta.platforms;
247 # add extra maintainer(s) to every package
248 maintainers = (meta.maintainers or []) ++ [ ];
249 broken = disabled;
250 } // meta;
251}))