引言:
用 lua 来编写功能的时间很长,但对于 lua 的底层原理其实知之甚少,只知道它是开源的,用 C 语言写的。今天趁着手头任务不紧,想着还是花点时间读读源码吧,总得调点恶心自己的事情干干知道自己的极限在哪里。
起步:
1.源码下载:
首先先到官网下载一份最新版的 lua 源码 ,这里我选择最新的 lua-5.3.4.tar.gz
先解压看一下源码中的目录结构:
lua-5.3.4
|-- doc
|-- src
|-- Makefile
|-- README
其中 doc
中是官方提供的使用手册,而 src
中保存这 lua 的所有 C 源码,在正式开始看源码之前,建议先看一下 doc/readme.html
这个官方提供的说明文档。
2.编译环境:
通常都是在 Unix 或基于 Unix 的系统下来编译 lua 的源码,例如:Linux 或 Mac OS X 等,但是作为一个前端开发者,显然使用 Windows 会更加得心应手一点,参考官方的手册的这段内容:
Building Lua on other systems
If you’re not using the usual Unix tools, then the instructions for building Lua depend on the compiler you use. You’ll need to create projects (or whatever your compiler uses) for building the library, the interpreter, and the compiler, as follows:
library:
lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c loadlib.c linit.c
interpreter:
library, lua.c
compiler:
library, luac.c
To use Lua as a library in your own programs you’ll need to know how to create and use libraries with your compiler. Moreover, to dynamically load C libraries for Lua you’ll need to know how to create dynamic libraries and you’ll need to make sure that the Lua API functions are accessible to those dynamic libraries — but don’t link the Lua library into each dynamic library. For Unix, we recommend that the Lua library be linked statically into the host program and its symbols exported for dynamic linking; src/Makefile does this for the Lua interpreter. For Windows, we recommend that the Lua library be a DLL. In all cases, the compiler luac should be linked statically.
As mentioned above, you may edit src/luaconf.h to customize some features before building Lua.
大概意思就是:
需要创建若干个工程,用来分别编译生成三个对象:lua 的库文件 、 lua 解释器 和 lua 的编译器。
而且,官方建议:不要将 Lua 库链入每个动态库 。
- 在 Unix 下,建议把 Lua 库静态链入宿主程序中,然后将符号导出用与动态链接(
src/Makefile
就是这样处理 Lua 解释器的); - 在 Windows 下,建议把 Lua 库编译成一个
DLL
。
不管是哪个平台下,编译器 luac
都应该静态链接。
编译步骤:
此时,我的 Windows 已经安装了 Visual Studio 2015,我打算直接使用它来编译,从上面的内容可知我们需要编译得到三个对象,分别是:lua 的库文件 、 lua 解释器 和 lua 的编译器,大致步骤如下:
1.安装一下 Visual C++
插件:
因为之前使用 VS 主要是进行 C# 开发,所以并没有安装对于 C++ 支持的插件,假如已安装可以忽略此步骤:【文件】—>【新建】—>【项目…】—>【 Visual C++】—>【 安装适用于 Windows 桌面的 Visual C++ 2015 工具】,此工具包含了:编译器、通用 CRT 和 Windows 8.1 SDK。
2.生成库文件 Lua5.3.4.lib
:
- 创建一个 C++ 的 Win32 控制台应用程序:
步骤如下:【文件】—>【新建】—>【项目…】—>【 Visual C++】—>【Win32 控制台应用程序】,取名为Lua5.3.4
。在应用程序设置中勾选应用类型为 【静态库】 ,附加选项中去掉 【预编译头】 的勾选,点击 【完成】。新建完毕后得到如下目录结构:
Lua5.3.4
|-- 引用
|-- 外部依赖项
|-- 头文件
|-- 源文件
|-- 资源文件
|-- ReadMe.txt
- 源码引入:
- 创建源码目录: 在当前项目根目录下创建一个文件夹,取名为
LuaSrc
,然后将上面 lua-5.3.4 源码包解压目录下/src
目录中的所有文件都复制到此目录中。 - 头文件引入:【头文件】右键 —> 【添加】—>【现有项…】,选择
LuaSrc
目录,从该目录中选中所有.h
后缀的文件,点击 【添加】将源码头文件都添加进来; - 源文件引入:【源文件】右键 —> 【添加】—>【现有项…】,选择
LuaSrc
目录,从该目录中选中所有.c
后缀的文件(注:这里需要剔除lua.c
和luac.c
,这两个源文件不引进来),点击 【添加】将源码源文件都添加进来。
- 配置属性:
- 编译附加目录: 【Lua5.3.4】右键—>【属性】—>【C/C++】—>【常规】—>【附加包含目录】,填写
LuaSrc
目录的路径,然后点击 【应用】让设置生效; - 编译目标: 切换到 【C/C++】—>【高级】,选中 【编译为】,切换其参数为 【编译为 C 代码 (/TC)】,点后点击 【应用】让设置生效;
- 最后点击 【确定】 关闭配置属性界面。
- 编译库:
设置菜单栏中选择编译目标版本为 【Release】,然后点击【本地 Windows 调试器】按钮进行编译,输出栏输出如下内容表示编译成功:
1>------ 已启动生成: 项目: Lua5.3.4, 配置: Release Win32 ------
1> Lua5.3.4.vcxproj -> E:\Skynet\Tools\Lua5.3.4\Release\Lua5.3.4.lib
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
可以在日志输出的目录下获得编译好的 Lua5.3.4.lib
文件,这是上面说到的三个目标对象中的第一个,即 lua 的库文件。
3.生成解释器 Lua.exe
:
- 创建一个 C++ 的 Win32 控制台应用程序:
参考上面的步骤,创建一个 C++ 的 Win32 控制台应用程序,只是在应用程序设置步骤中不在选择 【静态库】而是选择【控制台应用程序】,选勾选为【空项目】,而且不用去掉【预编译头】的勾选,项目取名为Lua
。 - 源码引入:
步骤与上述基本一致,只是引入源文件的时候,只剔除luac.c
,把lua.c
和其他*.c
文件都引入到源文件中。 - 编译解释器:
直接设置菜单栏中选择编译目标版本为 【Release】,然后点击【本地 Windows 调试器】按钮进行编译,假如直接弹出一个命令行窗口,并且窗口内输出:
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio
>
可以直接输入一个 Lua 打印语句,Enter 即可输出执行结果,这就表示解释器生成成功,可以在项目根目录下的 Release
目录下找到一个 Lua.exe
文件,双击即可运行,并且可以直接在弹出窗口进行 lua 语句的运行,这就是上面说到的三个目标对象中的第二个,即 lua 的解释器。
4.生成编译器 Luac.exe
:
步骤与上一步生成 lua 的解释器基本相同,唯一的区别在于源码引入 步骤,只剔除 lua.c
,把 luac.c
和其他 *.c
文件都引入到源文件中。然后运行项目,在 Release
目录下可以得到一个 luac.exe
,这是上面说到的三个目标对象中的第三个,即 lua 的编译器。
小结:
至此,我们就完成了 lua 最主要的三个工具的生成操作,后面我们要开始正式地解读 lua 的源码。
参考资料: