Как лучше всего упаковывать в 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 ?