Mac OS X 上的 Lua 编译脚本 - Intel 与 PPC

发布于 2024-07-25 10:56:31 字数 539 浏览 3 评论 0原文

在 Mac OS X 通用二进制应用程序中使用 Lua 5.0 已有几年了。 Lua 脚本使用 luac 编译,编译后的脚本与应用程序捆绑在一起。 它们在Tiger和Leopard、Intel或PPC中都可以正常工作。

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

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

未编译脚本一如既往地在 Tiger 和 Leopard、Intel 和 PPC 中正常工作。

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

所以我用“ansi”标志重建了 luac,并重新编译了我的脚本。 同样的错误。 同样,“通用”的构建标志也不会带来任何乐趣。

谁能告诉我下一步可以做什么吗?

Been using Lua 5.0 in a Mac OS X universal binary app for some years. Lua scripts are compiled using luac and the compiled scripts are bundled with the app. They have worked properly in Tiger and Leopard, Intel or PPC.

To avoid library problems at the time, I simply added the Lua src tree to my Xcode project and compiled as is, with no problems.

It was time to update to a more modern version of Lua so I replaced my source tree with that of 5.1.4. I rebuilt luac using make macosx (machine is running Leopard on Intel).

Uncompiled scripts work properly in Tiger and Leopard, Intel and PPC, as always.

However, now compiled scripts fail to load on PPC machines.

So I rebuilt luac with the 'ansi' flag, and recompiled my scripts. Same error. Similarly, a build flag of 'generic' produced no joy.

Can anyone please advise on what I can do next?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

忱杏 2024-08-01 10:56:31

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 中完成,通过提供你自己的 chunk reader< /a> 函数到 lua_load()。 只要您的平台上唯一的兼容性问题是字节顺序,这应该就可以工作。

第二个是修补核心本身,以便在所有平台上使用编译脚本的通用表示形式。 Luiz Henrique de Figueiredo 对此进行了尽可能的描述:

....
我确信最好的路线
字节顺序或交叉编译是
第三方转储/取消转储对。 这
文件 ldump.c 和 lundump.c 是
完全可更换; 他们出口一个
单一的、定义明确的入口点。 这
预编译块的格式不是
神圣不可侵犯; 你可以使用任何格式,
只要 ldump.c 和 lundump.c 一致
关于它。 (例如,瑞慈湖
考虑编写文本格式
预编译块。)
....

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

编辑:感谢 lhf 的评论,我更新了字节码标头的描述。 我还没有读过 Lua 源代码的这一部分,在对标头中存在或不存在哪些信息如此自信之前,我可能应该检查一下它。

这是来自 lundump.c 形成与运行平台匹配的标头副本,以便与正在加载的字节码进行比较。 它只是与 memcmp() 进行比较,以确保与文件中的标头完全匹配,因此任何不匹配都会导致库存加载程序 (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? */
}

可以看出,标头长 12 个字节,包含签名(4 个字节,“Lua”)、版本和格式代码、字节序标志字节、类型大小intsize_tInstructionlua_Number,以及一个指示是否 lua_Number 的标志是一个整型。

这允许捕获大多数平台差异,但不会尝试捕获平台可能存在差异的所有方式。

我仍然坚持上面提出的建议:第一,发布可编译的源; 或者第二,自定义 ldump.clundump.c 来存储和加载通用格式,附加注意的是任何自定义格式都应重新定义标头的 LUAC_FORMAT 字节,以便以免与库存字节码格式混淆。

Lua's compiled scripts are pretty much the raw bytecode dumped out after a short header. The header documents some of the properties of the platform used to compile the bytecode, but the loader only verifies that the current platform has the same properties.

Unfortunately, this creates problems when loading bytecode compiled on another platform, even if compiled by the very same version of Lua. Of course, scripts compiled by different versions of Lua cannot be expected to work, and since the version number of Lua is included in the bytecode header, the attempt to load them is caught by the core.

The simple answer is to just not compile scripts. If Lua compiles the script itself, you only have to worry about possible version mismatches between Lua cores in your various builds of your application, and that isn't hard to deal with.

Actually supporting a full cross compatibility for compiled bytecode is not easy. In that email, Mike Pall identified the following issues:

  1. Endianess: swap on output as needed.

  2. sizeof(size_t), affects huge string constants: check for overflow when
    downgrading.

  3. sizeof(int), affectsMAXARG_Bx and MAXARG_sBx: check for overflow when
    downgrading.

  4. typeof(lua_Number): easy in C, but only when the host and the target
    follow the same FP standard; precision
    loss when upgrading (rare case);
    warn about non-integer numbers when
    downgrading to int32.

From all the discussions that I've seen about this issue on the mailing list, I see two likely viable approaches, assuming that you are unwilling to consider just shipping the uncompiled Lua scripts.

The first would be to fix the byte order as the compiled scripts are loaded. That turns out to be easier to do than you'd expect, as it can be done by replacing the low-level function that reads the script file without recompiling the core itself. In fact, it can even be done in pure Lua, by supplying your own chunk reader function to lua_load(). This should work as long as the only compatibility issue over your platforms is byte order.

The second is to patch the core itself to use a common representation for compiled scripts on all platforms. This has been described as possible by Luiz Henrique de Figueiredo:

....
I'm convinced that the best route to
byte order or cross-compiling is
third-party dump/undump pairs. The
files ldump.c and lundump.c are
completely replaceable; they export a
single, well-defined, entry point. The
format of precompiled chunks is not
sacred at all; you can use any format,
as long as ldump.c and lundump.c agree
about it. (For instance, Rici Lake is
considering writing a text format for
precompiled chunks.)
....

Personally, I'd recommend giving serious consideration to not pre-compiling the scripts and thus avoid the platform portability issues entirely.

Edit: I've updated my description of the bytecode header thanks to lhf's comment. I hadn't read this part of the Lua source yet, and I probably should have checked it before being quite so assertive about what information is or is not present in the header.

Here is the fragment from lundump.c that forms a copy of the header matching the running platform for comparison to the bytecode being loaded. It is simply compared with memcmp() for an exact match to the header from the file, so any mismatch will cause the stock loader (luaU_undump()) to reject the file.

/*
* 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? */
}

As can be seen, the header is 12 bytes long and contains a signature (4 bytes, "<esc>Lua"), version and format codes, a flag byte for endianness, sizes of the types int, size_t, Instruction, and lua_Number, and a flag indicating whether lua_Number is an integral type.

This allows most platform distinctions to be caught, but doesn't attempt to catch every way in which platforms can differ.

I still stand by the recommendations made above: first, ship compilable sources; or second, customize ldump.c and lundump.c to store and load a common format, with the additional note that any custom format should redefine the LUAC_FORMAT byte of the header so as to not be confused with the stock bytecode format.

掌心的温暖 2024-08-01 10:56:31

您可能想要使用支持不同字节序的修补字节码加载器。
请参阅

You may want to use a patched bytecode loader that supports different endianness.
See this.

假面具 2024-08-01 10:56:31

我本想对 RBerteig 的帖子发表评论,但显然我还没有足够的声誉来这样做。 在努力使 LuaRPC 跟上 Lua 5.1.x 的速度并使其与嵌入式目标一起工作时,我一直在修改 ldump.c 和 lundump.c 源代码,以使它们更加灵活。 嵌入式 Lua 项目 (eLua) 已经包含了一些您可以在 Lua 列表中找到的补丁,但我添加了更多补丁,以使 lundump 对在不同架构上编译的脚本更加友好。 它还提供了交叉编译支持,以便您可以针对与主机系统不同的目标进行构建(请参阅与下面的链接位于同一目录中的 luac.c)。

如果您有兴趣查看修改,可以在 eLua 源存储库中找到它们:
http://svn.berlios.de/wsvn/elua/ trunk/src/lua/lundump.c
http://svn.berlios.de/wsvn/elua/ trunk/src/lua/lundump.h
http://svn.berlios.de/wsvn/elua/ trunk/src/lua/ldump.c

标准免责声明:
我并不声称这些修改是完美的或在任何情况下都有效。 如果您使用它并发现任何损坏,我很高兴听到它,以便可以修复它。

I would have commented on RBerteig's post, but I apparently don't have enough reputation yet to be able to do so. In working on bringing LuaRPC up to speed with Lua 5.1.x AND making it work with embedded targets, I've been modifying the ldump.c and lundump.c sources to make them both a bit more flexible. The embedded Lua project (eLua) already had some of the patches you can find on the Lua list, but I've added a bit more to make lundump a little more friendly to scripts compiled on different architectures. There's also cross-compilation support provided so that you can build for targets differing from the host system (see luac.c in the same directory as the links below).

If you're interested in checking out the modifications, you can find them in the eLua source repository:
http://svn.berlios.de/wsvn/elua/trunk/src/lua/lundump.c
http://svn.berlios.de/wsvn/elua/trunk/src/lua/lundump.h
http://svn.berlios.de/wsvn/elua/trunk/src/lua/ldump.c

Standard Disclaimer:
I make no claim that the modifications are perfect or work in every situation. If you use it and find anything broken, I'd be glad to hear about it so that it can be fixed.

情释 2024-08-01 10:56:31

Lua 字节码不可移植。 您应该随应用程序一起提供源脚本。

如果下载大小是一个问题,它们通常比字节码形式短。

如果担心知识产权,您可以使用代码混淆器,并记住反汇编 Lua 字节码并不困难。

如果加载时间是一个问题,您可以在安装脚本中本地预编译源。

Lua bytecode is not portable. You should ship source scripts with your application.

If download size is a concern, they are generally shorter than the bytecode form.

If intellectual property is a concern, you can use a code obfuscator, and keep in mind that disassembling Lua bytecode is anything but difficult.

If loading time is a concern, you can precompile the sources locally in your installation script.

叫思念不要吵 2024-08-01 10:56:31

我猜想您是在英特尔机器上编译脚本的。

编译后的脚本非常不可移植。 如果您确实想要预编译脚本,则需要包含每个编译脚本的两个版本:一种用于 Intel,一种用于 PPC。 您的应用程序必须询问它正在运行的程序并使用正确的编译脚本。

I conjecture that you compiled the scripts on an Intel box.

Compiled scripts are wildly unportable. If you really want to precompile scripts, you'll need to include two versions of each compiled script: one for Intel and one for PPC. Your app will have to interrogate which program it's running on and use the correct compiled script.

楠木可依 2024-08-01 10:56:31

我没有足够的声誉来发表评论,所以我必须提供这个作为答案,即使这不是所提问题的适当答案。 对不起。

这里有一个 Lua 混淆器:

http://www.capprime.com/CapprimeLuaObfuscator/CapprimeLuaObfuscator。 aspx

完全披露:我是混淆器的作者,我知道它并不完美。 欢迎并鼓励提供反馈(上面的页面有一个反馈页面)。

I don't have enough reputation to comment, so I have to provide this as an answer instead even though it's not an appropriate answer to the question asked. Sorry.

There is an Lua Obfuscator available here:

http://www.capprime.com/CapprimeLuaObfuscator/CapprimeLuaObfuscator.aspx

Full disclosure: I am the author of the obfuscator and I am aware it is not perfect. Feedback is welcome and encouraged (there is a feedback page available from the above page).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文