Ошибки новичков и дополнительные материалы
На этой странице
-
Ошибки новичков
- 1. Символическая ссылка .so попала в основной пакет
- 2. Забыли ldconfig — «error while loading shared libraries»
- 3. Не удалили .la-файлы
- 4. Неправильный glob-шаблон для .so-файлов
- 5. Забыли %{?_isa} в Requires подпакета -devel
- 6. Заголовочные файлы в неправильной директории
- 7. Забыли включить pkgconfig-файл в -devel
- 8. Не обновили %changelog
- Дополнительно: как узнать, какие файлы установились
- Дополнительно: статическая библиотека
- Итоги
Ошибки новичков
1. Символическая ссылка .so попала в основной пакет
Что произошло: в секции %files написали %{_libdir}/libyaml*.so*
(без точки после *), и ссылка libyaml.so попала в основной пакет.
Почему это плохо: пользователи, которым не нужна разработка, получают
лишний файл. А программы, зависящие от -devel, не смогут явно потребовать
его установку.
Как правильно:
# Основной пакет — только версионированные файлы:
%{_libdir}/libyaml*.so.*
# -devel — ссылка без версии:
%{_libdir}/libyaml.so
2. Забыли ldconfig — «error while loading shared libraries»
Симптом: пакет установлен, но при запуске программы:
./myprogram: error while loading shared libraries: libyaml-0.so.2:
cannot open shared object file: No such file or directory
Причина: не вызван ldconfig, кэш /etc/ld.so.cache не обновлён.
Решение: добавьте в SPEC:
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
Быстрая проверка на живой системе: запустите sudo ldconfig вручную.
Если после этого программа заработала — значит, проблема именно в скриптлетах.
3. Не удалили .la-файлы
Симптом: rpmlint предупреждает:
W: libyaml-devel.x86_64: la-file /usr/lib64/libyaml.la
Решение: добавьте в %install:
find %{buildroot} -name '*.la' -delete
4. Неправильный glob-шаблон для .so-файлов
Ошибка: написали %{_libdir}/libyaml.so.* (без -0 в имени).
Реальные файлы называются libyaml-0.so.2 и libyaml-0.so.2.0.9.
Шаблон libyaml.so.* ничего не захватит, и rpmbuild упадёт:
error: File not found: /home/user/rpmbuild/BUILDROOT/.../usr/lib64/libyaml.so.*
Решение: всегда проверяйте реальные имена файлов в BUILDROOT:
ls -la ~/rpmbuild/BUILDROOT/libyaml-*/usr/lib64/
И используйте шаблон, соответствующий реальным именам: libyaml*.so.*
5. Забыли %{?_isa} в Requires подпакета -devel
Что написали:
Requires: %{name} = %{version}-%{release}
Почему плохо: на мультилиб-системе (где стоят и 32-битные, и 64-битные пакеты) может установиться libyaml другой архитектуры. Разработчик получит несовпадение между заголовками (64-бит) и библиотекой (32-бит).
Как правильно:
Requires: %{name}%{?_isa} = %{version}-%{release}
6. Заголовочные файлы в неправильной директории
Ошибка: upstream устанавливает заголовки в /usr/include/libyaml/yaml.h,
а вы написали %{_includedir}/yaml.h.
Решение: всегда проверяйте, куда реально устанавливаются файлы:
find ~/rpmbuild/BUILDROOT/ -name '*.h'
7. Забыли включить pkgconfig-файл в -devel
Симптом: после установки -devel команда pkg-config --libs yaml-0.1
выдаёт ошибку:
Package yaml-0.1 was not found in the pkg-config search path.
Причина: файл yaml-0.1.pc не указан в секции %files devel.
Решение: добавьте:
%files devel
...
%{_libdir}/pkgconfig/yaml-0.1.pc
8. Не обновили %changelog
Каждое изменение в SPEC-файле должно сопровождаться записью в %changelog.
Без этого rpmlint выдаст предупреждение. Используйте rpmdev-bumpspec
для автоматического добавления записи.
Дополнительно: как узнать, какие файлы установились
После rpmbuild -bi (или полной сборки -ba) можно посмотреть
содержимое BUILDROOT:
find ~/rpmbuild/BUILDROOT/libyaml-*/ -type f -o -type l | sort
Ожидаемый вывод:
.../usr/include/yaml.h
.../usr/lib64/libyaml-0.so.2
.../usr/lib64/libyaml-0.so.2.0.9
.../usr/lib64/libyaml.so
.../usr/lib64/pkgconfig/yaml-0.1.pc
(Файл .la уже удалён, если вы добавили find ... -delete.)
Именно по этому списку вы заполняете секции %files и %files devel.
Дополнительно: статическая библиотека
Иногда upstream также собирает статическую библиотеку libyaml.a.
Если вы хотите её включить, создайте подпакет libyaml-static:
%package static
Summary: Static library for libyaml
Requires: %{name}-devel%{?_isa} = %{version}-%{release}
%description static
Static library for linking libyaml statically.
%files static
%{_libdir}/libyaml.a
Если статическая библиотека не нужна (чаще всего не нужна), удалите её:
find %{buildroot} -name '*.a' -delete
Итоги
В этом практикуме вы научились:
- Понимать структуру shared library: реальный файл, SONAME-ссылка и dev-ссылка
- Разделять пакет на runtime (основной) и development (-devel)
- Настраивать ldconfig для обновления кэша библиотек
- Работать с pkgconfig для удобной компиляции зависимых программ
- Удалять ненужные .la-файлы
- Проверять правильность сборки с помощью readelf, pkg-config и тестовой программы