Integrating distro modules with LuaRocks
This is documentation on strategies to integrate OS-installed modules (e.g. packages such as luafilesystem
and lpeg
provided by Linux distros) with existing versions of LuaRocks.
This page will list two approaches: the minimal one, and a more complete one that extends the first one.
- The examples below use Lua 5.3 — just change "5.3" to "5.1" or "5.2" and the same applies.
- Distro-installed modules live at standard Lua locations under
/usr
, such as/usr/lib/lua/5.3/lfs.so
This is the minimum that should be added to distro module packages so that they visible as dependencies by LuaRocks:
For LuaRocks to be able to find any OS-installed modules, there needs to be an index file called manifest
at /usr/lib/luarocks/rocks-5.3/
.
This file should be generated running:
luarocks-admin make-manifest --local-tree --tree=/usr
This should be run as a post-install action after installing any module via the distro. This file is the LuaRocks "index" and should be kept up-to-date or else LuaRocks doesn't know about the installed modules.
For the above command to work, there has to be a directory tree for each rock and version, containing, at the bare minimum, a rock_manifest
file. The structure looks like this:
/usr/lib/luarocks/rocks-$LUA_VERSION/$ROCK_NAME/$ROCK_VERSION-$ROCK_REVISION/
-
$LUA_VERSION with with a dot: "5.3"
-
$ROCK_NAME should match the name used in the luarocks.org repository — in other words,
luafilesystem
has to be calledluafilesystem
, notlfs
. LuaRocks checks dependencies by rock name, not by individual module name. -
$ROCK_VERSION usually matches upstream, so that's not an issue.
-
$ROCK_REVISION can always be 0 for our purposes here.
Examples:
- /usr/lib/luarocks/rocks-5.3/lpeg/1.0.0-0/
- /usr/lib/luarocks/rocks-5.3/luafilesystem/1.6.0-0/
- /usr/lib/luarocks/rocks-5.3/lua-cjson/2.1.0-0/
Inside the version directory for a rock there must be a rock_manifest
file. The minimal contents of rock_manifest
to make luarocks-admin
not fail is simply:
rock_manifest = {}
This means that in the above examples, we'd have several identical one-liner files:
- /usr/lib/luarocks/rocks-5.3/lpeg/1.0.0-0/rock_manifest
- /usr/lib/luarocks/rocks-5.3/luafilesystem/1.6.0-0/rock_manifest
- /usr/lib/luarocks/rocks-5.3/lua-cjson/2.1.0-0/rock_manifest
With those empty manifests, the post-install operation mentioned above works and a later luarocks install
will the existence of the "rocks" in /usr, given the following configuration in /etc/luarocks/config-5.3.lua
:
rocks_trees = {
{ name = "user", root = home.."/.luarocks" },
{ name = "distro-modules", root = "/usr" },
{ name = "system", root = "/usr/local" },
}
deps_mode = "all"
It's important that the "system" tree is the last entry: it is the one used for system-wide installation of rocks using LuaRocks (when sudo luarocks
is used). The "distro-modules" tree should never be used directly by the user.
For more info on the deps_mode flag, see the Dependency modes documentation.
- Error messages: Running with such bare minimum setup will resolve dependencies, but running the post-install operation above will output error messages when running, such as...
Tree inconsistency detected: luafilesystem 1.6.0-0 has no rockspec. Could not load rockspec file /usr/lib/luarocks/rocks-5.3/luafilesystem/1.6.0-0/luafilesystem-1.6.0-0.rockspec (/usr/lib/luarocks/rocks-5.3/luafilesystem/1.6.0-0/luafilesystem-1.6.0-0.rockspec: No such file or directory)"
...for each entry under /usr/lib/luarocks/rocks-5.3
(for our purposes, these can be simply ignored and silenced away with &> /dev/null
).
-
Failed commands: this minimal tree will work for solving dependencies, but not for much else. In particular,
luarocks list --tree=/usr
will work, butluarocks show lpeg --tree=/user
will not, complaining that it can't find a rockspec.
A more complete approach to make commands such as luarocks show
to work would entail two steps: adding proper contents to rock_manifest
and including a rockspec file for each module.
A workable version of rock_manifest
with contents would look like this:
rock_manifest = {
lib = {
["lpeg.so"] = "136a74c6e472c36a65449184e1820a31"
},
["lpeg-1.0.0-0.rockspec"] = "4933a611af43404761002ee139c393e8",
lua = {
["re.lua"] = "5f09bb0129b09b6a8e8c1db1b206b1ca"
}
}
The entries under lib
are the files installed by the package at /usr/lib/5.3
.
The entries under lua
are the files installed by the package at /usr/share/5.3
.
The rockspec key is the rockspec file to be stored alongside the rock_manifest
file.
The values to these entries are MD5 sums to the files in question.
For luarocks show
to display metadata properly, a rockspec file must exist. It should be named according to the pattern $ROCK_NAME-$ROCK_VERSION-$ROCK_REVISION.rockspec
(in all lowercase). Continuing the examples above:
- /usr/lib/luarocks/rocks-5.3/lpeg/1.0.0-0/lpeg-1.0.0-0.rockspec
- /usr/lib/luarocks/rocks-5.3/luafilesystem/1.6.0-0/luafilesystem-1.6.0-0.rockspec
- /usr/lib/luarocks/rocks-5.3/lua-cjson/2.1.0-0/lua-cjson-2.1.0-0.rockspec
For simplicity, I would recommend just copying over the appropriate rockspec file from luarocks.org and bundling them in the package metadata. For completeness, this is how the one for LPeg 1.0 looks like:
package = "LPeg"
version = "1.0.0-1"
source = {
url = "http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.0.tar.gz",
md5 = "0aec64ccd13996202ad0c099e2877ece",
}
description = {
summary = "Parsing Expression Grammars For Lua",
detailed = [[
LPeg is a new pattern-matching library for Lua, based on Parsing
Expression Grammars (PEGs). The nice thing about PEGs is that it
has a formal basis (instead of being an ad-hoc set of features),
allows an efficient and simple implementation, and does most things
we expect from a pattern-matching library (and more, as we can
define entire grammars).
]],
homepage = "http://www.inf.puc-rio.br/~roberto/lpeg.html",
maintainer = "Gary V. Vaughan <gary@vaughan.pe>",
license = "MIT/X11"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
lpeg = {
"lpcap.c", "lpcode.c", "lpprint.c", "lptree.c", "lpvm.c"
},
re = "re.lua"
}
}