Почему я не могу установить несколько версий общей библиотеки?

10

Часто бывают случаи, когда определенная программа будет зависеть от версии библиотеки xy, а другая от xz, но, насколько мне известно, ни один менеджер пакетов не позволит мне установить xy и xz. Иногда они разрешают обе основные версии (такие как qt4 и qt5, которые могут быть установлены одновременно), но (по-видимому) никогда не второстепенные версии.

Почему это? Как, в чем ограничивающий фактор, который мешает этому? Я предполагаю, что должна быть веская причина не допустить эту, казалось бы, полезную функциональность. Например, нет ли поля, указывающего, какую версию загружать при загрузке общего объекта, и, следовательно, у Linux нет возможности узнать, как решить, какую из них загрузить? Или на самом деле нет причин для этого? Как и все минорные версии должны быть совместимы в любом случае или что-то?

Тайлер
источник

Ответы:

13

На самом деле, вы можете установить несколько версий общей библиотеки, если все сделано правильно.

Общие библиотеки обычно называются следующим образом:

lib<name>.so.<api-version>.<minor>

Далее есть символические ссылки на библиотеку под следующими именами:

lib<name>.so
lib<name>.so.<api-version>

Когда разработчик связывается с библиотекой для создания двоичного файла, это имя файла заканчивается тем, .soчто находит компоновщик. На самом деле может быть только одна из тех, которые установлены за один раз, <name>но это означает, что разработчик не может одновременно использовать несколько разных версий библиотеки. В случае с менеджерами пакетов эта .soсимволическая ссылка является частью отдельного -devпакета, который требуется установить только разработчикам.

Когда компоновщик находит файл с именем, оканчивающимся на .soи использует его, он ищет в этой библиотеке поле с именем soname . Soname сообщает компоновщику, какое имя файла нужно вставить в получившийся двоичный файл и, следовательно, какое имя файла будет найдено во время выполнения. Сонама должна быть установлена ​​в lib<name>.so.<api-version>.

Поэтому во время выполнения динамический компоновщик будет искать lib<name>.so.<api-version>и использовать это.

Намерение таково:

  • <minor>Обновления не изменяют API библиотеки, и когда они <minor>поднимаются до более высокой версии, можно позволить всем двоичным файлам обновиться до новой версии. Поскольку все двоичные файлы ищут библиотеку под lib<name>.so.<api-version>именем, которое является символической ссылкой на последнюю установленную lib<name>.so.<api-version>.<minor>версию, они получают обновление.
  • <api-version>Обновления изменяют API библиотеки, и небезопасно позволять существующим двоичным приложениям использовать новую версию. В случае, если <api-version>изменяется, так как эти приложения ищут имя, lib<name>.so.<api-version>но с другим значением для <api-version>, они не получат новую версию.

Менеджеры пакетов часто не упаковывают более одной версии одной и той же библиотеки в одну и ту же версию дистрибутива, потому что весь дистрибутив, включая все двоичные файлы, использующие библиотеку, обычно компилируется для использования согласованной версии каждой библиотеки до того, как дистрибутив будет выпущенный. Убедиться, что все согласовано и что все в дистрибутиве совместимо со всем остальным, является большой частью рабочей нагрузки для дистрибьюторов.

Но вы можете легко получить несколько версий библиотеки, если вы обновили систему с одной версии дистрибутива на другую, и у вас все еще есть более старые пакеты, требующие более старых версий библиотеки. Пример:

  • libmysqlclient16 из более раннего Debian, содержит libmysqlclient.so.16.0.0и символическую ссылку libmysqlclient.so.16.
  • libmysqlclient18 из текущего Debian, содержит libmysqlclient.so.18.0.0и символическую ссылку libmysqlclient.so.18.
Celada
источник
4

Эта функциональность не запрещена, просто она не очень распространена из-за того, как работает нумерация большинства библиотек, и из-за неудобств, связанных с изменениями имени пакета.

Если используется точечная схема номеров версий XYZ. «Микро» версия Z часто изменяется на исправлениях, «младший» номер Y изменяется на обратно совместимых изменениях, а «основной» номер версии X должен меняться на изменения API (а иногда и на основной дополнительный функционал).

Никогда не должно быть причины, по которой вы не хотите исправлять последние ошибки, и изменения, совместимые с предыдущими версиями, также не должны сломать ваше программное обеспечение.

Если библиотека разработана таким образом, вы всегда должны иметь возможность заменить XYZ на X. (Y + m). (Z + n). для любых заданных м и н. Т.е. вы всегда должны иметь возможность заменить свою библиотеку последней в той же серии старших номеров. И если разработчики библиотеки осторожны и следующий основной номер совместим (например, посредством объявления об устаревших вещах, но не удалять их), вы можете даже использовать следующий основной номер.

Для разработчиков пакетов это означает, что они могут использовать имя только с одним или даже без номера, чтобы предоставить вам последнюю версию, просто обновив пакет. Если они отправляют библиотеку в пакете , abc2то они должны пройти через обручи , чтобы переместить их собственное программное обеспечение , которое опиралось на abc2обновление до использования abc3, иногда с переходными пакетами. Удобнее не указывать основной номер версии в библиотеке, если это работает для большинства зависимых пакетов. Таким образом, даже если оба abc2и abc3должны быть доступны в какой-то момент, доступный в дистрибутиве, abc3часто вызывается abc(точно так же, как abc2был вызван, когда еще не abc3было), и как только пакеты не зависят от abc2дистрибутива, становится возможным отброситьabc2 в целом.

Схема нумерации не соблюдается единообразно, но я могу только представить, что с появлением в Интернете информации о том, как использовать такую ​​схему, и давлением со стороны пользователей библиотеки (включая разработчиков дистрибутивов), чтобы сделать понятными такие важные вещи, как обратная совместимость, без необходимость прочитать файл CHANGES, включенный в библиотеку, способствовала тому, что это стало более распространенным явлением.

Один встречный пример, но не библиотеки - это Python Intpreter, который не совместим с общими объектами и форматом выбора при незначительном изменении числа. Поэтому вы увидите пакеты для python (последний в серии 2.7) и python3 (последний в настоящее время в серии python3.4), а также явные пакеты для python 2.6 (не менее распространенные), а также python 3.3.

Энтон
источник