Назад | Перейти на главную страницу

RPM упаковывает конфликтующие библиотеки

Как лучше всего упаковывать в RPM что-то, что предоставляет библиотеку, которая по названию затеняет системную библиотеку?

Задний план: Для системы Linux с поддержкой RPM я упаковываю "автономное" приложение. foo который хочет жить в / opt и предоставлять как можно больше собственных зависимостей, чтобы не полагаться на версии, установленные в основной системе. (foo использует LD_LIBRARY_PATH, чтобы избежать системных библиотек.)

К сожалению, один из foo зависимости - это библиотека grunk, чья версия в точности совпадает с версией libgrunk.so требуется для основной системы. RPM автоматический Обеспечивает: Generation затем идентифицирует два RPM как предоставляющих эту библиотеку. (Это не совсем так - только системный пакет делает библиотеку доступной для любой программы, тогда как foo пакет делает его доступным только для foo.)

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

Пример:

grunk-libs-1.2-3.$arch.rpm              # System Library
  Files:
    %{_libdir}/libgrunk.so.1
    %{_libdir}/libgrunk.so.1.2
  Provides:
    libgrunk.so.1()(%{_arch})

foo-x.y.z-r.$arch.rpm                   # App
   Files:
     /opt/foo
     /opt/foo/bin/...
   Requires:
     libgrunk.so.1()(%{_arch})          # foo needs grunk, but wants its own instance

foo-grunklibs-1.2-1.$arch.rpm           # App Dependency
  Files:
    /opt/foo/libs/libgrunk.so.1
    /opt/foo/libs/libgrunk.so.1.2
  Provides:
    libgrunk.so.1()(%{_arch})           # <-- same as from system "grunk-libs"

На данный момент я отключил AutoReqProv, но я хочу иметь возможность использовать автоматические возможности RPM и создание зависимостей. Я хочу, чтобы RPM знал, что foo.rpm требует foo-grunklibs.rpm в силу последнего libgrunk.so.1, но также знайте, что той же библиотеки из основной системы rpm будет недостаточно.

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

Поразмыслив над этим некоторое время, я думаю, что более правильный подход - использовать «пространства имен» виртуальных ресурсов RPM. Например.:

Provides:  resource               # 'resource' is available to the whole system
Provides:  namespace(resource)    # 'resource' is specifically available only to "namespace"

RPM в конечном итоге выглядят так:

grunk-libs.rpm
  Provides:  libgrunk.so.1()(%{_arch})       # System library.  unchanged

foo.rpm
  Requires:  /bin/sh
  Requires:  libc.so.6()(%{_arch})
  Requires:  foo(libgrunk.so.1()(%{_arch}))  # Note special foo(...) namespace

foo-grunklibs.rpm
  Provides:  foo(libgrunk.so.1()(%{_arch}))  # Note special foo(...) namespace

Таким образом foo зависимость от специальной сборки libgrunk не может быть удовлетворен обычным grunk-libs RPM, но должна удовлетворяться сборкой этой библиотеки для foo.

Мое доказательство концепции выглядит так:

Name:     foo
...
Source99: find-namespaced-requires     # Here's the magic

%define    _use_internal_dependency_generator 0
%define    __find_requires %{SOURCE99} foo /bin/sh glibc

Где сценарий find-namespaced-требует оборачивает стандартный RPM % {_ rpmconfigdir} / find-requires и фильтрует его вывод. Его первый аргумент - это пространство имен ("foo(...)") для использования, а последующие аргументы - это зависимости или RPM, обеспечивающие зависимости, которые должны не быть в пространстве имен. В этом примере я хочу foo чтобы потребовать / bin / sh основной системы, а также обычные libc, libdl, libm и т. д. из glibc, но все остальные зависимости должны рассматриваться как специфические для foo.

Это можно было бы сделать немного чище и универсальнее, заключив большую часть вышеперечисленного в RPM времени сборки и сказав что-то вроде:

Name:          foo
BuildRequires: special-deps-macros

%define _namespace            foo      # defaults to %{name} ?
%define _generic_dependencies ...      # defaults to /bin/sh glibc libselinux ?