Files
2026-10-11 22:32:13 +03:00

4.1 KiB
Raw Permalink Blame History

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()

Ищет эталонную библиотеку по порядку:

  1. <applicationDirPath>/zlib/libz.so.1 — запуск из дерева сборки;
  2. <applicationDirPath>/../lib/BiLauncher/libz.so.1 — установленный пакет, tar.gz и AppImage;
  3. LAUNCHER_ZLIB_INSTALL_DIR/libz.so.1 — путь, заданный при конфигурации CMake.

Второй вариант рассчитан на CMAKE_INSTALL_LIBDIR=lib. Поэтому CI на Ubuntu передаёт его явно, иначе библиотека легла бы в lib/x86_64-linux-gnu.

applyTo(env, &note)

  • zlib-ng в системе нет — подменять нечего, возвращает true, note пуст.
  • zlib-ng есть, эталон найден — дописывает его путь в начало LD_PRELOAD (чужое содержимое переменной сохраняется), возвращает true, в note пишет, что подставлено.
  • zlib-ng есть, эталона нет — возвращает false, в note пишет предупреждение.

ModLoaderInstaller пишет note в журнал установщика. Если applyTo() вернула false, а установщик упал с ошибкой контрольных сумм, к ошибке добавляется прямая подсказка про zlib-ng.


При создании этого документа использовался ИИ.