4.1 KiB
zlibreference.h
zlibreference.h, zlibreference.cpp
Обход одной конкретной проблемы на Linux: Forge и NeoForge не ставятся на системах, где вместо zlib стоит zlib-ng.
В чём проблема
Установщики Forge и NeoForge собирают часть jar прямо на машине пользователя и сверяют sha1
каждого собранного файла с эталоном из install_profile.json. Эталон посчитан на обычном zlib.
CachyOS, Fedora и некоторые другие дистрибутивы ставят вместо него zlib-ng в режиме совместимости.
Он сжимает корректно, но результат побайтово другой. Поэтому установка падает на любой версии игры
с сообщением Processor failed, invalid outputs.
Другая Java не помогает: сборки OpenJDK под Linux берут libz.so.1 из системы.
Что сделано
В репозитории лежат исходники zlib 1.3.1 (каталог zlib/). На Linux CMake собирает из них цель
launcher_zlib_reference (libz.so.1). В дереве сборки она лежит в <папка бинарника>/zlib/, при
установке — в <prefix>/lib/BiLauncher/. Сам лаунчер с ней не линкуется. Библиотека
подкладывается через LD_PRELOAD только процессу установщика, системный zlib-ng не трогается.
Исходники лежат в репозитории, а не скачиваются при сборке, по двум причинам: сборка не зависит от сети, и версия зафиксирована. От версии зависит побайтовый результат сжатия.
Функции
На Windows и macOS все три функции ничего не делают: systemIsZlibNg() возвращает false,
bundledPath() пустую строку, applyTo() — true.
systemIsZlibNg()
Открывает libz.so.1 через dlopen, то есть ту же библиотеку, которую загрузчик выдаст процессу
java, и смотрит, есть ли zlib-ng в строке zlibVersion(). Результат вычисляется один раз за
запуск.
bundledPath()
Ищет эталонную библиотеку по порядку:
<applicationDirPath>/zlib/libz.so.1— запуск из дерева сборки;<applicationDirPath>/../lib/BiLauncher/libz.so.1— установленный пакет, tar.gz и AppImage;LAUNCHER_ZLIB_INSTALL_DIR/libz.so.1— путь, заданный при конфигурации CMake.
Второй вариант рассчитан на CMAKE_INSTALL_LIBDIR=lib. Поэтому CI на Ubuntu передаёт его явно,
иначе библиотека легла бы в lib/x86_64-linux-gnu.
applyTo(env, ¬e)
- zlib-ng в системе нет — подменять нечего, возвращает
true,noteпуст. - zlib-ng есть, эталон найден — дописывает его путь в начало
LD_PRELOAD(чужое содержимое переменной сохраняется), возвращаетtrue, вnoteпишет, что подставлено. - zlib-ng есть, эталона нет — возвращает
false, вnoteпишет предупреждение.
ModLoaderInstaller пишет note в журнал установщика. Если applyTo()
вернула false, а установщик упал с ошибкой контрольных сумм, к ошибке добавляется прямая
подсказка про zlib-ng.
При создании этого документа использовался ИИ.