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