Хранение всего в одном блоке байт-кода lua?
Я включил lua вместе с блоком байт-кода в проект, написанный на C.
Теперь, когда я расширяю свою базу кода lua, добавляя файлы .lua, есть ли способ сохранить этот код в одном блоке байт-кода?
(Я знаю, как загружать несколько байт-кодов, но заставляя его загружать один кусок, а затем забывать о коде клея, просто будет удобно.)
Я попытался использовать текстовое включение, но, похоже, в Lua нет ключевого слова для этого.
"Требовать" и "делать файлы" смотрите файлы во время выполнения, поэтому полученный байт-код после запуска "lua -b..." не будет содержать код этих файлов.
И нет способа комбинировать файлы байт-кода, есть ли? Я имею в виду, что при создании файла байт-кода команда "require" добавит код всех этих файлов в один файл байт-кода.
PS: Михал Коттман отвечает за работу в Lua, и это то, о чем я просил. Я думал, что Lua и LuaJIT будут работать одинаково. Они этого не делают. Чтобы объединить несколько файлов .lua в один файл байт-кода LuaJIT, нужно
- использовать "LuaJIT -b" (похоже, не работает)
- скомпилировать Lua luac.c с источниками LuaJIT
- emulate luac.c с командами lua (без C API)?
Ответы
Ответ 1
Вы можете объединить несколько файлов в один файл, используя luac. При запуске все куски из исходных файлов выполняются в том порядке, в котором они были добавлены в скомпилированный файл:
$ 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
Вы можете загрузить этот файл в Lua из C с помощью luaL_loadfile
, который помещает функцию в верхнюю часть стека, если она будет загружена успешно. Затем вы можете просто запустить эту функцию, используя lua_call
, чтобы запустить все объединенные скомпилированные файлы.
Обратите внимание, что вы можете вставлять содержимое скомпилированного файла в строку в свой проект, не нужно хранить его во внешнем файле.
Обновление для LuaJIT 2
Как вы уже нашли, вы можете использовать компилятор Lua в Lua, чтобы получить объединенный файл, который можно загрузить, как было отмечено ранее. Это упрощенная версия, которая выводит на 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))
Для предыдущего образца вы можете использовать его следующим образом:
$ luajit combine.lua l1.lua l2.lua l3.lua > out.ljc
$ luajit out.ljc
1 2
Ответ 2
Другой альтернативой является использование инструмента, такого как Mathew Wild squish, чтобы собрать все источники Lua в один файл .lua
. Одна приятная особенность хлюпания заключается в том, что она поддерживает множество фильтров, чтобы сделать пакет с закругленным размером меньше, чем общее количество исходных файлов.
После применения squish вы можете запустить результат через luac
, чтобы получить байт-код. Однако байт-код часто больше исходного кода и почти наверняка больше, если в squish используется более агрессивный фильтр (например, gzip
).
Если ваш файл байт-кода хранился отдельно от исполняемого файла (или, что еще хуже, передавался по сети), я также вызывал проблемы безопасности, связанные с байт-кодом, которые не относятся к исходному коду Lua. Однако байт-код, связанный с приложением, гораздо труднее подорвать, поскольку вредный байт-код никогда не будет результатом запуска luac
.
Ответ 3
После попытки luac, luajit и squish, я нашел, что все они требуют, чтобы список файлов был объединен. Это утомительно, когда работа над проектом содержит много файлов lua.
Итак, я написал небольшой инструмент для объединения lua файлов путем анализа require
s
Вот он: https://github.com/yi/node-lua-distiller
Надеюсь, что это поможет.
Ответ 4
loadstring
- это то, что вы ищете. Он берет строку и загружает, если (после компиляции в байтовый код, если необходимо). Это приводит к функции, которая может быть выполнена для запуска содержащегося кода впоследствии.
Если вам все еще нужно что-то более общее, посмотрите load
, который позволяет вам указать функцию для подачи кусков.
Обе функции могут обрабатывать как исходный код Lua, так и скомпилированный байт-код.