libros - porque aprender lua
¿Manteniendo todo en un solo bloque de bytes de lua? (4)
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 código byte?
(Sé cómo cargar múltiples fragmentos de código de bytes. Pero hacer que cargue un solo trozo y luego olvidarse del código de pegamento sería muy cómodo.)
Intenté usar la inclusión textual, pero parece que no hay palabras clave para esto en Lua. "Require" y "dofile" miran 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ódigo 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.
PD : La respuesta de Michal Kottman funciona para Lua, que es lo que pedí. Pensé que Lua y LuaJIT funcionarían de la misma manera. Ellos no. Para combinar múltiples archivos .lua en un archivo de código de bytes LuaJIT,
- use "LuaJIT -b" (parece que no funciona)
- compila Luac.c de Lua con fuentes de LuaJIT
- emular luac.c con comandos lua (sin C API)?
Otra alternativa es usar una herramienta como el squish de Mathew Wild para recolectar todas tus fuentes de 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 usa un filtro más agresivo (como gzip
) en squish.
Si su archivo de código de bytes se almacenó por separado del ejecutable (o peor, se transmitió a través de la red), también plantearía inquietudes de seguridad relacionadas 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
.
Puede combinar varios archivos en un solo archivo usando luac . Cuando se ejecuta, todos los fragmentos 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 desde 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
Como ha encontrado, puede usar el compilador de Lua en Lua para obtener un archivo combinado que puede cargarse como se indicó anteriormente. Esta es una versión simplificada, que se envía a stdout:
-- 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 la muestra anterior, puede usarlo de la siguiente manera:
$ luajit combine.lua l1.lua l2.lua l3.lua > out.ljc
$ luajit out.ljc
1 2
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, eche un vistazo a la load
que le permite especificar una función para alimentar los fragmentos.
Ambas funciones pueden procesar tanto el código fuente de Lua como el código de bytes compilado.
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
Aquí está: https://github.com/yi/node-lua-distiller
Espero que sea útil.