1{
2 pkgs,
3 lib,
4 lua,
5}:
6let
7 inherit (lib.generators) toLua;
8 requiredLuaModules =
9 drvs:
10 let
11 modules = lib.filter hasLuaModule drvs;
12 in
13 lib.unique ([ lua ] ++ modules ++ lib.concatLists (lib.catAttrs "requiredLuaModules" modules));
14 # Check whether a derivation provides a lua module.
15 hasLuaModule = drv: drv ? luaModule;
16
17 # Use this to override the arguments passed to buildLuarocksPackage
18 overrideLuarocks =
19 drv: f:
20 (drv.override (
21 args:
22 args
23 // {
24 buildLuarocksPackage = drv: (args.buildLuarocksPackage drv).override f;
25 }
26 ))
27 // {
28 overrideScope = scope: overrideLuarocks (drv.overrideScope scope) f;
29 };
30
31in
32rec {
33 inherit overrideLuarocks;
34 inherit hasLuaModule requiredLuaModules;
35
36 luaPathList = [
37 "share/lua/${lua.luaversion}/?.lua"
38 "share/lua/${lua.luaversion}/?/init.lua"
39 ];
40 luaCPathList = [
41 "lib/lua/${lua.luaversion}/?.so"
42 ];
43
44 # generate paths without a prefix
45 luaPathRelStr = lib.concatStringsSep ";" luaPathList;
46 luaCPathRelStr = lib.concatStringsSep ";" luaCPathList;
47
48 # generate LUA_(C)PATH value for a specific derivation, i.e., with absolute paths
49 genLuaPathAbsStr = drv: lib.concatMapStringsSep ";" (x: "${drv}/${x}") luaPathList;
50 genLuaCPathAbsStr = drv: lib.concatMapStringsSep ";" (x: "${drv}/${x}") luaCPathList;
51
52 # Generate a LUA_PATH with absolute paths
53 # genLuaPathAbs = drv:
54 # lib.concatStringsSep ";" (map (x: "${drv}/x") luaPathList);
55
56 luaAtLeast = lib.versionAtLeast lua.luaversion;
57 luaOlder = lib.versionOlder lua.luaversion;
58 isLua51 = (lib.versions.majorMinor lua.version) == "5.1";
59 isLua52 = (lib.versions.majorMinor lua.version) == "5.2";
60 isLua53 = lua.luaversion == "5.3";
61 isLuaJIT = lib.getName lua == "luajit";
62
63 /*
64 generates the relative path towards the folder where
65 seems stable even when using lua_modules_path = ""
66
67 Example:
68 getDataFolder luaPackages.stdlib
69 => stdlib-41.2.2-1-rocks/stdlib/41.2.2-1/doc
70 */
71 getDataFolder = drv: "${drv.pname}-${drv.version}-rocks/${drv.pname}/${drv.version}";
72
73 /*
74 Convert derivation to a lua module.
75 so that luaRequireModules can be run later
76 */
77 toLuaModule =
78 drv:
79 drv.overrideAttrs (oldAttrs: {
80 # Use passthru in order to prevent rebuilds when possible.
81 passthru = (oldAttrs.passthru or { }) // {
82 luaModule = lua;
83 requiredLuaModules = requiredLuaModules drv.propagatedBuildInputs;
84 };
85 });
86
87 /*
88 generate a luarocks config conforming to:
89 https://github.com/luarocks/luarocks/wiki/Config-file-format
90
91 The config lists folders where to find lua dependencies
92
93 Example:
94 generateLuarocksConfig {
95 externalDeps = [ { name = "CRYPTO"; dep = pkgs.openssl; } ];
96 rocksSubdir = "subdir";
97 };
98
99 Type:
100 generateLuarocksConfig :: AttrSet -> String
101 */
102 generateLuarocksConfig =
103 {
104 externalDeps ? [ ],
105 # a list of lua derivations
106 requiredLuaRocks ? [ ],
107 ...
108 }@args:
109 let
110 rocksTrees = lib.imap0 (i: dep: {
111 name = "dep-${toString i}";
112 root = "${dep}";
113 # packages built by buildLuaPackage or luarocks doesn't contain rocksSubdir
114 # hence a default here
115 rocks_dir =
116 if dep ? rocksSubdir then "${dep}/${dep.rocksSubdir}" else "${dep.pname}-${dep.version}-rocks";
117 }) requiredLuaRocks;
118
119 # Explicitly point luarocks to the relevant locations for multiple-output
120 # derivations that are external dependencies, to work around an issue it has
121 # (https://github.com/luarocks/luarocks/issues/766)
122 depVariables = zipAttrsWithLast (
123 lib.lists.map (
124 { name, dep }:
125 {
126 "${name}_INCDIR" = "${lib.getDev dep}/include";
127 "${name}_LIBDIR" = "${lib.getLib dep}/lib";
128 "${name}_BINDIR" = "${lib.getBin dep}/bin";
129 }
130 ) externalDeps'
131 );
132 zipAttrsWithLast = lib.attrsets.zipAttrsWith (name: lib.lists.last);
133
134 # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ]
135 externalDeps' = lib.filter (dep: !lib.isDerivation dep) externalDeps;
136
137 externalDepsDirs = map (x: builtins.toString x) (lib.filter (lib.isDerivation) externalDeps);
138
139 generatedConfig = (
140 {
141
142 # first tree is the default target where new rocks are installed,
143 # any other trees in the list are treated as additional sources of installed rocks for matching dependencies.
144 rocks_trees = (
145 [
146 {
147 name = "current";
148 root = "${placeholder "out"}";
149 rocks_dir = "current";
150 }
151 ]
152 ++ rocksTrees
153 );
154 }
155 // lib.optionalAttrs lua.pkgs.isLuaJIT {
156 # Luajit provides some additional functionality built-in; this exposes
157 # that to luarock's dependency system
158 rocks_provided = {
159 jit = "${lua.luaversion}-1";
160 ffi = "${lua.luaversion}-1";
161 luaffi = "${lua.luaversion}-1";
162 bit = "${lua.luaversion}-1";
163 };
164 }
165 // {
166 # For single-output external dependencies
167 external_deps_dirs = externalDepsDirs;
168 # Some needed machinery to handle multiple-output external dependencies,
169 # as per https://github.com/luarocks/luarocks/issues/766
170 variables = depVariables;
171 }
172 // removeAttrs args [
173 "requiredLuaRocks"
174 "externalDeps"
175 ]
176 );
177 in
178 generatedConfig;
179}