nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
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 strictDeps = true;
92 env = {
93 LUAROCKS_CONFIG = self.configFile;
94 }
95 // attrs.env or { };
96
97 generatedRockspecFilename = "./${self.pname}-${self.rockspecVersion}.rockspec";
98
99 nativeBuildInputs = [
100 lua # for lua.h
101 wrapLua
102 luarocks_bootstrap
103 ]
104 ++ lib.optionals self.doCheck self.nativeCheckInputs;
105
106 inherit
107 doCheck
108 extraConfig
109 rockspecFilename
110 knownRockspec
111 externalDeps
112 nativeCheckInputs
113 ;
114
115 buildInputs =
116 let
117 # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ]
118 externalDeps' = lib.filter (dep: !lib.isDerivation dep) self.externalDeps;
119 in
120 [ luarocks_bootstrap ] ++ buildInputs ++ (map (d: d.dep) externalDeps');
121
122 # propagate lua to active setup-hook in nix-shell
123 propagatedBuildInputs = propagatedBuildInputs ++ [ lua ];
124
125 # @-patterns do not capture formal argument default values, so we need to
126 # explicitly inherit this for it to be available as a shell variable in the
127 # builder
128 rocksSubdir = "${self.pname}-${self.version}-rocks";
129
130 configFile = writeTextFile {
131 name = self.pname + "-luarocks-config.lua";
132 text = self.luarocks_content;
133 };
134
135 luarocks_content = (lib.generators.toLua { asBindings = true; } self.luarocksConfig) + ''
136
137 ${self.extraConfig}
138 '';
139
140 # TODO make it the default variable
141 luarocksConfig =
142 let
143 externalDepsGenerated = lib.filter (drv: !drv ? luaModule) (
144 self.finalPackage.nativeBuildInputs ++ self.propagatedBuildInputs ++ self.buildInputs
145 );
146
147 generatedConfig = luaLib.generateLuarocksConfig {
148 externalDeps = lib.unique (self.externalDeps ++ externalDepsGenerated);
149 local_cache = "";
150
151 # To prevent collisions when creating environments, we install the rock
152 # files into per-package subdirectories
153 rocks_subdir = self.rocksSubdir;
154
155 # Filter out the lua derivation itself from the Lua module dependency
156 # closure, as it doesn't have a rock tree :)
157 # luaLib.hasLuaModule
158 requiredLuaRocks = lib.filter luaLib.hasLuaModule (
159 lua.pkgs.requiredLuaModules (self.finalPackage.nativeBuildInputs ++ self.propagatedBuildInputs)
160 );
161 };
162
163 luarocksConfig' = lib.recursiveUpdate luarocksConfig (
164 lib.optionalAttrs (attrs ? extraVariables) (
165 lib.warn "extraVariables in buildLuarocksPackage is deprecated, use luarocksConfig instead" {
166 variables = attrs.extraVariables;
167 }
168 )
169 );
170 in
171 lib.recursiveUpdate generatedConfig luarocksConfig';
172
173 configurePhase = ''
174 runHook preConfigure
175 ''
176 + lib.optionalString (self.rockspecFilename == null) ''
177 rockspecFilename="${self.generatedRockspecFilename}"
178 ''
179 + lib.optionalString (self.knownRockspec != null) ''
180 # prevents the following type of error:
181 # Inconsistency between rockspec filename (42fm1b3d7iv6fcbhgm9674as3jh6y2sh-luv-1.22.0-1.rockspec) and its contents (luv-1.22.0-1.rockspec)
182 rockspecFilename="$TMP/$(stripHash ${self.knownRockspec})"
183 cp ${self.knownRockspec} "$rockspecFilename"
184 ''
185 + ''
186 runHook postConfigure
187 '';
188
189 buildPhase = ''
190 runHook preBuild
191
192 source ${lua}/nix-support/utils.sh
193 nix_debug "Using LUAROCKS_CONFIG=$LUAROCKS_CONFIG"
194
195 LUAROCKS_EXTRA_ARGS=""
196 if (( ''${NIX_DEBUG:-0} >= 1 )); then
197 LUAROCKS_EXTRA_ARGS=" --verbose"
198 fi
199
200 runHook postBuild
201 '';
202
203 postFixup =
204 lib.optionalString (!dontWrapLuaPrograms) ''
205 wrapLuaPrograms
206 ''
207 + attrs.postFixup or "";
208
209 installPhase = ''
210 runHook preInstall
211
212 # work around failing luarocks test for Write access
213 mkdir -p $out
214
215 # luarocks make assumes sources are available in cwd
216 # After the build is complete, it also installs the rock.
217 # If no argument is given, it looks for a rockspec in the current directory
218 # but some packages have several rockspecs in their source directory so
219 # we force the use of the upper level since it is
220 # the sole rockspec in that folder
221 # maybe we could reestablish dependency checking via passing --rock-trees
222
223 nix_debug "ROCKSPEC $rockspecFilename"
224 luarocks $LUAROCKS_EXTRA_ARGS make --deps-mode=all --tree=$out ''${rockspecFilename}
225
226 runHook postInstall
227 '';
228
229 shellHook = ''
230 runHook preShell
231 export LUAROCKS_CONFIG="$PWD/${luarocks_config}";
232 runHook postShell
233 '';
234
235 passthru = {
236 inherit lua;
237 }
238 // attrs.passthru or { };
239
240 meta = {
241 platforms = lua.meta.platforms;
242 # add extra maintainer(s) to every package
243 maintainers = (attrs.meta.maintainers or [ ]) ++ [ ];
244 broken = disabled;
245 }
246 // attrs.meta or { };
247 }
248 )
249 );
250in
251luarocksDrv