Ответ 1
Я не знаю о "лучших", но вот практика, которая успешно сработала для меня, по крайней мере, в четырех проектах, три из которых были "настоящими", коммерческими. Хотя я обнаружил только конкретный случай для ZeroMQ, я считаю, что принципы носят общий характер и должны работать для любых родных библиотек. Большая часть кода может быть легко использована повторно, и она лицензируется в Eclipse, поэтому не стесняйтесь принимать ее, если хотите. У меня не было необходимости в более общей версии встроенной библиотеки, но я считаю, что ее можно легко извлечь.
Проблема, с которой я столкнулась со стандартными решениями (lein: native-path, JVM args и т.д.), заключалась в том, что я хотел иметь портативное решение для дистрибутива uberjar , которое не требует от пользователя установки чего-либо еще, поэтому такие инструкции, как "загрузить uberjar, установить libzmq-dev из вашего диспетчера пакетов, а затем запустить uberjar", не могут быть и речи.
Принцип довольно прост: я собираю собственные библиотеки в библиотечном банке для всех поддерживаемых платформ. Таким образом:
- Я, как автор библиотеки, контролирую, какие именно версии используются. Никаких сюрпризов нет.
- Включение библиотеки из другого проекта может быть сделано без какого-либо осознания того, что библиотека опирается на собственные библиотеки.
- Точно так же распределение uberjar, будь то от leiningen или maven, работает без проблем.
Я не полагаюсь ни на одну из стратегий связывания ОС, так как мне было трудно заставить их работать надежно. Так что я сделал, что я включил все необходимые родные библиотеки, которые не гарантированно присутствуют в запущенной системе в банке, а затем во время выполнения библиотека:
- динамически обнаруживает, на какой платформе он работает;
- извлекает собственные библиотеки из собственного архива в системный каталог temp, если он еще не существует (на основе SHA, это было необходимо, чтобы избежать накопления на платформах, которые неправильно очищают свои временные директории - это, Windows);
- "вручную" загружает собственные зависимости в правильном порядке, поэтому динамическая компоновка не пытается разрешить библиотеки на пути к хост-системе.
Есть, конечно, недостатки этого подхода:
- Поскольку процесс сборки для одного артефакта включает в себя три разных ОС (я поддерживаю Linux, Windows и OSX) и 2 архитектуры (i386 и x86_64), процесс сборки трудно автоматизировать и требует доступа к соответствующим машинам;
- В связи с тем, что конкретные версии родных библиотек объединены, пользователи библиотеки не могут их обновлять; в уязвимых средах это может быть неприемлемым;
- Как пользователь этой библиотеки, вы должны доверять мне, что вложенные собственные библиотеки действительно являются тем, что я утверждаю, что они есть, и действительно были построены в процессе, который я описываю в исходном коде, без каких-либо дополнительных вмешательств;
- Поскольку я практически ничего не знаю о связи динамических библиотек, могут быть другие проблемы с этим подходом, хотя они еще не укусили меня.