2012-03-06 7 views
14

He incluido lua junto con un fragmento de bytecode en un proyecto escrito en C. Ahora cuando extiendo mi base de código lua agregando archivos .lua, ¿hay alguna manera de mantener este código en un solo fragmento de bytecode?¿Guardando todo en un solo fragmento de bytecode lua?

(sé cómo cargar varios fragmentos de código de bytes. Pero lo que es cargar un solo trozo y luego olvidar el código de unión que sólo parecen cómodos.)

He intentado utilizar la inclusión textual, pero parece que no hay palabra clave para esto en Lua. "Require" y "dofile" observan los archivos en tiempo de ejecución, por lo que el bytecode resultante después de ejecutar "lua -b ..." no incluirá el código de esos archivos.

Y tampoco hay forma de combinar archivos de códigos de bytes, ¿verdad? Quiero decir que, al crear un archivo de código de bytes, el comando "requerir" agregaría el código de todos esos archivos en un solo archivo de código de bytes.

PS: La respuesta de Michal Kottman funciona para Lua, que es lo que solicité. Pensé que Lua y LuaJIT funcionarían de la misma manera. Ellos no. Para combinar varios archivos .lua al archivo de código de bytes uno LuaJIT, debe uno

  • uso "LuaJIT -b" (no parece funcionar)
  • compilar luac.c de Lua con las fuentes LuaJIT
  • emular luac.c con comandos lua (sin C API)?
+0

Aquí hay una respuesta que puede ser sobre el tema y útil. http://stackoverflow.com/questions/8936369/compile-lua-code-store-bytecode-then-load-and-execute-it –

Respuesta

11

Puede combinar varios archivos en un solo archivo usando luac. Cuando se ejecuta, todos los trozos de los archivos de origen se ejecutan en el orden en que se agregaron al archivo compilado:

$ echo "x=1"   > l1.lua 
$ echo "y=2"   > l2.lua 
$ echo "print(x, y)" > l3.lua 
$ luac -o run.luac l1.lua l2.lua l3.lua 
$ lua run.luac 
1 2 

Puede cargar este archivo en Lua de C usando luaL_loadfile, que coloca una función en la parte superior de la pila si se cargó con éxito. Luego puede ejecutar esta función usando lua_call para ejecutar todos los archivos compilados combinados.

Tenga en cuenta que puede incrustar el contenido del archivo compilado como una cadena en su proyecto, sin necesidad de guardarlo en un archivo externo.

Actualización para LuaJIT 2

A medida que han encontrado, se puede utilizar el Lua Compiler in Lua para obtener un archivo combinado que puede ser cargada como se señaló anteriormente.Esta es una versión simplificada, que da salida a la salida estándar:

-- http://lua-users.org/wiki/LuaCompilerInLua 
-- compile the input file(s) passed as arguments and output them combined to stdout 
local chunk = {} 
for _, file in ipairs(arg) do 
    chunk[#chunk + 1] = assert(loadfile(file)) 
end 
if #chunk == 1 then 
    chunk = chunk[1] 
else 
    -- combine multiple input files into a single chunk 
    for i, func in ipairs(chunk) do 
    chunk[i] = ("loadstring%q(...);"):format(string.dump(func)) 
    end 
    chunk = assert(loadstring(table.concat(chunk))) 
end 
io.write(string.dump(chunk)) 

Para el ejemplo anterior, puede utilizar la siguiente manera:

$ luajit combine.lua l1.lua l2.lua l3.lua > out.ljc 
$ luajit out.ljc 
1 2 
+0

¡Muchas gracias! Está bien que con el Lua original esto funcione. Estoy tratando de lograr lo mismo con luaJIT, usando "luajit -b" y varios archivos, pero no pude hacerlo allí. No hay luac.c en luaJIT y el formato de bytecode es diferente, así que me pregunto si esto también puede funcionar con luaJIT. Tal vez emulando a luac como aquí http://lua-users.org/wiki/LuaCompilerInLua. – John

+0

Según este http://lua-users.org/lists/lua-l/2005-12/msg00209.html luac.c también funcionará con luaJIT. – John

+0

Tenga en cuenta que es LuaJIT 1, que fue capaz de leer el bytecode de Lua estándar. El nuevo LuaJIT 2 tiene bytecode incompatible. –

0

loadstring es lo que estás buscando. Toma una cadena y carga si (después de compilarla en código de bytes si es necesario). Resulta en una función que puede ejecutarse para ejecutar el código contenido posteriormente.

Si aún necesita algo más general, echar un vistazo a load que le permite especificar una función de alimentar los trozos en.

Ambas funciones se pueden procesar tanto el código fuente de Lua y código compilado.

+0

Lo probé, veo cómo funciona, pero no cómo podría crear un solo trozo que contiene tanto el trozo de carga como el trozo cargado. ¿Puede dar un ejemplo? Estoy buscando algo así como (al trabajar con C) la creación de un único archivo de biblioteca a partir de archivos de objeto, por lo que no es necesario vincularlo con cada archivo de objeto. Solo así, pero para Lua, así que necesito incorporar solo un recurso en mi ejecutable. – John

+0

Ya veo. Tal vez este enlace pueda ayudarlo más: [Compilador Lua en Lua] (http://lua-users.org/wiki/LuaCompilerInLua) – jpjacobs

+0

Muchas gracias, esta es quizás la única forma con luaJIT, ya que no hay luac. – John

4

Otra alternativa es utilizar una herramienta como Mathew salvaje de squish para recoger todas sus fuentes Lua en un solo archivo .lua. Una buena característica de Squish es que admite una variedad de filtros para ayudar a que el paquete squished sea más pequeño que el total de los archivos fuente.

Después de aplicar squish, puede ejecutar el resultado a través de luac para obtener bytecode. Sin embargo, bytecode suele ser más grande que el código fuente, y casi seguramente más grande si se utiliza un filtro más agresivo (como gzip) en squish.

Si su archivo de bytecode se almacenó por separado del ejecutable (o peor, se transmite a través de la red), también plantearía problemas de seguridad relacionados con bytecode que no se aplican al código fuente de Lua. Sin embargo, el bytecode vinculado a una aplicación es mucho más difícil de subvertir ya que el bytecode dañino nunca será el resultado de ejecutar luac.

2

Después de probar luac, luajit y squish, encontré que todos ellos requieren que mantenga una lista de archivos para combinar. Eso es tedioso cuando se trabaja en un proyecto que contiene muchos archivos lua.

Así que escribí una pequeña herramienta para fusionar archivos lua mediante el análisis de require s

Aquí está: https://github.com/yi/node-lua-distiller

Esperamos que le ayuda.

Cuestiones relacionadas