Shared Libs Policy Comments

Материал из ALT Linux Wiki

Пошаговая инструкция по переходу на Shared Libs Policy при смене soname.

В багзилле около пяти сотен багов посвящено файловым конфликтам, возникающим при обновлении библиотек (подсчёт неточный).

Обновление пошагово

Рассмотрим пошагово действия при обновлении на примере условного пакета libsoo, у которого в новой версии поменялся soname (имя библиотеки): libfoo.so.N -> libfoo.so.M

  1. Берем пакет libfoo из репозитория и обновляем его до новой версии.
  2. Меняем название бинарного пакета на libfooM.
    1. Для указания версии библиотеки добавляем в спек
      %define abiversion M
      и используем его в названии бинарного пакета:
      %package -n libpaper%abiversion
      и в секции %files:
      %_libdir/lib%name.so.%abiversion
      (последнее — для подстраховки от случайной смены soname при обновлении пакета).
    2. Добавляем в libpaperM
      Provides: libfoo = %version-%release
      (для совместимости с пакетами и пользователями, которые используют имя libfoo.
    3. Название пакета libfoo-devel оставляем неизменным
  3. Из-за того, что в libpaper был упакован файл /usr/bin/paperconf, который переехал в libpaperM, проставляем у libpaperM конфликт со старой версией:
    Conflicts: libfoo < 1.1.28-alt4 (ведь пакеты пересекаются по файлам)
  4. Делаем копию пакета libfoo из репозитория (то есть старого) под названием libfooN для сборки в нём старой версии
  5. Отключаем в пакете сборку всего, что может конфликтовать по файлам с пакетами новой версии, ведь у нас цель обеспечить возможность одновременной установки libpaperN и libpaperM.
    1. Для указания версии библиотеки добавляем в спек
      %define abiversion N
      и используем его в секции %files:
      %_libdir/lib%name.so.%abiversion
      (для подстраховки от случайной смены soname при обновлении пакета).
      и для бинарного пакета libfoo в
      Provides: libfoo%abiversion = %EVR
    2. Для libfooN выставляем
      Group: System/Legacy libraries


Дополнительные пункты для самопроверки

  1. При взгляде на исходные пакеты: добавляется новый пакет libfooN (из него собирается бинарный libfoo[1]).
  2. При взгляде на бинарные пакеты: добавляется новый пакет libfooM (из него собирается бинарный libfooM и libfoo-devel)
  3. Если библиотека пакуется под SharedLibsPolicy, то в пакете с библиотекой не должно быть ничего, что может потом в дальнейшем начать конфликтовать с файлами из нового пакета этой библиотеки. То есть содержимое /usr/bin должно оказаться в %name-tools, а %_datadir/%name/ — в %name-common (условно).
  4. Следует придерживаться того правила, чтобы пакет с библиотекой не менял имя, поскольку существует вероятность[2] того, что apt не сможет корректно обработать ситуацию, когда библиотека с конкретным soname переезжает в пакет с другим названием.
  5. При переходе на SharedLibsPolicy следует исправить все недостатки разбиения по подпакетам — смена soname удобный момент для этого.


Причины для применения Shared Libs Policy

  • Постепенная пересборка пакетов в репозитории при обновлении пакета.
    Чтобы не общаться с другим мантейнерами на предмет разрешения пересборки их пакетов в вашем большом задании, вы по сути просто собираете новую библиотеку в новый пакет, не нарушая целостность репозитория, а мантейнерам оставляете возможность чинить их пакеты, если они перестают собираться с новой версии библиотеки.
  • Необходимость одновременного существования разных версий библиотек в репозитории.
    Библиотека может быть очень известной (например, libpng) и сторонние бинарные программы могут быть привязаны к определённой версии библиотеки, не той,которая основная в репозитории.
  • При проблемах обновления с бранча на бранч возможность точечных обновлений чрезвычайно расширяется, т.к. старые библиотеки со старыми SONAME вытеснять никто не будет. Например, возможность обновить один новый пакет foo , зависящий от libname2 не затронет другой старый пакет bar, который зависит от старой версии libname1, которой уже нет в новом репозитории, но еще есть в системе. Если бы пакет со старой и новой версией библиотеки назывался libname, то по цепочке потянулась бы вся борода из других библиотек и пакетов, наткнувшись на какую-нибудь другую проблему обновления.

Причины для неприменения Shared Libs Policy

  • SharedLibsPolicy не применим, если пакет содержит множество других файлов, например с данными или плагинами, в пересекающихся каталогах (см. libsane в качестве примера). В этом случае мантейнеру придётся пересобрать в своём задании все зависящие пакеты.


Вынесение утилит в подпакет

Исходя из правила «в пакете с библиотекой не должно быть ничего, что может потом в дальнейшем начать конфликтовать с файлами из нового пакета этой библиотеки», утилиты и прочие неверсионированные файлы (т.е. скорее всего все, кроме собственно библиотеки) должны упаковываться в отдельный подпакет.

К примеру, от пакета libfooM ожидается собственно библиотека, а /usr/bin/foo должен быть упакован в отдельный подпакет, например libfoo-utils или просто foo, в зависимости от важности команды и их количества.

Такой пакет скорее всего будет иметь зависимость на libfoo, но пакет libfoo не должен зависеть от утилит (если библиотека вызывает утилиты, тогда разделение на подпакет не имеет смысла).

Польза от вынесения утилит в подпакет

  • Чтобы не было файлового конфликта у любых релизов libfoo, libfooN, libfooM.
  • Чтобы тот, кто устанавливал /usr/bin/foo, не потерял его в системе, когда /usr/bin/foo переедет из пакета libfoo в libfooM.
  • Минимизация зависимостей пакета с библиотекой. Если /usr/bin/bin это скрипт на python, то в итоге у пакета с библиотекой раздуются зависимости.

Благодарности

За появление этой статьи большая благодарность Глебу, начавшему обсуждение[3] и другим участникам:

  • Gleb Fotengauer-Malinovskiy
  • Mikhail Tergoev
  • Alexey V. Vissarionov
  • Sergey V Turchin
  • Anton Farygin

Ссылки

  1. libfoo, а не libfoo1, чтобы соблюсти условие о том, что библиотека не должна переезжать в пакет с другим названием.
  2. glebfm@: Я (как автор того изменения в apt, которое улучшило положение дел) всегда был уверен, что просто сильно уменьшилась вероятность. https://bugzilla.altlinux.org/show_bug.cgi?id=46837#c11
  3. https://lore.altlinux.org/devel/ZL7b3jkMiopSSuVX@glebfm.altlinux.org/