LuaRocks is the package manager for Lua. When youdecide to install a package (or module1) there are afew places it can be installed.
The directory that LuaRocks installs to is called atree. It’s a speciallystructured directory that contains all the installed module files, along withmetadata about those modules.
A common request I've heard is“I wish LuaRocks worked likenpm and let meinstall modules in the current directory.” I'm glad to report it already can!I've written this guide to clear up any confusion about how and where LuaRocksinstalls modules.
There are three ways of choosing where packages get installed:
/usr/share/lua/5.1)--local--tree some/directoryFor general purpose modules, ones that will be available for any Lua script youexecute, thelocal tree should be used. This tree is located in your homedirectory (~/.luarocks). A global install is not recommended because itrequires root access.
If you're building a project in Lua you'll probably want to more closelycontrol the dependencies and their versions. For this scenario I recommendusing a tree that is located in the project’s directory. This is the approachused by other package mangers such asnpm.
This section is not specific to LuaRocks, but LuaRocks utilizes this systemto provide Lua a way to load the modules it installs.
When executingrequire("hello.world") Lua must figure out where the file forthis module is in order to load it. A module can resolve to either Lua sourcecode, a.lua file, or a native code library, a.so on Linux or.dll onWindows.
Similar to your operating system’sPATH environment variable for findingexecutables, Lua has apath to find modules. As mentioned above, there aretwo types of modules, so Lua has two paths.
You can view (and edit) the paths usingpackage.path andpackage.cpathwithin a Lua script:
print(package.path)-- where .lua files are searched forprint(package.cpath)-- where native modules are searched for-- add a new directory to the pathpackage.path=package.path..";/opt/custom/?.lua"require("hello.zone")-- might load /opt/custom/hello/zone.luaThe initial value ofpackage.path andpackage.cpath comes from the defaultscompiled into your Lua executable, and the special environment variablesLUA_PATH andLUA_CPATH.
LuaRocks has a built in command for setting the Lua path environment variables.It’s calledluarocks path
Running it the command might produce:
$ luarocks pathexport LUA_PATH='/home/leafo/.luarocks/share/lua/5.1/?.lua;/home/leafo/.luarocks/share/lua/5.1/?/init.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;;./?.lua;/usr/lib/lua/5.1/?.lua;/usr/lib/lua/5.1/?/init.lua'export LUA_CPATH='/home/leafo/.luarocks/lib/lua/5.1/?.so;/usr/lib/lua/5.1/?.so;;./?.so;/usr/lib/lua/5.1/loadall.so'The special syntax
;;can be used in the environment variable’s value torepresent the default value provided by the Lua runtime.
This is a shell script that will set the Lua path environment variables tocorrectly load modules from the global and local install locations of LuaRocks.
You might want to append this to your.bashrc like this:
$ luarocks path >> ~/.bashrcNow you canrequire() any modules that you've installed locally or globallywithout any additional steps. (After restarting your shell or sourcing the rcfile)
Modules installed globally will work without adjusting the Lua path sincethey are installed in the default Lua system path.
Don’t care about the explanation, go to thequick guide.
Installing packages to the current directory is as simple as
luarocks install --tree lua_modules lpegThis will install the packagelpeg (and any dependencies if necessary) to thedirectorylua_modules in the current directory.
Loading those modules is a bit more complicated.
The structure of thetree, atlua_modules/, after installinglpeg lookslike this:
lua_modules/├── lib│ ├── lua│ │ └── 5.1│ │ └── lpeg.so│ └── luarocks│ └── rocks-5.1│ ├── lpeg│ │ └── 1.0.0-1│ │ ├── lpeg-1.0.0-1.rockspec│ │ └── rock_manifest│ └── manifest└── share └── lua └── 5.1 └── re.luaI happen to be using a version of LuaRocks compiled for Lua 5.1 in thisexample, but this technique will work for any version. Just make sure thepaths you create have the correct version
For this example I choselpegbecause it contains both a.lua module:re, and a native.so module:lpeg. From this we can already see how we might structure our Luapath andcpath.
path would be:lua_modules/share/lua/5.1/?.luacpath would be:lua_modules/lib/lua/5.1/?.soThere’s one more entry we'd like to add to the path. A common idiom is to useaninit.lua file as the entry point for a package, located in the directoryof that package. We'll amend the path:
path would be:lua_modules/share/lua/5.1/?.lua;lua_modules/share/lua/5.1/?/init.luacpath would belua_modules/lib/lua/5.1/?.so
;is used to provide two places to look in the path
As discussed above there are a few ways to enable these paths. From commandline you could prepend the environment variables in front of your command:
LUA_PATH='lua_modules/share/lua/5.1/?.lua;lua_modules/share/lua/5.1/?/init.lua;;' LUA_CPATH='lua_modules/lib/lua/5.1/?.so' lua my_script.luaThat’s a mouthful though, so lets use an alternate approach. Thelua commandline executable can take an-l flag to specify a module to load beforeexecuting the script.
Lets create a new file in the current directory,set_paths.lua:
-- set_paths.lualocalversion=_VERSION:match("%d+%.%d+")package.path='lua_modules/share/lua/'..version..'/?.lua;lua_modules/share/lua/'..version..'/?/init.lua;'..package.pathpackage.cpath='lua_modules/lib/lua/'..version..'/?.so;'..package.cpathNow to run a script with the modules installed in that directory:
lua -l set_paths my_script.luaThis requires that the script be run from the same directory that
set_paths.luaandlua_modules/is located
You might be tempted to putrequire("set_paths") in your code’s entry pointto avoid the additional argument, butit’s a bad idea.
A module should run on any machine it is installed to regardless of the packagepath configuration. Theset_paths script is only to facilitate developmentand execution in the current directory.
By configuring paths on script execution, you avoid embedding any assumptionsabout the package path in your code. If this additional step is too much totype, consider aMakefile that includes some of your common commands.
Want the full explanation? Scroll up.
luarocks install --tree lua_modules lpegCreate fileset_paths.lua:
-- set_paths.lualocalversion=_VERSION:match("%d+%.%d+")package.path='lua_modules/share/lua/'..version..'/?.lua;lua_modules/share/lua/'..version..'/?/init.lua;'..package.pathpackage.cpath='lua_modules/lib/lua/'..version..'/?.so;'..package.cpathExecute scripts:
lua -l set_paths my_script.luaRunning tests withbusted:
busted --helper=set_pathsDo not includerequire("set_paths") in your code, scroll up to see why.
Installing packages to thelocal tree, or the home directory, requires the--local flag to be passed to theluarocks install install command. This isthe recommended way to install packages that are generally available because itdoes not require root access to perform the installation.
$ luarocks install --local moonscriptTheLUA_PATH andLUA_CPATH should be configured. This can be done with theluarocks path command as discussed above.
print(require("moonscript"))Installing packages in the system tree requires root access. Prefixing theluarocks command withsudo is a common way to install global packages:
$ sudo luarocks install moonscriptInstalling globally is not recommended since it requires root access. Use thelocal tree to install packages andmake them available for all your scripts.
1: The distinction isn’t always clear, but a package is synonymouswith a library, and a module is an individual thing (.lua file, shredlibrary) you can include from that package. I tend to use them interchangeably.
A community LuaRocks hosting repository
leafo.net · Generated Sun Oct 8 13:02:35 2023 bySitegenmastodon.social/@leafo