Lua在Mac OS X上编译脚本 - Intel vs PPC

Sir*_*tty 4 macos lua cross-compiling luac

多年来一直在Mac OS X通用二进制应用程序中使用Lua 5.0.Lua脚本使用luac编译,编译后的脚本与app捆绑在一起.他们在Tiger和Leopard,Intel或PPC中都能正常使用.

为了避免当时的库问题,我只是将Lua src树添加到我的Xcode项目中并按原样编译,没有任何问题.

是时候更新到更现代的Lua版本,所以我用5.1.4替换了源代码树.我使用make macosx重建了luac (机器在Intel上运行Leopard).

与往常一样,未编译的脚本在Tiger和Leopard,Intel和PPC中正常工作.

但是,现在编译的脚本无法在PPC计算机上加载.

所以我用'ansi'标志重建了luac,并重新编译了我的脚本.同样的错误.同样,'generic'的构建标志也没有产生任何乐趣.

谁能告诉我接下来能做些什么?

RBe*_*eig 13

Lua的编译脚本几乎是在短标题之后转储的原始字节码.头文件记录了用于编译字节码的平台的一些属性,但加载器仅验证当前平台具有相同的属性.

不幸的是,这会在加载在另一个平台上编译的字节码时产生问题,即使是由相同版本的Lua编译也是如此.当然,不能期望由不同版本的Lua编译的脚本工作,并且由于Lua的版本号包含在字节码头中,因此加载它们的尝试被核心捕获.

简单的答案是不编译脚本.如果Lua编译脚本本身,您只需要担心应用程序的各种版本中的Lua核心之间可能存在版本不匹配,这并不难解决.

实际上支持编译字节码的完全交叉兼容性并不容易.在该电子邮件中,Mike Pall确定了以下问题:

  1. Endianess:根据需要交换输出.

  2. sizeof(size_t),影响巨大的字符串常量:降级时检查溢出.

  3. sizeof(int),影响MAXARG_BxMAXARG_sBx:降级时检查溢出.

  4. typeof(lua_Number):C语言简单,但仅当主机和目标遵循相同的FP标准时; 升级时的精度损失(罕见情况); 在降级到时,警告非整数 int32.

从我在邮件列表中看到的有关此问题的所有讨论中,我看到了两种可行的方法,假设您不愿意考虑只发送未编译的Lua脚本.

第一个是在加载编译脚本时修复字节顺序.事实证明这比你期望的更容易,因为它可以通过替换读取脚本文件的低级函数而不重新编译核心本身来完成.事实上,它甚至可以在纯Lua中完成,方法是将自己的块读取器函数提供给lua_load().只要您的平台上唯一的兼容性问题是字节顺序,这应该可以工作.

第二种是修补核心本身,以便在所有平台上使用编译脚本的通用表示.Luiz Henrique de Figueiredo已经描述了这一点:

....我确信字节顺序或交叉编译的最佳路径是第三方转储/转储对.文件ldump.c和lundump.c是完全可替换的; 他们导出一个明确定义的单一入口点.预编译块的格式根本不是神圣的; 你可以使用任何格式,只要ldump.c和lundump.c同意它.(例如,Rici Lake正在考虑为预编译块编写文本格式.)....

就个人而言,我建议认真考虑不预先编译脚本,从而完全避免平台可移植性问题.

编辑:由于lhf的评论,我已经更新了我对字节码标题的描述.我还没有读过Lua源代码的这一部分,我可能应该先检查它,然后对标题中是否存在哪些信息非常自信.

这里的片段lundump.c形成了与运行平台匹配的标头副本,用于与正在加载的字节码进行比较.它只是与memcmp()文件中标题的精确匹配进行比较,因此任何不匹配都会导致stock loader(luaU_undump())拒绝该文件.

/*
* make header
*/
void luaU_header (char* h)
{
 int x=1;
 memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
 h+=sizeof(LUA_SIGNATURE)-1;
 *h++=(char)LUAC_VERSION;
 *h++=(char)LUAC_FORMAT;
 *h++=(char)*(char*)&x;                         /* endianness */
 *h++=(char)sizeof(int);
 *h++=(char)sizeof(size_t);
 *h++=(char)sizeof(Instruction);
 *h++=(char)sizeof(lua_Number);
 *h++=(char)(((lua_Number)0.5)==0);             /* is lua_Number integral? */
}
Run Code Online (Sandbox Code Playgroud)

如可以看到的,所述报头是12个字节长,包含一个签名(4个字节," <esc>Lua"),版本和格式码,字节序一个标志字节,大小的种类int,size_t,Instruction,和lua_Number,和一个标志,指示是否lua_Number是一个积分型.

这允许捕获大多数平台区别,但不会尝试捕获平台可以区别的各种方式.

我仍然支持上面提出的建议:首先,提供可编辑的来源; 或者第二,定制ldump.clundump.c存储和加载通用格式,附加说明任何自定义格式都应重新定义标题的LUAC_FORMAT字节,以免与库存字节码格式混淆.