Как я могу убедить mkbundle включить MonoPosixHelper?

Я использую mkbundle и пытаюсь создать встроенную версию маленькой программы IdaTester, которая использует Isis2. Эта система в свою очередь использует функции Mono, которые зависят от MonoPosixHelper

Моя проблема в том, что mkbundle не распознает зависимость, и я получаю исполняемый файл, который все еще должен динамически связываться с ~/bin/lib/libMonoPosixHelper.so, вызывая проблемы, когда я перемещаю этот исполняемый файл в систему, где я не установить моно. По сути, в пакете отсутствует одна из вещей, с которой он должен быть статически связан.

Мой исполняемый файл работает, но только в том случае, если я запускаю его только на машинах с динамической библиотекой в ​​"правильном месте". Это противоречит цели встроенного исполняемого файла... Я надеялся, что смогу дать людям эту программу в качестве сервера, который они могли бы разместить в любом месте и запустить как двоичный файл, и, очевидно, если им нужно будет установить библиотеку, чтобы это работало сервер не совсем автономен!

Я вижу, как заставить mkbundle включать любые файлы dll, от которых зависит программа, но MonoPosixHelper не существует как dll; это библиотека только для Linux и существует только как общая библиотека. Кто-нибудь знает способ "заставить" пакет статически встраивать его?

Если это поможет, мой маленький скрипт компиляции выглядит следующим образом:

mcs -debug+ IdaTester.cs Isis.cs -r:System.dll -r:Microsoft.CSharp.dll -r:Mono.Posix.dll
mkbundle --static -o IdaTester IdaTester.exe --deps

Затем я запускаю IdaTester; это работает на платформах, где может быть найдена библиотека libMonoPosixHelper, но завершится с ошибкой во время выполнения при попытке динамически загрузить эту библиотеку, если она работает на платформе, где libMonoPosixHelper не была установлена ​​...

2 ответа

Нужно распространять libMonoPosixHelper.so с приложением и изменить карту DLL, чтобы сделать эту работу.

Предыстория проблемы - библиотека загружается во время выполнения

libMonoPosixHelper не является статически связанным, но выполняется поиск и загрузка в виде вызова P/Invoke, как в примере ниже:

    [DllImport ("MonoPosixHelper")]
    static extern int zipClose (ZipHandle handle, string globalComment);

То есть он запрашивается только во время выполнения, а не во время компиляции, и поэтому не может быть связан заранее.

Исправление - Распространение libMonoPosixHelper.so

Требуются четыре шага.

  1. Скопируйте libMonoPosixHelper в каталог, с которым вы будете распространять программу.
  2. Обновите файл конфигурации DllMap, чтобы избежать жесткого расположения.
  3. Вставить файл конфигурации с помощью mkbundle
  4. Добавьте путь с помощью libMonoPosixHelper.so к LD_LIBRARY_PATH на установочном компьютере.

Для выполнения каждого:

1. Скопируйте libMonoPosixHelper в каталог, с которым вы будете распространять программу.

libMonoPosixHelper обычно находится в папке lib, просто скопируйте его в папку, из которой вы будете делать архив.

cp $MONO_ROOT/lib/libMonoPosixHelper.so ~/MY_PROGRAM/

2. Обновите файл конфигурации DllMap, чтобы избежать жестко закодированного местоположения.

Это важный бит, чтобы избежать проблемы жестко закодированных путей. Нам нужно встроить файл конфигурации с mkbundle, в котором не указан путь. Для этого сначала найдите файл конфигурации mono, а также скопируйте его в локальный каталог.

cp $MONO_ROOT/etc/mono/config ~/MY_PROGRAM/config

Теперь нам нужно изменить этот файл, чтобы удалить конкретный путь для DLL, открыть его в вашем любимом редакторе и изменить пути, чтобы избежать конкретного префикса:

<dllmap dll="MonoPosixHelper" target="MACHINE_SPECIFIC/lib/libMonoPosixHelper.dylib" os="!windows" />

в

<dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.dylib" os="!windows" />

3. Вставьте файл конфигурации с помощью mkbundle.

Добавьте следующую опцию в команду mkbundle, чтобы встроить недавно отредактированный файл конфигурации:

   --config MY_PROGRAM/config

4. Добавьте путь с помощью libMonoPosixHelper.so к LD_LIBRARY_PATH на установочном компьютере.

Теперь вы можете заархивировать ваш исполняемый файл mkbundled, libMonoPosixHelper.so и любые другие файлы для распространения. Разархивированный и запущенный на машине, dlopen теперь будет искать libMonoPosixHelper.so, как и любой другой dll. Поэтому просто добавьте любой каталог, содержащий вашу распределенную версию libMonoPosixHelper, в их переменную среды LD_LIBRARY_PATH

Насколько я могу судить, лучший доступный для меня вариант - это создать библиотеку Mono без общего доступа, содержащую те же методы, которые в настоящее время находятся в MonoPosixHelper.so, либо предоставить копию MonoPosixHelper.so в качестве компонента, который будет установлен в той же папке, что и мой сервер. Ни то, ни другое не кажется идеальным: первое вынуждает меня "добраться до" дистрибутива Mono, что создает проблему более длительного обслуживания, а второе вынуждает меня переходить в более сложный режим дистрибуции и установки. Но, похоже, что когда вы создаете общую библиотеку, вы просто не можете статически связываться с этой версией библиотеки; загрузчик Linux просто не рассматривает такую ​​вещь как библиотеку так, как она обрабатывает больше стандартных библиотек.

Напротив, если я сгенерирую стандартную библиотеку из тех же файлов.o, загрузчик будет рад статически скомпоновать ее, а поскольку в конечном итоге mxbundle запускает cc и, следовательно, использует стандартный ld, эта опция будет работать для меня. Так что я думаю, что это ответ на мой вопрос.

Другие вопросы по тегам