razzi.abuissa.net

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:

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.