Spec-helper
Содержание
Как это работает
Spec-helper предоставляет набор скриптов, которые автоматически запускаются по время сборки пакетов и производят ряд действий, приводящих пакеты в соответствие с политиками сборки РОСЫ. Также в пакет spec-helper входят несколько скриптов, которые могут использовать мэйнтейнеры для автоматизации рутинных задач.
Обратите также внимание на файлы /usr/lib/rpm/brp-*. Сокращение "brp" происходит от "build root policies", "политик сборочного контейнера". Эти файлы определяют инструкции, которые будут выполнены в директории сборки сразу после завершения ее. Запуск скриптов BRP регулируется макросом %_os_install_post, который в РОСЕ определяется в файлах настройки внутри /usr/lib/rpm/.
Например, согласно политикам РОСЫ, справочные страницы man должны архивироваться с помощью xz. Чтобы избавить мэйнтейнера от необходимости самостоятельно вызывать команды сжатия и облегчит возможность изменения политики (например, смену программы архивации), мы используем специальный хук для rpm, который архивирует man-страницы автоматически в процессе сборки пакета и тем самым автоматически приводит пакет в соответствие политикам.
Скрипты, используемые spec-helper, размещаются в директории /usr/share/spec-helper. Запуск тех или иных скриптов регулируется в файле /etc/rpm/macros.d/spec-helper.macros.
Далее мы объясним, как можно добавить свой скрипт в spec-helper.
Создание скрипта
Для примера, напишем скрипт, запускающий pngcrush на каждом png-файле пакета.
Для начала, необходимо выбрать имя скрипта. Использовать "pngcrus" не следует, поскольку так называется непосредственно программа, которую будет вызывать наш скрипт, и вы не сможете гарантированно сказать, что вы запускаете - ваш скрипт или программу. Поэтому давайте назовем скрипт png_crush_rpm.
Что касается языка, на котором писать скрипт, то здесь у вас есть некоторая свобода выбора. У нас уже есть скрипты на perl, bash и python. В нашем примере мы будем использовать shell.
Можно использовать и другие интерпретируемые языки, но помните, что добавление скрипта на новом языке добавит еще одну зависимость пакету spec-helper. Использование компилируемого языка и создание программы сделает spec-helper зависящим от аппаратной платформы и может затруднить его перенос на другие архитектуры, чего нам бы очень хотелось избежать..
Что касается тела скрипта, то в нашем случае оно очень простое - мы должны применить pngcrush к каждому файлу, находящемуся внутри сборочно директории, имя которой содержится в переменной окружения $RPM_BUILD_ROOT. Обязательно убедитесь, что эта переменная выставлена и указывает на реально существующую директорию.
#!/bin/sh # проверим, выставлена ли переменная $RPM_BUILD_ROOT if [ -z $RPM_BUILD_ROOT ]; then exit 0 fi; # проверим, указывает ли она на реальную директорию [ -d $RPM_BUILD_ROOT ] || exit 0 # вызовем pngcrush для каждого png-файла for i in ind $RPM_BUILD_ROOT -type f -name '*.png' ; do pngcrush -q $i $i.new mv -f $i.new $i done;
Не забудьте сделать файл исполняемым! (chmod a+x).
Скрипт можно протестировать, вручную выставив переменную RPM_BUILD_ROOT, чтобы она указывала на некоторую директорию с png-файлами, и проверив, что при запуске скрипта действительно происходит обработка этих файлов.
Добавление скрипта в spec-helper
Теперь добавим наш скрипт в spec-helper.
Необходимо предусмотреть опцию и переменную окружения, отключающие запуск вашего конкретного скрипта. Например, можно добавить следующую опцию в соответствующие секции spec-helper:
echo "-png не запускать pngcrsuh на png-файлах." 1>&2
и ее обработку:
-png) DONT_PNG_CRUSH=1;;
в конструкцию switch/case.
Остается только добавить команду запуска вашего скрипта:
test -z "$DONT_PNG_CRUSH" && echo -n "Пережимаем png..." && png_crush_rpm && echo "done"
Теперь rpm будет автоматически запускать ваш скрипт при сборке пакетов.
Если вы полагаете, что написали скрипт, потенциально полезный многим мэйнтейнерам - на забудьте прислать его разработчикам РОСЫ для включения в штатные spec-helper.
Отключение запуска скриптов spec-helper в spec-файлах
Могут возникать ситуации, когда вы намеренно хотите нарушить одну из политик, автоматически претворяемых в жизнь посредством spec-helper. Например, вы хотите собрать пакет, оставив отладочную информацию непосредственно в его бинарных файлах - для облегчения отладки. Для этого вам необходимо выставить соответствующую переменную в секции %install:
%install %makeinstall .... # не запускать "strip" на исполнимых файлах export DONT_STRIP=1
Перечень всех доступных переменных можно найти в файле /etc/rpm/macros.d/spec-helper.macros. На момент написания данной статьи список переменных был таков:
- DONT_CLEANUP - не удалять резервные копии и прочие бесполезные файлы
- DONT_CLEAN_PERL - не удалять некоторые вспомогательные файлы для perl, не требуемые при работе программ (например, .packlist)
- DONT_COMPRESS - не архивировать справочные страницы man и info
- DONT_STRIP - не удалять отладочныую информацию из исполнимых баинарных файлов и разделяемых библиотек
- DONT_RELINK - не превращать символьные ссылки в относительные
- DONT_SYMLINK_LIBS - не создавать автоматически символьные ссылки для библиотек
- DONT_FIX_PAMD_CONFIGS - не заменять /lib на /lib64 в конфигурационных файлах pam для 64-битных пакетов
- DONT_REMOVE_INFO_DIR - не удалять /usr/share/info/dir/
- DONT_FIX_MO - не исправлять часто встречающиеся ошибки переводов
Скрипты для ручного запуска
Пакет spec-helper также содержит несколько скриптов, которые не запускаются автоматически при сборке, но предназначены для самостоятельного использования мэйнтейнерами.
spec-cleaner
Скрипт Spec-cleaner предназначен для очистки spec-файлов от ненужных и устаревших конструкций. В частности, spec-cleaner выполняет следующие действия:
- удаляет устаревшие и ненужные декларации — например, определение BuildRoot и Packager, зависимость от install-info, очистку buildroot и так далее;
- изменяет оформление использования макросов и переменных — переменные печатаются в фигурных скобках — %{const}, а макросы — без них — %{macro}. Такие изменения производятся только для макросов и переменных, определенных в самом rpm (а точнее, перечисленных непосредственно в скрипте spec-cleaner). Если вы сами определяете какие-то сущности, то их оформление скрипт изменять не будет;
- изменяет форматирование Summary — делает первую букву заглавной, удаляет точку в конце;
- удаляет явные определения переменных %{name}, %{version} и %{release};
- заменяет устаревшие макросы на современные аналоги;
- … и много других мелочей.
По умолчанию, spec-cleaner удаляет из spec-файлов секцию %changelog, поскольку в РОСЕ перечень изменений для пакета формируется на основе истории коммитов в Git на ABF, а большинство spec-файлов в секции %changelog содержат только очень старые записи. Если же вы не хотите, чтобы spec-cleaner удалял секцию %changelog, просто выставьте переменную окружения SPEC_LEAVE_CHANGELOG в 1.
rediff_patch
Rediff_patch пытается переделать имеющийся патч под новую версию тарболла с исходным кодом. Использовать его надо следующим образом:
- запускать rediff_patch необходимо в директории склонированного проекта — там, где лежит spec-файл и патчи. Spec-файл используется для того, чтобы определить — как именно применяется патч;
- в эту же директорию необходимо поместить новый тарболл с исходным кодом, для которого надо переделать патч;
- непосредственно запуск скрипта выглядит так:
rediff_patch <patch_ro_rediff> <tarball>
Если у вас в директории только один тарболл, то второй параметр можно опустить — rediff_patch возьмет единственный тарболл самостоятельно.
В ходе работы rediff_patch создаст директорию rediff_patch, распакует в нее новый тарболл и попытается применить к нему патч с параметрами, взятыми из spec-файла, добавив к ним опцию «--force» и используя значение fuzz по умолчанию (при сборке в rpmbuild используется «--fuzz=0»). Сейчас скрипт рассчитан на работу с тарболлами, при распаковке которых получается одна директория — обрабатывать tar-бомбы он откажется.
В случае, если все сложится успешно, рядом с вашим патчем вы обнаружите новый патч с суффиксом «.new», а остальные следы деятельности скрипта (директория rediff_patch со всем содержимым) будут уничтожены.
Если же что-то не заладится (например, патч применился не целиком), то вам останется директория rediff_patch с двумя поддиректориями — исходной и новой, к которой пробовали применить патч. Так что вы сможете вручную завершить работу, которую не получилось сделать автоматически, и уже самостоятельно сформировать новый патч с помощью стандартного diff -Naur.
Практика показывает, что большинство патчей все-таки требуют доработки, переделать их автоматически с использованием --force и более мягкого значения fuzz получается не очень часто. Однако даже если rediff_patch справился со всем самостоятельно, обязательно проверьте результирующий патч — ведь '--force' иногда может привести к нежелательному результату. А если rediff_patch не справился — что ж, по крайней мере, мы немного сэкономим на распаковке архива и первой попытке применить патч.