文章格式

Luabundle,用于 Lua 和 Skynet 项目依赖管理

luabundle

很高兴向大家介绍 Luabundle,一个我们用来管理 skynet 项目依赖的工具,当然它也可以拿来管理任何 Lua 项目的依赖。

项目的主体是一个 shell 脚本,来控制 skynet 的获取和编译,以及通过 luarocks 来管理 Lua 包。它来源于我们自己实际的需求,skynet 是我们后端主要开发平台,之前 Lua 包都是直接下载源代码复制到项目内。而对于有 C 扩展的包,则是把源文件放到 skynet 下,并修改 skynet 的 Makefile,一起编译出来。这种方式有个很大的问题,就是更新 skynet 和 Lua 包都很痛苦,而且 C 扩展的集成也很麻烦。在研究了已有的 Lua 包管理工具以及参考 Ruby 中 Bundler 之后就有了 Luabundle。

Luabundle 本身的用法在 Github 项目的 README 中已经有详细的描述就不再重复。使用中碰到任何问题欢迎在 Issues 里提出来。这里主要是介绍下 Luabundle 实现的原理。

Luafile

Luafile 就是一个普通的 bash 文件,所以任何 bash 语法和命令都是可以用的。唯一不同就是可以使用一些 Luabundle 注入的函数,通过这些函数来列出项目的依赖。比如 skynet 就是安装指定版本的 skynet;rock 就是 luarocks 的封装,但是会把所有 Lua 包安装到 bundle 子目录下,并且会处理带 C 扩展的 Lua 包的编译和链接。在项目中就只需要保留 Luafile,依赖通过 luabundle 命令安装,就不需要放到项目的代码仓库里了。锁定版本只要在 Luafile 中指定。升级也只需要修改 Luafile,然后通知所有人更新并重新执行 luabundle。

Skynet 管理

Skynet 管理比较简单,把它的 Github 仓库克隆到 skynet 子目录下,然后通过 make 编译即可。版本选择就是通过 Git 的 ​tag 和 branch 来选择。只是 skynet 的启动配置中需要把 bundle 下的 Lua 包加到 lua_path 和 lua_cpath 里,借用项目 README 中的例子:

 

Luarocks 集成

在开始有 Luabundle 这个想法时就决定尽量基于现有的方案来管理 Lua 包,就像 Bundler 是基于 Gems 来管理 Ruby 包。目前比较流行的 Lua 包管理器就两个:Luarocks 和 LuaDist。通过比较后发现 Luarocks 定制性更强,所以最终选择了 Luarocks。

首先是定制方便,只用生成一个配置文件,然后设置下环境变量 LUAROCKS_CONFIG 就行了。Luabundle 就是基于模板生成了 .luabundle.lua 文件,其中的内容可以参考 Github 仓库中的 config.lua 文件。

配置文件中的 rocks_trees 是用来配置 Lua 包的安装位置的,这样就能很容易的隔离不同项目的依赖。

而 variables 中是用来控制 C 扩展的编译和链接的。Skynet 中自带了 lua,如果想在 skynet 中正常使用 Lua 包,最好是编译和链接就使用自带的 Lua。​Luarocks 只用设置 variables 中的 LUALUA_BINDIRLUA_INCDIR 和 LUA_LIBDIR 就行了。但是当在 Mac OS X 下集成 luaossl,一个 OpenSSL 的封装的时候,碰到了一个问题。Luaossl 需要最新版本的 OpenSSL,这个可以通过 Homebrew 安装并链接到 /usr/local 下

但是编译 luaossl 的时候,并没有相应 -I 和 -L 参数来添加目录 /usr/local,所以会找不到 OpenSSL。这个可以通过 variables 里的 CFLAGS 和 LIBFLAG 来控制,不过会出现两个问题:

  • CFLAGS 和 LIBFLAG 原来的默认值会被覆盖掉,要把 luarocks 中使用的默认值抽取出来,这个是分平台的,可以查看源代码
  • CFLAGS​ 和 LIBFLAG 中添加的 -I 和 -L 参数会出现在 LUA_INCDIR 和 LUA_LIBDIR 之前。如果也通过 Homebrew 安装了 Lua,编译的时候会优先使用 /usr/local 下安装的 Lua。为了解决这个问题就是不依赖 LUA_INCDIR 和 LUA_LIBDIR,而是自己在 CFLAGS 和 LIBFLAG 靠前的位置加入 Lua 的头文件位置和库位置,详细的修改可以查看这个提交

目前测试,lua-cjsonluaossl 等库都可以通过 Luabundle 集成到 skynet 中使用了。不过因为 skynet 已经使用了 Lua 5.3,一些 C 扩展不兼容 5.3 的话目前是没法使用的。

作者: | 评论: 没有评论 | 分类: 游戏开发 | 标签: , ,

发表评论

标记*号为必填项