构建 Lua |
|
有关详细说明,请参阅 "Beginning Lua Programming" 的 [第 1 章]。
BuildingModules 解释了如何为 Lua 构建 C 扩展模块。
请注意,Lua 是 ANSI C 的一个干净子集,可以作为 C 或 C++ 编译。Lua 头文件不包含 {#ifdef __cplusplus extern "C" {#endif ... Lua 头文件 ...#ifdef __cplusplus}#endif },因此 lua 可以通过简单地更改文件名称来作为 C 或 C++ 编译,而无需对文件内容进行任何更改。
如果 lua 被编译为 C 库,这在预打包的二进制文件中很常见,为了在 C++ 应用程序中嵌入 Lua(即链接 C 到 C++),您需要在 C++ 应用程序中包含 Lua 头文件时使用 extern "C"
,例如:
extern "C" { #include "lua.h" }
如果您没有这样做,您可能会因为 C++ 名称修饰而遇到 **链接错误**。
请不要在邮件列表中抱怨此事。:-) 请花时间搜索邮件列表,因为这个问题之前已经多次讨论过。
有人可能会说,如果您正在分发库的预打包二进制文件,那么您已经将 lua 核心编译为 C(最有可能)或 C++,如果您将 lua 编译为 C,您应该修改 lua 头文件以指示这一点。但是,作者不建议使用预构建的 lua 库,他们建议将 lua 源代码直接合并到您的应用程序中。有关讨论(页面末尾),请参阅 BuildingModules。
默认情况下,如果 lua 5.1 或更高版本被编译为 C++,它将使用 C++ 异常来展开堆栈,而不是 longjmp/setjmp,尽管这是可配置的(在编译时)。有关此内容的讨论,请参阅 luaconf.h 中的 LUAI_THROW/LUAI_TRY 附近。
对于 5.0,您可能需要联系 Alexey 以找到一个使用 C++ 异常而不是 setjmp/longjmp 的补丁,请在页面上找到他的电子邮件:' AlexeyVolynskov
请注意,从 lua 5.1.1 开始,在定义了 LUA_USE_MACOSX 的情况下构建时,lua 会避免在 OS X 上使用 dlopen() 和其他 dlfcn API,因为 dlopen() 以前不支持,除非使用第三方(开源)dlcompat 库。但是,从 OS X 10.3 开始,提供了 dlopen(),从 OS X 10.4 开始,dlopen() 是动态加载库的推荐方式(至少对于非 Objective-C 代码而言)。这意味着,如果您不想针对 10.3 之前的 OS X 版本,则 OS X 特定的模块加载代码完全没有必要。如果您定义了 LUA_USE_DLOPEN,它将优先于 LUA_USE_DL_DYLD。
有关更多信息,请参见 http://developer.apple.com/releasenotes/DeveloperTools/RN-dyld/index.html。
Lua 构建 [1] 包含构建 lua、luac 和库的文件。它适用于以下平台。它包含所有必要的源代码和构建文件。
vc6/Lua.dsw
并执行 Build
)。
tar xvzf luabuild-x.x.tgz ; cd LuaX/unix; make all
)
如果您想添加另一个平台,请联系 NickTrout。目前仅构建了 Lua 的静态链接版本。
将 src 和 src/lua 中的所有内容都执行以下操作:
bcc *.c -olua.exe
所有项目都必须在 Lua src 目录中创建,''1 Core.lib 和标准库'' 为 Win32 控制台或 GUI 创建一个 静态库(用于 .dll)(.lib),对库没有影响。添加安装文件中提到的必需文件。将 lua 包含目录添加到项目包含目录中。将编译器设置为 Pentium 代码 和 Word 数据对齐:然后您将能够在 luser_number.h 中定义 USE_FASTROUND。编译。
替代方案:为 **Win32** 控制台或 GUI 创建一个 **动态库(.dll)**,库本身是否为控制台或 GUI 无关紧要。添加安装文件提到的必要文件。修改 lua.h 和 lualib.h 文件,将 LUA_API 定义为 __declspec(dllexport) 以及 LUALIB_API 定义为 __declspec(dllexport)。将 lua 包含目录添加到项目包含目录中。将编译器设置为 **奔腾代码** 和 **字** 数据对齐:然后你就可以在 luser_number.h 中定义 USE_FASTROUND。编译。
注意:编译器会抱怨并产生关于不存在的结构(例如 lua_State)的警告。你可以安全地忽略它们。如果你想使用 USE_POPEN,你需要将 popen 和 pclose 转换为 _popen 和 _pclose。你可以将 USE_TMPNAME 定义为 1。2 Lua 解释器和编译器 为 **Win32** 和 **控制台** 创建一个 **可执行文件(.exe)**。包含 **核心** 和 **标准** 库以及安装文件提到的必要文件。将 lua 包含目录添加到项目包含目录中。将编译器设置为 **奔腾** 代码和 **字** 数据对齐。编译。你已经准备好了!
注意:如果你使用 Lua DLL 而不是 LIB,不要忘记在 lua.h 和 lualib.h 中将 LUA_API 定义为 __declspec(dllimport) 以及 LUALIB_API 定义为 __declspec(dllimport)。
简而言之,这包含一个 Visual Studio 解决方案和 3 个项目。一个项目用于将 Lua 5.x 构建为静态库,一个项目用于测试库是否正常工作,还有一个项目用于构建 luac。以下是关于此内容的详细信息 [Read Me] 以下是文件 [Visual Studio .Net 2003(版本 7.1)解决方案和项目文件]
注意:从 [Philippe Lhoste (PhiLho) 法语网站] 下载文件,我需要更新 Lua 页面以进行直接下载。
它们可以用于 Lua 4.0.1,只需稍作修改(此版本的特定项目也可用)。
基本上,我在 Lua 树的根目录中设置了一个 .dsw 文件(工作区),并在层次结构中散布了几个 .dsp(项目),以生成库文件、DLL 或可执行文件。
要编译,你应该先做库(依赖项应该会处理这个问题)。
为了做 DLL,我不得不创建 .def 文件,但对于 Lua 4.0.1,我只是使用了 make_def.lua 脚本(假设我已经有一个 Lua 二进制文件,当然 :-))。
你不需要创建 .def 文件来制作 DLL,只需将 LUA_API=__declspec(dllexport)
或 LUALIB_API=__declspec(dllexport)
添加到你的 C 编译器定义中,对我来说完美地工作了。 -- JaenSaul
是的,但在 Lua 4.0 时代,这种功能不可用,我从 4.0 项目派生了 5.0 项目。此外,我喜欢 .def 文件,它允许你一目了然地看到所有 API 函数... -- PhilippeLhoste
看起来有人为这种情况做了一个规定(至少在 5.1 版本中),使用 LUA_BUILD_AS_DLL 定义。 -- BobClown?
我还创建了一些资源文件,以提供漂亮的图标和一些版本信息。
简单来说
make mingw
但是你得到的 lua 可执行文件将不支持动态加载模块。如果你想启用此功能,你应该修改目标 mingw
为
mingw: $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS='-DLUA_DL_DLL -DLUA_BUILD_AS_DLL'" "MYLIBS=" "MYLDFLAGS=-s" \ lua.exe $(MAKE) "LUAC_T=luac.exe" luac.exe
对于那些愿意冒险的人(在 DLL 中导出额外的符号,这些符号不是官方的 Lua API),你可以通过将 mingw
目标更改为以下方式来构建 lua.exe 和 luac.exe:
mingw: $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" "LUAC_T=luac.exe" \ "AR=$(CC) -shared -Wl,--export-all-symbols -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" all
请注意,官方的 Lua 发行版创建并使用 lua51.dll
,而 LuaBinaries 分发 lua5.1.dll
。两者都使用 lua.exe
名称,但该应用程序链接到其中一个 DLL - 当两者都安装时,这可能是细微错误的来源(见下文“创建转发 DLL”)。
要正确安装 Lua,请打开顶层 Makefile 并更改
TO_BIN= lua luac
为 TO_BIN= lua.exe luac.exe lua51.dll
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
为 #cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
现在,对于一些旧版本...
以下是成功构建 Lua 5.0.2 的配置 [13] 和 Makefile [14] 示例。Lua 子目录中的 Makefile 不需要任何更改。使用目标 dll(即“make dll”)使用 lua.dll 和 lualib.dll 构建所有内容,包括 lua.exe 和 luac.exe。将 lua-5.0.2/bin 中的所有内容复制到 MSYS/local/bin,并将 liblualib.a 和 liblua.a 复制到 MSYS/local/lib。现在,你可以通过将动态加载库与 liblualib.a 和 liblua.a 链接来编译它们(-L /usr/local/lib -llua -llualib)。
以下是构建 lua-5.1-work5 作为一对 DLL 和一对应用程序的 Makefile 和 luaconf.h 示例 [15]。“make install” 将这些文件放入 Mingw /usr/local 子目录中。
警告:以下内容适用于旧版本的 Cygwin(1.5)。Cygwin 1.7 不再使用“-mno-cygwin”(有人:请更新此部分)。
不幸的是,Lua 5.1.1 Makefile 没有选项可以从 Cygwin 中包含的 MinGW 版本干净地构建。
要使用 Cygwin 轻松构建用于 Windows 的 Lua,无需修改 Makefile
make "CC=gcc -mno-cygwin" mingw
如果你还想使用 luac.exe
make "CC=gcc -mno-cygwin" -C src LUAC_T=luac.exe luac.exe
这些命令构建动态链接到 lua51.dll 的 lua.exe,并构建静态链接到 lua 的 luac.exe。我们不将 luac.exe 动态链接到 lua51.dll 的原因是 luac.exe 使用了 lua51.dll 未导出的某些内部函数。一个可能更好的方法是从 lua51.dll 导出这些额外的符号 [2],最好只添加这些符号。
除了以上两个命令,修改 Lua Makefile 也相当简单。在 src/Makefile 中添加以下内容:
mingw-cygwin: $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ "CC=gcc -mno-cygwin" \ "AR=gcc -mno-cygwin -shared -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe && \ $(MAKE) "LUAC_T=luac.exe" "CC=gcc -mno-cygwin" luac.exe
然后使用 make mingw-cygwin
构建。
要安装,在 make 命令中添加 "TO_LIB=lua51.dll"。例如:
make TO_LIB=lua51.dll local
以下描述了构建 Cygwin 版本的 Lua(即与 cygwin1.dll 链接 [*3])。对于 Cygwin 下的 MinGW 构建,请参见上面的内容。另请参见 Cygwin Lua 包 [3][4][5]。
"make posix" 将构建一个没有共享库支持或 readline 支持的 Cygwin Lua。
"make linux" 将构建一个没有共享库支持但有 readline 支持的 Cygwin Lua。[*1]
"make mingw" 将构建一个有共享库支持的 Cygwin Lua,但它不使用 "-DLUA_USE_LINUX",因此它并不理想。
要构建一个有共享库支持和 readline 支持的 Cygwin Lua,可以使用以下构建规则[*2]
cygwin: $(MAKE) "LUA_A=cyglua-5.1.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS=-DLUA_USE_LINUX -DLUA_BUILD_AS_DLL" \ "MYLIBS=-lreadline -lhistory" "MYLDFLAGS=-s" lua.exe
以上内容也适用于 Lua 5.2,只需更改 DLL 的名称。
cygwin: $(MAKE) "LUA_A=cyglua-5.2.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ "MYCFLAGS=-DLUA_USE_LINUX -DLUA_BUILD_AS_DLL" \ "MYLIBS=-lreadline -lhistory" "MYLDFLAGS=-s" lua.exe
注意:Cygwin 通常在共享库前加上 "cyg"。Cygwin 中的 Lua 包使用 "cyglua-5.1.dll",但您仍然可以使用传统的 Windows "lua51.dll" 或 "lua52.dll"。
与 Linux 不同,Cygwin 不需要 "-lncurses",尽管它不会造成伤害。
LUA_USE_ULONGJMP
是 LUA_POSIX
的一部分,反过来是 LUA_USE_LINUX
的一部分,它曾经在 Cygwin 1.5 中导致一个无害的警告 [16]。在 Cygwin 1.7 中,这种情况似乎不再发生,因为 Cygwin 1.7 定义了 _setjmp
。因此,现在可以在 Cygwin 中使用 LUA_POSIX
或 LUA_USE_LINUX
而不产生警告。
"MYLDFLAGS=-s" 是可选的:它从可执行文件中剥离符号,这些符号是不需要的,从而减小了文件大小。"RANLIB=strip --strip-unneeded" 也是可选的:这减少了 DLL 中不必要的符号数量。Lua Cygwin 包使用 "RANLIB=:"(即不做任何操作),也可以写成 "RANLIB=@:"(即没有输出)。Lua 默认的 "RANLIB=ranlib" 对 Windows DLL 无效。
Lua Cygwin 包使用 "AR=$(CC) -shared -Wl,--enable-auto-image-base -Wl,--enable-auto-import -Wl,--out-implib,liblua.dll.a -o"。"-Wl,--out-implib,liblua.dll.a" 会生成一个导入库(如果您需要的话,实际上在基于 Windows 的 gcc 中是可选的)。"-Wl,--enable-auto-import" 应该是 Cygwin 的标准 [6]。"-Wl,--enable-auto-image-base [7][8][9][10] 是一个可选的改进,但现在似乎默认启用了 [11][12]。因此,"-Wl,--enable-auto-image-base -Wl,--enable-auto-import" 似乎不再需要了。
您可能希望像 Lua Cygwin 包一样将 LUA_CPATH_DEFAULT 设置为使用 .dll 而不是 .so 作为 Lua C 模块的扩展名,但这只是可选的。
有关在 Cygwin 下使用 LuaRocks 的信息,请参见 [*4]
要使用 Dev-C++ 快速、干净(不脏!:-)) 地构建 Lua,请使用此 .bat 文件:[17]。您可能需要在运行此 .bat 文件之前更改您的路径(SET PATH=C:\Dev-Cpp\Bin;C:\Dev-Cpp\lib\gcc-lib\mingw32\3.2;%PATH% 请根据您的 Dev C++ 目录进行调整)。它会构建 lua.exe、luac.exe、lua5.dll 和 lualib5.dll。将其复制到 lua-5.0 目录并运行。我不愿说,但此 .bat 文件没有保证(它在我的 Windows XP 和 2000 上运行良好),我只是希望它有用(此外,它比 makefile 更易读)。要使用 devCpp 构建所有内容,请使用此 .bat/.cmd 文件 [18]。如果 DevCPP 不在 C:\Dev-Cpp\ 中,您需要对其进行编辑。将文件复制到 lua-5.0 目录并运行它,它将构建 liblua.a、liblualib.a、lua5.dll、lualib5.dll、lua.exe 和 luac.exe。我已经在 dev-cpp 5 beta 版上测试过。
Lua 5.0.2(以及大多数更高版本)可以使用这些 devcpp 配置在 Windows 中构建。1. 下载 lua tar.gz 并将其解压缩到您选择的文件夹中。2. 下载并解压缩此文件 [19] 到 lua-5.0.2 文件夹中,以便您有一个名为 devcpp 的子文件夹 3. 打开 devcpp 文件夹并双击 corelibs.dev 等。
注意:将 -DLUA_API=__declspec(dllexport) 更改为 -DLUA_API='__declspec(dllexport)'
只需点击编译按钮,一切就应该没问题。请注意,您的系统路径中绝对不能有任何 lua.dll。否则,标准库和 lua.exe 可能无法链接到正确的 dll。我不知道如何直接从 devcpp 文件中设置它。
Lua 5.1 DLL 的默认名称(如 Lua makefile 中所指定)为 lua51.dll。但是,那里有几个预编译的二进制文件使用另一种约定。当您使用使用一种约定(例如 lua51.dll)的解释器并尝试加载使用另一种约定(lua5.1.dll)的模块时,就会出现真正的问题。如果两个 dll 都存在,这两个 dll 都将被加载,导致代码重复,以及与静态变量重复相关的潜在错误(例如,在一个 dll 中释放一块内存,而它是在另一个 dll 中分配的,会导致不可预测的结果)。
解决方案是确保解释器和所有模块使用相同的 dll。如果它们链接了不同的 dll 名称,您可以创建一个类似于假 dll(称为代理 dll 或转发 dll)的东西,它将所有 API 调用转发到正确的 dll。在上面的示例中,您可以创建一个名为 lua5.1.dll 的代理 dll,它将所有调用转发到 lua51.dll。这样,解释器和模块将使用相同的 dll 副本(lua51.dll),避免上述问题。
您可以在以下位置找到生成此类 DLL 的脚本:LuaProxyDllThree 和 LuaProxyDllTwo。
这是一个最小的 CMakeLists 文件
PROJECT ( lua ) IF( NOT WIN32 ) message( FATAL_ERROR "Written for window only" ) ENDIF() CMAKE_MINIMUM_REQUIRED(VERSION 2.8) # remove warnings ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS ) SET (HDR_LIBLUA src/lapi.h src/lauxlib.h src/lcode.h src/lctype.h src/ldebug.h src/ldo.h src/lfunc.h src/lgc.h src/llex.h src/llimits.h src/lmem.h src/lobject.h src/lopcodes.h src/lparser.h src/lstate.h src/lstring.h src/ltable.h src/ltm.h src/lua.h src/luaconf.h src/lualib.h src/lundump.h src/lvm.h src/lzio.h ) #SET_SOURCE_FILES_PROPERTIES(${HDR_LIBLUA} PROPERTIES HEADER_FILE_ONLY TRUE) #include_directories(src) # Build Libraries SET (SRC_LIBLUA src/lapi.c src/lauxlib.c src/lbaselib.c src/lbitlib.c src/lcode.c src/lcorolib.c src/lctype.c src/ldblib.c src/ldebug.c src/ldo.c src/ldump.c src/lfunc.c src/lgc.c src/linit.c src/liolib.c src/llex.c src/lmathlib.c src/lmem.c src/loadlib.c src/lobject.c src/lopcodes.c src/loslib.c src/lparser.c src/lstate.c src/lstring.c src/lstrlib.c src/ltable.c src/ltablib.c src/ltm.c src/lundump.c src/lvm.c src/lzio.c ) SET ( SRC_LUA src/lua.c ) SET ( SRC_LUAC src/luac.c ) # compile with C++ compiler set_source_files_properties(${SRC_LIBLUA} ${SRC_LUA} ${SRC_LUAC} PROPERTIES LANGUAGE CXX) # append headers to sources to make them show up in MSVC GUI LIST(APPEND SRC_LIBLUA ${HDR_LIBLUA}) #Library ADD_LIBRARY ( lualib ${SRC_LIBLUA} ) #DLL ADD_LIBRARY ( lua5.2 SHARED ${SRC_LIBLUA} ) SET_TARGET_PROPERTIES (lua5.2 PROPERTIES DEFINE_SYMBOL "LUA_BUILD_AS_DLL" ) #exe ADD_EXECUTABLE ( lua ${SRC_LUA} ) ADD_EXECUTABLE ( luac ${SRC_LUAC} ) #lua uses a DLL; luac uses a library TARGET_LINK_LIBRARIES ( lua lua5.2 ) TARGET_LINK_LIBRARIES ( luac lualib )
将此复制并粘贴到 5.2.2 根目录中的 CMakeLists.txt 文件中
使用类似的命令
cmake -G "Visual Studio 10"
取决于您的开发工作室版本。使用 lua.sln 文件进行编译。