Or vendoring Lua rocks
The Lua programming language, like many others, employs a purpose-built package manager to download and install its ecosystem of libraries. This tool, LuaRocks, has some notable features:
downloads/installs packages to user-specific or system-wide locations
configurable dependency resolution
builds locally define rocks (Lua modules packaged by LuaRocks)
queries information about the active LuaRocks configuration
Where these features fall short is in managing the dependencies of multiple Lua projects—each with a potentially different version of Lua. Being that Lua is an embedded language, this is in fact common, and further exacerbated by the popularity of both the reference Lua implementation and luajit.
I encountered this issue during the development of an experimental window manager, dovetail. It is based on the awesome window manager framework, which can be built with Lua versions 5.1-5.3 or luajit. It also depends on a few Lua packages, and therein lies the problem. It quickly became an overwhelming task to unify the range of Lua versions and implementations, 3rd party packages, varying installation paths, and integration with an embedded interpreter.
After consideration of my options, I decided the easiest solution was to vendor all dependency packages. I set up Makefile rules to download the version of packages specified in a version-controlled file to a specific Lua rocks tree where the package’s files are extracted and moved into a
lua_modules directory in the root of the project. During installation, these modules are copied to a system-wide shared data directory and referenced by awesome’s Lua interpreter.
When I required this functionality outside of the dovetail project, I re-implemented these Makefile rules as a shell script called luarocket. It is meant to be included directly in a project and utilized as part of its build process.