Razzi's guide to Lua
Lua! It compiles fast and starts fast
install local package
luarocks is the package manager for lua.
By default lua tries to write to the system directory at /usr/local,
however this would require sudo.
Fortunately, you can install to ~/.luarocks with --local:
$ luarocks install --local cmark
You can see the result of the install like so:
$ luarocks show cmark
cmark 0.31.1-1 - Lua wrapper for libcmark, CommonMark Markdown parsing
...
Modules:
cmark (/Users/razzi/.luarocks/lib/lua/5.4/cmark.so)
cmark.builder (/Users/razzi/.luarocks/share/lua/5.4/cmark/builder.lua)
However if you try to require it you’ll get an error:
$ lua
Lua 5.4.7 Copyright (C) 1994-2024 Lua.org, PUC-Rio
> require 'cmark'
stdin:1: module 'cmark' not found:
no field package.preload['cmark']
no file '/usr/local/share/lua/5.4/cmark.lua'
...
The problem is that it hasn’t added ~/.luarocks to your lua require path.
Fortunately luarocks knows the commands it needs to add its installs to your lua require path:
$ luarocks path
export LUA_PATH='/usr/local/Cellar/luarocks/3.11.1/share/lua/5.4/?.lua;/usr/local/share/lua/5.4/?.lua;/usr/local/share/lua/5.4/?/init.lua;/usr/local/lib/lua/5.4/?.lua;/usr/local/lib/lua/5.4/?/init.lua;./?.lua;./?/init.lua;/Users/razzi/.local/lib/lua/share/lua/5.4/?.lua;/Users/razzi/.luarocks/lib/lua/5.4/?.lua;/Users/razzi/.luarocks/lib/luarocks/5.4/?.lua;/Users/razzi/.luarocks/lib/luarocks/rocks-5.4/?.lua;/Users/razzi/.luarocks/share/lua/5.4/?.lua;/Users/razzi/.luarocks/share/lua/5.4/?/init.lua'
export LUA_CPATH='/usr/local/lib/lua/5.4/?.so;/usr/local/lib/lua/5.4/loadall.so;./?.so;/Users/razzi/.luarocks/lib/lua/5.4/?.so'
export PATH='/Users/razzi/.local/bin:/Users/razzi/.luarocks/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'
You could evaluate this directly like so:
$ eval $(luarocks path)
However I prefer to avoid eval in such contexts, so I take the output of luarocks path and add it to my ~/.profile myself.
$ export LUA_CPATH="$HOME/.luarocks/lib/lua/5.4/?.so"
Now I can require my module!
$ lua
Lua 5.4.7 Copyright (C) 1994-2024 Lua.org, PUC-Rio
> cmark = require 'cmark'
table: 0x7fb04d704240 /Users/razzi/.luarocks/lib/lua/5.4/cmark.so
install package to local directory
The above works fine when just hacking around.
When it’s time to build out an application, there are 2 helpful practices:
- all dependencies should be declared in a requirements file, with versions
- dependencies should be installed into a per-project environment, so working on multiple applications doesn’t cause library conflicts
The way lua declares its dependencies is using a rockspec file. Here’s an example:
razzi-dev-1.rockspec
rockspec_format = "3.0"
package = "razzi"
version = "dev-1"
source = {
url = ""
}
dependencies = {
"cmark == 0.31.1",
}
And the way to install dependencies in a local folder is as follows:
$ luarocks make --tree lua_modules --deps-only
You must also add the local path to your PATH:
$ luarocks path --tree lua_modules
export LUA_PATH='/Users/razzi/hack/vendor/share/lua/5.4/?.lua;...
As above, you can either eval this or add it to a .env file or similar:
$ luarocks path --tree lua_modules/ > .env
$ source .env
$ lua
Lua 5.4.7 Copyright (C) 1994-2024 Lua.org, PUC-Rio
> require 'cmark'
table: 0x7f872e004290 /Users/razzi/hack/lua_modules/lib/lua/5.4/cmark.so
This approach is taken a slightly different direction here: https://leafo.net/guides/customizing-the-luarocks-tree.html
The main benefit being that it is all tracked in code, versus my approach,
which would end up adding the lua_modules and .env to .gitignore, which would
then require an explanation how to set things up in the README or other doc.
The leafo approach also requires a bit of extra command setup, but that could be put in a Makefile.
The .env approach can also be automated with shell integration.