Зависимости: BuildRequires и Requires
Зависимости для сборки и работы, автоматическое определение, Provides/Conflicts/Obsoletes.
На этой странице
- Типы зависимостей
- Формы указания зависимостей
- Автоматические зависимости
- Provides — что предоставляет пакет
- Conflicts — конфликтующие пакеты
- Obsoletes — замена устаревшего пакета
- Зависимости подпакетов
- Слабые зависимости
- Зависимости времени выполнения скриптов
- Типичные ошибки
- Отладка зависимостей
- Проверьте понимание
Правильное указание зависимостей — одна из главных задач сборщика. Пакет должен работать «из коробки» и собираться в чистом окружении.
Типы зависимостей
BuildRequires — для сборки
Пакеты, необходимые во время сборки. Устанавливаются в сборочное окружение.
BuildRequires: gcc
BuildRequires: make
BuildRequires: cmake
BuildRequires: pkgconfig(libcurl)
BuildRequires: python3-devel
Requires — для работы
Пакеты, необходимые для работы установленной программы.
Requires: python3
Requires: libcurl
Requires: %{name}-data = %{version}-%{release}
Формы указания зависимостей
По имени пакета
BuildRequires: openssl-devel
Requires: openssl-libs
Через pkgconfig (рекомендуется для библиотек)
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(libcurl)
BuildRequires: pkgconfig(gtk4)
Преимущества:
- Не зависит от конкретного имени пакета
- Работает, даже если библиотека переехала в другой пакет
Как узнать pkgconfig-имя:
pkg-config --list-all | grep ssl
# openssl OpenSSL - OpenSSL cryptographic library
Через виртуальные provides
# Любой пакет, предоставляющий /usr/bin/python3
Requires: /usr/bin/python3
# Любой MTA
Requires: /usr/sbin/sendmail
# Perl-модуль
BuildRequires: perl(File::Copy)
# Python-модуль
BuildRequires: python3dist(requests)
С указанием версии
# Точная версия
Requires: libfoo = 1.0
# Минимальная версия
Requires: libfoo >= 1.0
# Диапазон
Requires: libfoo >= 1.0, libfoo < 2.0
# Строгая привязка подпакетов
Requires: %{name}-libs = %{version}-%{release}
Операторы сравнения:
=— точно равно<,>— меньше/больше<=,>=— меньше-равно/больше-равно
Автоматические зависимости
RPM автоматически определяет многие зависимости:
Разделяемые библиотеки
# Что программа требует
ldd /usr/bin/htop
# libncursesw.so.6 => /lib64/libncursesw.so.6
# RPM преобразует в
Requires: libncursesw.so.6()(64bit)
Интерпретаторы скриптов
#!/usr/bin/python3
# RPM автоматически добавит
Requires: /usr/bin/python3
Perl/Python модули
import requests
# RPM добавит
Requires: python3dist(requests)
Отключение автозависимостей
Иногда нужно отключить автоматику:
# Полное отключение
AutoReq: no
AutoProv: no
# Фильтрация конкретных зависимостей
%global __requires_exclude ^libprivate\\.so.*$
%global __provides_exclude_from ^%{_libdir}/%{name}/plugins/.*$
Provides — что предоставляет пакет
Provides: webclient
Provides: bundled(libfoo) = 1.2.3
Автоматические provides:
- Имя пакета и версия
- Разделяемые библиотеки (
.so) - Perl/Python модули
Явные provides нужны для:
- Виртуальных возможностей (
Provides: httpd) - Bundled-библиотек (
Provides: bundled(libfoo) = 1.2.3) - Совместимости (
Provides: old-name)
Conflicts — конфликтующие пакеты
Пакеты, которые нельзя установить одновременно:
# Конфликт с конкретным пакетом
Conflicts: otherpkg
# Конфликт со старой версией
Conflicts: libfoo < 2.0
Используйте осторожно — конфликты усложняют жизнь пользователям.
Obsoletes — замена устаревшего пакета
Когда пакет заменяет другой (переименование, слияние):
# Заменяем старый пакет
Obsoletes: old-package < 2.0
Provides: old-package = %{version}-%{release}
При установке new-package пакетный менеджер автоматически удалит old-package.
Важно:
- Obsoletes должен иметь версию (
< X.Y) - Без версии пакет будет «obsolete» навсегда
- Добавьте
Providesдля совместимости зависимостей
Зависимости подпакетов
Строгая привязка
%package libs
Summary: Libraries for %{name}
%package devel
Summary: Development files for %{name}
Requires: %{name}-libs = %{version}-%{release}
%{version}-%{release} гарантирует, что установятся одинаковые версии.
Рекомендации и предложения
# Рекомендуется, но не обязательно (dnf установит по умолчанию)
Recommends: %{name}-plugins
# Предлагается (dnf покажет, но не установит)
Suggests: %{name}-docs
# Дополняет другой пакет (устанавливается, если тот есть)
Supplements: (python3 and %{name})
# Улучшает другой пакет
Enhances: vim
Слабые зависимости
Recommends
Пакет будет установлен по умолчанию, но пользователь может отказаться:
Recommends: bash-completion
Suggests
Пакет будет показан как предложение:
Suggests: documentation
Supplements
Пакет будет установлен, если установлен другой:
# Установить langpack, если установлены firefox и langpacks-ru
Supplements: (firefox and langpacks-ru)
Зависимости времени выполнения скриптов
Requires(pre), Requires(post), …
Зависимости для скриптлетов:
Requires(pre): shadow-utils # Для создания пользователя
Requires(post): systemd # Для systemctl daemon-reload
Requires(preun): systemd
Requires(postun): systemd
OrderWithRequires
Управление порядком транзакции без жёсткой зависимости:
OrderWithRequires: otherpkg
Типичные ошибки
Недостающий BuildRequires
Симптом: Сборка работает локально, падает на ABF.
error: Package 'libfoo-devel' not found
Причина: Локально пакет уже установлен, в чистом окружении — нет.
Решение: Собирать в mock или внимательно смотреть логи configure/cmake.
Избыточные Requires
# Неправильно — уже подтягивается автоматически
Requires: glibc
Requires: libstdc++
# Правильно — только то, что RPM не найдёт сам
Requires: python3-requests
Отсутствие версии в Obsoletes
# Неправильно — obsolete навсегда
Obsoletes: old-package
# Правильно
Obsoletes: old-package < 2.0
Нестрогая привязка подпакетов
# Неправильно — может установиться libs от другой версии
Requires: %{name}-libs
# Правильно
Requires: %{name}-libs = %{version}-%{release}
Отладка зависимостей
Посмотреть зависимости пакета
# Requires собранного пакета
rpm -qp --requires package.rpm
# Provides
rpm -qp --provides package.rpm
# BuildRequires из SRPM
rpm -qp --requires package.src.rpm
Найти, какой пакет предоставляет файл
dnf provides /usr/lib64/libssl.so.3
# openssl-libs-3.0.8-1.x86_64 : ...
Найти, какой пакет предоставляет pkgconfig
dnf provides 'pkgconfig(openssl)'
# openssl-devel-3.0.8-1.x86_64 : ...
Проверить автоматические зависимости
# Что RPM найдёт автоматически
/usr/lib/rpm/find-requires < <(rpm -qlp package.rpm)
/usr/lib/rpm/find-provides < <(rpm -qlp package.rpm)
Проверьте понимание
- Чем отличается
BuildRequiresотRequires? - Почему лучше использовать
pkgconfig(...)вместо имени пакета? - Когда нужно использовать
ObsoletesиProvidesвместе? - Как RPM автоматически определяет зависимости от библиотек?
- Зачем нужна строгая привязка
= %{version}-%{release}для подпакетов?