Lua скомпилированные скрипты на Mac OS X - Intel против PPC - PullRequest
4 голосов
/ 26 июня 2009

Уже несколько лет использую Lua 5.0 в универсальном бинарном приложении Mac OS X. Скрипты Lua компилируются с использованием luac, а скомпилированные скрипты прилагаются к приложению. Они правильно работали в Tiger и Leopard, Intel или PPC.

Чтобы избежать проблем с библиотеками в то время, я просто добавил дерево Lua src в свой проект Xcode и скомпилировал как есть, без проблем.

Пришло время обновиться до более современной версии Lua, поэтому я заменил дерево исходников на 5.1.4. Я перестроил luac, используя make macosx (машина работает под управлением Leopard на Intel).

Нескомпилированные скрипты работают должным образом в Tiger и Leopard, Intel и PPC, как всегда.

Однако теперь скомпилированные сценарии не могут загружаться на машинах PPC.

Итак, я перестроил luac с флагом 'ansi' и перекомпилировал мои скрипты. Та же ошибка. Точно так же флаг сборки 'generic' не принес радости.

Может кто-нибудь, пожалуйста, посоветовать, что я могу делать дальше?

Ответы [ 6 ]

13 голосов
/ 26 июня 2009

Скомпилированные сценарии Lua - это в значительной степени необработанный байт-код, сбрасываемый после короткого заголовка. Заголовок документирует некоторые свойства платформы, используемой для компиляции байт-кода, но загрузчик только проверяет, что текущая платформа имеет те же свойства.

К сожалению, это создает проблемы при загрузке байт-кода, скомпилированного на другой платформе, даже если он скомпилирован той же версией Lua. Конечно, нельзя ожидать, что скрипты, скомпилированные разными версиями Lua, будут работать, и, поскольку номер версии Lua включен в заголовок байт-кода, попытка загрузить их перехватывается ядром.

Простой ответ - просто не компилировать скрипты. Если Lua компилирует сам скрипт, вам нужно только беспокоиться о возможных несовпадениях версий между ядрами Lua в различных сборках приложения, и с этим не сложно справиться.

На самом деле поддержка полной перекрестной совместимости для скомпилированного байт-кода - это не просто . В этом письме Майк Палл выявил следующие проблемы:

  1. Endianess: замена на выходе при необходимости.

  2. sizeof(size_t), влияет на огромные строковые константы: проверять переполнение, когда понижение.

  3. sizeof(int), влияет на MAXARG_Bx и MAXARG_sBx: проверка на переполнение при понижение.

  4. typeof(lua_Number): легко в C, но только когда хост и цель следуйте тому же стандарту FP; точность потеря при апгрейде (редкий случай); предупреждать о нецелых числах, когда понижение до int32.

Из всех обсуждений, которые я видел по этой проблеме в списке рассылки, я вижу два вероятных жизнеспособных подхода, предполагающих, что вы не желаете рассматривать просто доставку не скомпилированных скриптов Lua.

Первым было бы исправить порядок байтов при загрузке скомпилированных скриптов. Это оказывается проще, чем вы ожидаете, поскольку это можно сделать, заменив низкоуровневую функцию, которая читает файл сценария без перекомпиляции самого ядра. Фактически, это можно сделать даже на чистом Lua, предоставив собственную функцию chunk reader для lua_load () . Это должно работать до тех пор, пока единственной проблемой совместимости ваших платформ является порядок байтов.

Второе - это исправить само ядро, чтобы использовать общее представление для скомпилированных скриптов на всех платформах. Луис Энрике де Фигейредо описал это как возможное :

.... Я убежден, что лучший путь к порядок байтов или кросс-компиляция сторонние пары дампа / разгрузки. файлы 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 байта, "<esc>Lua"), коды версии и формата, байты флага для порядкового номера, размеры типов int, size_t, Instruction и lua_Number, а также флаг, указывающий, является ли lua_Number целочисленным типом.

Это позволяет отследить большинство различий платформ, но не пытается отследить все различия между платформами.

Я по-прежнему придерживаюсь приведенных выше рекомендаций: во-первых, исходники, которые можно компилировать на корабле; или, во-вторых, настройте ldump.c и lundump.c для хранения и загрузки общего формата, с дополнительным примечанием, что любой пользовательский формат должен переопределять байт LUAC_FORMAT заголовка, чтобы не путать с форматом стандартного байт-кода.

3 голосов
/ 27 июня 2009

Я бы прокомментировал сообщение 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

Стандартный отказ от ответственности: Я не утверждаю, что модификации идеальны или работают в любой ситуации. Если вы используете это и найдете что-нибудь сломанное, я буду рад услышать об этом, чтобы это можно было исправить.

3 голосов
/ 26 июня 2009

Вы можете использовать исправленный загрузчик байт-кода, который поддерживает различные порядковые номера. Смотрите это .

1 голос
/ 26 июня 2009

Байт-код Lua не является переносимым. Вам следует отправлять исходные скрипты вместе с вашим приложением.

Если размер загружаемого файла имеет значение, он, как правило, короче формы для байт-кода.

Если речь идет об интеллектуальной собственности, вы можете использовать обфускатор кода и помнить, что дизассемблирование байт-кода Lua совсем не сложно.

Если время загрузки является проблемой, вы можете предварительно скомпилировать исходные коды в вашем скрипте установки.

0 голосов
/ 28 июня 2009

У меня недостаточно репутации, чтобы комментировать, поэтому я должен вместо этого предоставить это в качестве ответа, даже если это неправильный ответ на заданный вопрос. К сожалению.

Здесь доступен обфускатор Луа:

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

Полное раскрытие: я автор обфускатора, и я знаю, что он не идеален. Обратная связь приветствуется и приветствуется (страница выше доступна на вышеуказанной странице).

0 голосов
/ 27 июня 2009

Я предполагаю, что вы скомпилировали скрипты на коробке Intel.

Скомпилированные скрипты просто непереносимы. Если вы действительно хотите предварительно скомпилировать сценарии, вам необходимо включить две версии каждого скомпилированного сценария: одну для Intel и одну для PPC. Ваше приложение должно будет опросить, какая программа запущена, и использовать правильный скомпилированный скрипт.

...