Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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. </p> <p>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.</p> <p>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.</p> <p>Actually supporting a full cross compatibility for compiled bytecode is <a href="http://lua-users.org/lists/lua-l/2005-06/msg00048.html" rel="noreferrer">not easy</a>. In that email, Mike Pall identified the following issues:</p> <blockquote> <ol> <li><p>Endianess: swap on output as needed.</p></li> <li><p><code>sizeof(size_t)</code>, affects huge string constants: check for overflow when downgrading.</p></li> <li><p><code>sizeof(int)</code>, affects<code>MAXARG_Bx</code> and <code>MAXARG_sBx</code>: check for overflow when downgrading.</p></li> <li><p><code>typeof(lua_Number)</code>: 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 <code>int32</code>.</p></li> </ol> </blockquote> <p>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.</p> <p>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 <a href="http://www.lua.org/manual/5.1/manual.html#lua_Reader" rel="noreferrer">chunk reader</a> function to <a href="http://www.lua.org/manual/5.1/manual.html#lua_load" rel="noreferrer">lua_load()</a>. This should work as long as the only compatibility issue over your platforms is byte order. </p> <p>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 <a href="http://lua-users.org/lists/lua-l/2005-06/msg00073.html" rel="noreferrer">Luiz Henrique de Figueiredo</a>:</p> <blockquote> <p>.... 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.) ....</p> </blockquote> <p>Personally, I'd recommend giving serious consideration to not pre-compiling the scripts and thus avoid the platform portability issues entirely. </p> <p><strong>Edit:</strong> 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.</p> <p>Here is the fragment from <a href="http://www.lua.org/source/5.1/lundump.c.html#luaU_header" rel="noreferrer"><code>lundump.c</code></a> that forms a copy of the header matching the running platform for comparison to the bytecode being loaded. It is simply compared with <code>memcmp()</code> for an exact match to the header from the file, so any mismatch will cause the stock loader (<a href="http://www.lua.org/source/5.1/lundump.c.html#luaU_undump" rel="noreferrer"><code>luaU_undump()</code></a>) to reject the file.</p> <pre><code>/* * 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*)&amp;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? */ } </code></pre> <p>As can be seen, the header is 12 bytes long and contains a signature (4 bytes, "<code>&lt;esc&gt;Lua</code>"), version and format codes, a flag byte for endianness, sizes of the types <code>int</code>, <code>size_t</code>, <code>Instruction</code>, and <code>lua_Number</code>, and a flag indicating whether <code>lua_Number</code> is an integral type.</p> <p>This allows most platform distinctions to be caught, but doesn't attempt to catch every way in which platforms can differ. </p> <p>I still stand by the recommendations made above: first, ship compilable sources; or second, customize <code>ldump.c</code> and <code>lundump.c</code> 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.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload