Product SiteDocumentation Site

Глава 3. Пакеты с внешними зависимостями

3.1. Явная сборка внутри hasher
3.2. Сборка с помощью make, tarball
3.3. Hasher: работа с существующим пакетом
3.4. Решение конфликта именования
3.4.1. Ручная настройка
3.4.2. Автоматическая настройка
На примере библиотеки NCurses разберём сборку пакета из исходным файлов. В отличие от примера, состоящего из уже исполняемого файла, в этом случае необходимо будет провести сборку с использованием сторонней библиотеки.

3.1. Явная сборка внутри hasher

Соберём пакет из одного исходного файла. Для начала загрузим необходимую для работы библиотеку. Для разработки используются специальные devel-версии пакетов с библиотеками. Как правило, devel-версии включают в себя всё, что не нужно в процессе эксплуатации: примеры, документацию в разных форматах, .h-файлы, профили для различных инструментов сборки, а также специально оформленную символьную ссылку на файл с библиотекой, установленный из основного пакета. По этой причине вместе с devel-пакетом ставится и основной:
@user:
[user@VM ~]$ hsh-install libncurses-devel
<13>Jul 11 02:07:34 rpmi: libncurses6-6.3.20220618-alt4 sisyphus+327286.4600.14.1 1711486705 installed
<13>Jul 11 02:07:34 rpmi: libtinfo-devel-6.3.20220618-alt4 sisyphus+327286.4600.14.1 1711486705 installed
<13>ul 11 02:07:34 rpmi: libncurses-devel-6.3.20220618-alt4 sisyphus+327286.4600.14.1 1711486705 installed
[user@VM ~]$
Рассмотрим ближе структуру devel-библиотеки:
@builder
[builder@localhost ~]$ rpm -ql libncurses-devel
  • конфигурационные файлы библиотеки:
    /usr/bin/ncurses6-config
    /usr/bin/ncurses6-config
    
  • заголовочные файлы:
    /usr/include/curses.h
    /usr/include/eti.h
    /usr/include/form.h
    /usr/include/menu.h
    /usr/include/ncurses
    /usr/include/ncurses.h
    /usr/include/ncurses/curses.h
    /usr/include/ncurses/eti.h
    /usr/include/ncurses/form.h
    /usr/include/ncurses/menu.h
    /usr/include/ncurses/ncurses.h
    /usr/include/ncurses/panel.h
    /usr/include/ncurses/tic.h
    /usr/include/ncurses/unctrl.h
    /usr/include/panel.h
    /usr/include/unctrl.h
    
  • специальные символические ссылки на файлы динамической библиотеки и файлы компоновки pkg-config:
    /usr/lib64/libcurses.so
    /usr/lib64/libform.so
    /usr/lib64/libmenu.so
    /usr/lib64/libncurses.so
    /usr/lib64/libpanel.so
    /usr/lib64/pkgconfig/form.pc
    /usr/lib64/pkgconfig/menu.pc
    /usr/lib64/pkgconfig/ncurses.pc
    /usr/lib64/pkgconfig/panel.pc
    
  • набор документации и man:
    /usr/share/doc/ncurses-6.3.20220618
    /usr/share/doc/ncurses-6.3.20220618/announce.html
    /usr/share/doc/ncurses-6.3.20220618/demo.cc
    /usr/share/doc/ncurses-6.3.20220618/hackguide.doc
    /usr/share/doc/ncurses-6.3.20220618/hackguide.html
    /usr/share/doc/ncurses-6.3.20220618/index.html
    /usr/share/doc/ncurses-6.3.20220618/ncurses-intro.doc
    /usr/share/doc/ncurses-6.3.20220618/ncurses-intro.html
    /usr/share/man/man1/ncurses5-config.1.xz
    /usr/share/man/man1/ncurses6-config.1.xz
    /usr/share/man/man1/ncurses5-config.1.xz
    /usr/share/man/man1/ncurses6-config.1.xz
    <...>
    /usr/share/man/man3/wvline_set.3x.xz
    [builder@localhost ~]$
    
Перейдём к сборке пакета. В качестве тестовой программы рассмотрим программу, которая считывает приходящие символы и выводит их вместе с ASCII-кодом:
@builder: RPM/SOURCES/pkg-ncurses-1.0.c
#include <curses.h>

int main(void) {
       WINDOW* win;
       WINDOW* frame;
       char c = 0;

       initscr();
       noecho();
       cbreak();

       move(4, 10);
       printw("window:");
       refresh();

       frame = newwin(LINES - 8, COLS - 18, 4, 9);
       box(frame, 0, 0);
       mvwaddstr(frame, 0, (int)((COLS - 25) / 2), "Рамка");
       wrefresh(frame);

       win = newwin(LINES - 10, COLS - 20, 5, 10);
       keypad(win, TRUE);
       scrollok(win, TRUE);

       while((c = wgetch(win)) != 27) {
               wprintw(win, "  %d: %s\n", c, keyname(c));
               wrefresh(win);
       }

       delwin(win);
       endwin();
       return 0;
}
Поскольку для сборки пакета появилась новая подзадача — компиляция исходников в исполняемые файлы, меняется и spec-файл. Для описания команд по сборке итоговых файлов пакета используется директива %build:
@builder: RPM/SPECS/pkg-ncurses.spec
Name: pkg-ncurses
Version: 1.0
Release: alt1

Summary: Test pkg with ncurses library

License: GPL-3.0-or-later
Group: Development/Other

Source: %name-%version.c
BuildRequires: libncurses-devel

%description
This is a small testing package with ncurses functionality

%build
gcc %SOURCE0 -lncurses -o %name

%install
install -D -pm 755 %name %buildroot%_bindir/%name

%files
%_bindir/*

%changelog
* Thu Jul 03 2025 UsamG1t <usamg1t@altlinux.org> 1.0-alt1
- InitialBuild
Сборка пакета проходит успешно, и наряду с обычным двоичным пакетом собирается пакет с debuginfo, хранящий в себе информацию, необходимую для отладки:
@builder
[builder@localhost ~]$ tree RPM
RPM
├── BUILD
├── RPMS
│ ├── noarch
│ └── x86_64
├── SOURCES
│ └── pkg-ncurses-1.0.c
├── SPECS
│ └── pkg-ncurses.spec
└── SRPMS

7 directories, 2 files
[builder@localhost ~]$

[builder@localhost ~]$ rpmbuild -ba RPM/SPECS/pkg-ncurses.spec
<...>
Wrote: /usr/src/RPM/SRPMS/pkg-ncurses-1.0-alt1.src.rpm (w2.lzdio)
Wrote: /usr/src/RPM/RPMS/x86_64/pkg-ncurses-1.0-alt1.x86_64.rpm (w2.lzdio)
Wrote: /usr/src/RPM/RPMS/x86_64/pkg-ncurses-debuginfo-1.0-alt1.x86_64.rpm (w2.lzdio)
[builder@localhost ~]$ tree -A RPM/
RPM/
├── BUILD
│   └── pkg-ncurses
├── RPMS
│   ├── noarch
│   └── x86_64
│       ├── pkg-ncurses-1.0-alt1.x86_64.rpm
│       └── pkg-ncurses-debuginfo-1.0-alt1.x86_64.rpm
├── SOURCES
│   └── pkg-ncurses-1.0.c
├── SPECS
│   └── pkg-ncurses.spec
└── SRPMS
   └── pkg-ncurses-1.0-alt1.src.rpm

8 directories, 6 files
[builder@localhost ~]$
Попробуем установить пакет в это же окружение:
@user
[user@VM ~]$ hsh-shell --rooter
@rooter
[root@localhost .in]# rpm -i /usr/src/RPM/RPMS/x86_64/pkg-ncurses-1.0-alt1.x86_64.rpm
<13>Jul 3 05:26:57 rpm: pkg-ncurses-1.0-alt1 1751520368 installed
[root@localhost .in]#
[root@localhost .in]# which pkg-ncurses
/usr/bin/pkg-ncurses
[root@localhost .in]# pkg-ncurses
        ┌────────────Рамка─────────────┐
        │  72: H                       │
        │  101: e                      │
        │  108: l                      │
        │  108: l                      │
        │  111: o                      │
        │  44: ,                       │
        │  32:                         │
        │  105: i                      │
        │  115: s                      │
        │  32:                         │
        │  105: i                      │
        │  116: t                      │
        │  32:                         │
        │  109: m                      │
        │  101: e                      │
        │  32:                         │
        │  121: y                      │
        │  111: o                      │
        │  117: u                      │
        │  32:                         │
        │  108: l                      │
        │  111: o                      │
        │  111: o                      │
        │  107: k                      │
        │  105: i                      │
        │  110: n                      │
        │  103: g                      │
        │  32:                         │
        │  102: f                      │
        │  111: o                      │
        │  114: r                      │
        │  63: ?                       │
        └──────────────────────────────┘
Во время разработки окружение hasher должно содержать сборочные зависимости. Для эксплуатации пакета достаточно установить только эксплуатационные. Эксплуатационные зависимости можно указывать явно, но в большинстве случаев они добавляются в .rpm-пакет автоматически в процессе сборки:
@builder
[builder@localhost ~]$ rpmbuild -ba RPM/SPECS/pkg-ncurses.spec
<...>
Finding Requires (using /usr/lib/rpm/find-requires)
Executing: /bin/sh -e /usr/src/tmp/rpm-tmp.BxgcRM
find-requires: running scripts (cpp,debuginfo,files,lib,pam,perl,pkgconfig,pkgconfiglib,python,python3,rpmlib,shebang,shell,static,symlinks,systemd-services)
Requires: /lib64/ld-linux-x86-64.so.2, libc.so.6(GLIBC_2.2.5)(64bit), libc.so.6(GLIBC_2.34)(64bit), libncurses.so.6()(64bit) >= set:njzUlMJGoZaFrOm1ipLX6ub3NlTS2FoKH5pxjl802, libtinfo.so.6()(64bit) >= set:liZK
bfJOyUPV1IqfEUb0, rtld(GNU_HASH)
Requires(rpmlib): rpmlib(SetVersions)
<...>
Wrote: /usr/src/RPM/SRPMS/pkg-ncurses-1.0-alt1.src.rpm (w2.lzdio)
Wrote: /usr/src/RPM/RPMS/x86_64/pkg-ncurses-1.0-alt1.x86_64.rpm (w2.lzdio)
Wrote: /usr/src/RPM/RPMS/x86_64/pkg-ncurses-debuginfo-1.0-alt1.x86_64.rpm (w2.lzdio)
[builder@localhost ~]$
Скопируем пакет из hasher и попробуем установить его в чистое окружение без предварительной установки Ncurses. Чтобы у @rooter была возможность обратиться к полученному пакету, необходимо будет перенести его в директорию общего доступа для всех трёх пользователей — специальную директорию .in:
@user
[user@VM ~]$ cp hasher/chroot/usr/src/RPM/RPMS/x86_64/pkg-ncurses-1.0-alt1.x86_64.rpm
[user@VM ~]$ hsh --init
<...>
[user@VM ~]$ cp pkg-ncurses-1.0-alt1.x86_64.rpm hasher/chroot/.in/
[user@VM ~]$ hsh-shell --rooter
Поскольку библиотека является не только сборочной, но и эсплуатационной зависимостью пакета, её отсутствие не позволяет установить пакет:
@rooter
[root@localhost .in]# rpm -i pkg-ncurses-1.0-alt1.x86_64.rpm
error: Failed dependencies:
       libncurses.so.6()(64bit) >= set:mi6NHG6gUJ4yHTS2FoKH5hxjh80KggmL6K9X2A2 is needed by pkg-ncurses-1.0-alt1.x86_64
[root@localhost .in]#
Для решения проблемы необходимо установить все недостающие зависимости (которые, вообще говоря, могут и сами потребовать каких-либо других зависимостей и т. д.). Также файлы, передаваемые в директорию .in в hasher, автоматически удаляются из неё при нарушении условий целостности сессии (одним из таких условий является установка пакетов в hasher), вследствие чего их необходимо вновь добавить.
При установке библиотеки для эксплуатации следует пользоваться не devel-версией, а обычной. В репозитории Sysiphus часто встречаются несколько версий библиотек: старые, для корректной работы некоторых устаревших пакетов, и обновлённые. Обновлённые библиотеки имеют формат именования lib<имя_библиотеки>#, где номер в конце обозначает версию библиотеки. Старые библиотеки не имеют нумерации. В devel-версиях формат именования всегда lib<имя_библиотеки>-devel, но ссылка в них указывает на обновлённую библиотеку. Поскольку мы работаем с обновлённой библиотекой, необходимо установить её:
@user
[user@VM ~]$ hsh-install libncurses6
<13>Jul 11 02:14:27 rpmi: libncurses6-6.3.20220618-alt4 sisyphus+327286.4600.14.1 1711486705 installed
[user@VM ~]$ cp pkg-ncurses-1.0-alt1.x86_64.rpm hasher/chroot/.in
[user@VM ~]$ hsh-shell --rooter
@rooter
[root@localhost .in]# rpm -i pkg-ncurses-1.0-alt1.x86_64.rpm
<13>Jul 11 02:14:41 rpm: pkg-ncurses-1.0-alt1 1752199720 installed

[root@localhost .in]# rpmquery --requires pkg-ncurses
/lib64/ld-linux-x86-64.so.2
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.34)(64bit)
libncurses.so.6()(64bit) >= set:mi6NHG6gUJ4yHTS2FoKH5hxjh80KggmL6K9X2A2
rpmlib(SetVersions)
libtinfo.so.6()(64bit) >= set:liZKbfJOyUPV1IqfEUb0
rtld(GNU_HASH)
rpmlib(PayloadIsLzma)
[root@localhost .in]#