当先锋百科网

首页 1 2 3 4 5 6 7


lua的包管理工具是:LuaRocks。本文内容基于MacOS系统。

安装luarocks

> cd 你预期的安装目录
> wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
> tar zxpf luarocks-3.9.2.tar.gz
> cd luarocks-3.9.2
> ./configure && make && sudo make install

使用luarocks

参考官方文档:Using LuaRocks

1. 安装模块

可用的模块在luarocks官网搜索即可。例如现在我们安装一个luasocket模块。

注意:不知道是luarocks故意为之,还是因为有bug。在luarocks的安装目录(以及任意子目录)执行luarocks命令,和在其它目录下执行luarocks命令时,产生的行为并不一致。例如:

  • luarocks安装目录下执行luarocks install ...,模块会被安装到luarocks安装目录/lua_modules/;而在其它目录执行此命令,模块会被安装到/usr/local/。具体的子路径则都符合rock的树结构

  • 执行luarocks path命令,可以得到适用于lua的模块搜索路径规则(稍后会讲到)。然而只有在luarocks的安装目录中执行此命令,得到的规则中才会包含匹配luarocks安装目录/lua_modules/路径的项。

  • 就像这两种目录对应了两个不同的环境一样。我提了一个issue询问此现象。

2. 加载模块

如果你并不是在luarocks安装目录下执行的模块安装命令,那么现在就可以直接在lua代码中使用require("socket")成功使用此模块了。

注意,通常模块安装命令中使用的模块名就是在lua代码中用require加载时填写的模块名,但也有一些例外的模块。比如luasocket在加载时的模块名是socket,即要使用require("socket"),而不是require("luasocket")

2.1 分析

为什么直接就可以使用,这么简单?作为一个经常遭到"挑战"的程序员,你可能原本已经做好了"和luarocks大战三百回合,不破luarocks终不还!"的准备,结果没想到刀还没拔出来,敌人就吓跑了。如果你一时接受不了这么简单的战斗,那么可以继续阅读,识破luarocks的诡计~
(非战斗人员请迅速撤离!)

注意:继续阅读需要对Lua的模块加载知识有一定的基础了解,如果有需要的话,可以在评论区留言,我会抽时间整理一篇关于Lua模块加载的文章,你也点击CSDN文末的推广码,我很乐意分享这些知识。

其实这是因为luarocks将模块安装在了/usr/local/share/lua/5.4/,具体见luarocks树结构。而这个树结构恰好匹配了package.pathpackage.cpath的默认规则。

print(package.path) -- `package.path`规则专门用于查找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

print(package.cpath) -- `package.cpath`规则专门用来查找C模块
-- /usr/local/lib/lua/5.4/?.so;/usr/local/lib/lua/5.4/loadall.so;./?.so

但是,如果你是在luarocks安装目录下执行的模块安装命令,就会像一开始说的那样,模块会被安装在luarocks安装目录/lua_modules/share/lua/5.4/,这并不在package.pathpackage.cpath的默认规则中。

因此,需要手动配置LUA_PATH_5_4LUA_PATH,或者LUA_CPATH_5_4LUA_CPATH环境变量。按照惯例,前两个环境变量专门用来配置.lua模块,后两个专门用来配置C模块(.so)。

注意,以下对环境变量的设置命令,只在当前shell会话有效,然后你可以通过执行lua命令开启命令行交互模式使用lua,运行require("socket")验证是否成功。如果想要永久设置环境变量,应该把它们写到shell的启动文件中,bash可以写到~/.bashrczsh可以写到~/.zshrc
如果对shell的这些基础知识感兴趣,可以阅读我的另一篇博客(篇幅较长):【Linux基础】理解并善用Shell – Shell精讲

于是我们可以配置LUA_PATH

# ;;会被替换为默认路径,作用是保留默认路径,这很有必要。
export LUA_PATH=";;/Users/wushu/Develop/luarocks-3.9.2/lua_modules/share/lua/5.4/?.lua

但此时你若是尝试使用require("socket"),会发现依然报错。仔细观察报错信息可以发现:其实socket.lua已经找到了,报错的原因是,socket.lua中还require了其它的模块。结合luarocks树结构观察模块的安装目录,以及socket.lua中的require,会发现其实是core.so没有被加载到。所以还需要配置LUA_CPATH

然后再尝试require("socket"),就可以啦。

2.2 luarocks path

其实,luarocks提供了一种更简单的方式来配置环境变量。

luarocks提供了一种半自动化的方式:luarocks path命令。此命令能够打印出适合当前平台的、用于设置环境变量的命令。
并且,此命令得到的模块搜索路径规则中,会包含默认规则;另外还有一个PATH,也会拼接原有的PATH。因此不必担心自己的环境会被覆盖。

~/Develop/luarocks-3.9.2 » luarocks path
export LUA_PATH='/Users/wushu/Develop/luarocks-3.9.2/./lua_modules/share/lua/5.4/?.lua;/Users/wushu/Develop/luarocks-3.9.2/./lua_modules/share/lua/5.4/?/init.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/wushu/Develop/luarocks-3.9.2/lua_modules/share/lua/5.4/?.lua;/Users/wushu/.luarocks/share/lua/5.4/?.lua;/Users/wushu/.luarocks/share/lua/5.4/?/init.lua'
export LUA_CPATH='/Users/wushu/Develop/luarocks-3.9.2/./lua_modules/lib/lua/5.4/?.so;/usr/local/lib/lua/5.4/?.so;/usr/local/lib/lua/5.4/loadall.so;./?.so;/Users/wushu/Develop/luarocks-3.9.2/lua_modules/lib/lua/5.4/?.so;/Users/wushu/.luarocks/lib/lua/5.4/?.so'
export PATH='/Users/wushu/.luarocks/bin:(原PATH环境变量)'

然后通过**eval "$(luarocks path)"**命令,就可以一键设置环境变量。注意,此命令只在当前shell会话有效,如果想要永久有效,需要把此命令写到shell启动文件中。

但正如一开始所说,luarocks path命令在不同目录下产生的行为并不一致。只有在luarocks安装目录(及其任意子目录)下执行,得到的规则中才会包含匹配luarocks安装目录/lua_modules/路径的项。而现在我们之所以需要配置环境变量,就是因为luarocks安装的模块不在默认目录下,而是在luarocks安装目录/lua_modules目录下。

所以,我们必须在shell启动文件中使用这种方式配置环境变量:

current_dir=$(pwd)
cd /Users/wushu/Develop/luarocks-3.9.2
# 在luarocks安装目录下获取环境变量命令并执行
eval "$(luarocks path)"
cd $current_dir

然后尝试require("socket"),Bingo!

至此,战斗结束,你就可以对luarocks宣布:KO!🎉🎉🎉


其它命令

查看模块信息描述:查看已安装模块的信息描述。

~/Desktop » luarocks show luasocket

LuaSocket 3.1.0-1 - Network support for the Lua language

LuaSocket is a Lua extension library composed of two parts: a set of C modules
that provide support for the TCP and UDP transport layers, and a set of Lua
modules that provide functions commonly needed by applications that deal with
the Internet.

License:      	MIT
Homepage:     	https://github.com/lunarmodules/luasocket
Installed in: 	/usr/local

Modules:
......

移除模块

sudo luarocks remove luasocket

协作开发使用方式

luarocks存在两点问题:

  1. 一些模块安装时的名字和require应该使用的名字不一致。如luarocks install luasocket -> require("socket")
  2. luarocks没有提供模块的多版本管理功能。(我没有找到有关的描述)

这在协同开发、长期开发时,会有些困难。

  1. 我是否需要在项目中添加一个文件来介绍项目使用了哪些模块?
  2. 由于没有版本管理,可能团队中的每个人在不同时间安装到的是不同版本的模块,因此,我是否应该把模块放到项目目录下?

这是我在luarocks仓库提的issue