官方提供是一在 unix 环境下进行编译的方式,所以就琢磨了一下怎么样在 Windows 环境下进行编译出来。

前提:安装了 vs2017 (或者其他版本)

编译步骤

下载源代码

可以在 这个地址 下载源代码,我下载的 5.3.5。

皆有一下的目录结构如下:

├── doc
│   ├── contents.html
│   ├── index.css
│   ├── logo.gif
│   ├── lua.1
│   ├── lua.css
│   ├── luac.1
│   ├── manual.css
│   ├── manual.html
│   ├── osi-certified-72x60.png
│   └── readme.html
├── Makefile
├── README
└── src
├── lapi.c
├── lapi.h
├── lauxlib.c
├── lauxlib.h
├── lbaselib.c
├── lbitlib.c
├── lcode.c
├── lcode.h
├── lcorolib.c
├── lctype.c
├── lctype.h
├── ldblib.c
├── ldebug.c
├── ldebug.h
├── ldo.c
├── ldo.h
├── ldump.c
├── lfunc.c
├── lfunc.h
├── lgc.c
├── lgc.h
├── linit.c
├── liolib.c
├── llex.c
├── llex.h
├── llimits.h
├── lmathlib.c
├── lmem.c
├── lmem.h
├── loadlib.c
├── lobject.c
├── lobject.h
├── lopcodes.c
├── lopcodes.h
├── loslib.c
├── lparser.c
├── lparser.h
├── lprefix.h
├── lstate.c
├── lstate.h
├── lstring.c
├── lstring.h
├── lstrlib.c
├── ltable.c
├── ltable.h
├── ltablib.c
├── ltm.c
├── ltm.h
├── lua.c
├── lua.h
├── lua.hpp
├── lua.o
├── luac.c
├── luac.o
├── luaconf.h
├── lualib.h
├── lundump.c
├── lundump.h
├── lutf8lib.c
├── lvm.c
├── lvm.h
├── lzio.c
├── lzio.h
└── Makefile

编译

编译源文件

我们采用两步的方式,先将 所有的 .c 源文件编译成 obj 文件,然后再将 obj 文件按照需求 链接成静态库,或者动态库。

cd src
cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.c

注意,在这个地方我们使用了 /MD 选项,这将会导致我们的链接至 msvcrt.lib 这个库, 这个很重要,因为现在程序都这样链接了。

链接生成动态库

因为 lua.c luac.c 这两个文件是有入口函数 main 对于库文件是不需要的,所以我们将其命名为其他名称,否则就会链接到我们的库内出错。

ren lua.obj lua.o
ren luac.obj lua.o
link /DLL /out:lua.dll l*.obj

生成Lua解释器

事实上这一步其实就是将我们的 lua.c 编译后生成的 lua.obj (我们已经改明为 lua.o) 与我们的静态库链接起来

link /OUT:lua.exe lua.o lua.lib

生成静态库

这一步和第二步一样,不过使用的命令不同,同时不会生成 dll 文件。

lib /OUT:lua.lib *.obj

生成 Luac 编译器

同上,

link /OUT:luac.exe luac.o lua.lib

完整文件

@echo off
cd src
echo "1. compile all .c source files"
cl /O2 /W3 /c /DLUA_BUILD_AS_DLL l*.c
ren lua.obj lua.o
ren luac.obj luac.o

echo "2. link to dynamic library .dll"
link /DLL /IMPLIB:lua.lib /out:lua.dll l*.obj

echo "3. generate lua.exe"
link /OUT:lua.exe lua.o lua.lib

echo "4. generate static library .lib"
lib /OUT:lua.lib *.obj

echo "5. generate luac.exe"
link /OUT:luac.exe luac.o lua.lib
cd ..

编译后的工作

编译后我按照官方提供的在 unix 下编译后安装的目录结构进行了一下配置:


├── install
│   ├── bin
│   │   ├── lua.exe
│   │   └── luac.exe
│   ├── include
│   │   ├── lauxlib.h
│   │   ├── lua.h
│   │   ├── lua.hpp
│   │   ├── luaconf.h
│   │   └── lualib.h
│   ├── lib
│   │   ├── liblua.a
│   │   ├── lua
│   │   │   └── 5.3
│   │   ├── lua.lib
│   │   └── luac.lib
│   ├── man
│   │   └── man1
│   │   ├── lua.1
│   │   └── luac.1
│   └── share
│   └── lua
│   └── 5.3
├── Makefile
├── README
└── src
├── lapi.c
├── lapi.h
....
...

重点是在 install 目录下建立了 bin, lib, include 三个目录分别来放库,可执行文件,和头文件。

添加环境变量

LUA_DIR=d:\Repo\lua-5.3.5\install\bin\

VS项目设置

  1. 项目属性——> C/C++ ——> General ——> Additional Include Directories,添加 $(LUA_DIR)\include
  2. 项目属性——> Linker ——> General——> Additional Library Dir 添加 $(LUA_DIR)\lib
  3. 项目属性——> Linker ——> Input ——> Additional Dependencies. 添加 lua.lib

测试例子

#include "pch.h"
#include <iostream>
#include "lua.hpp"

using namespace std;
int main()
{
std::cout << "Hello World!\n";
lua_State* L = luaL_newstate();
luaL_openlibs(L);

if (luaL_dofile(L,"test.lua"))
{
const char* err = lua_tostring(L,-1);
cout << err << endl;
}

lua_close(L);
getchar();
return 0;
}
-- test.lua

for k,v in pairs(_G) do
print(k,v)
end

问题

  1. LINK : warning LNK4098: defaultlib ‘LIBCMT’ conflicts with use of other libs; use /NODEFAULTLIB:library
    这个是我们的链接方式和宿主程序链接方式不一致造成的。
  2. X64 无法识别外部符号
    需要用 cl 命令来生成 64 位的静态库