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