Следуем политикам сборки пакетов с помощью 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. На момент написания данной статьи список переменных был таков:

Скрипты для ручного запуска

Пакет spec-helper также содержит несколько скриптов, которые не запускаются автоматически при сборке, но предназначены для самостоятельного использования мэйнтейнерами.

spec-cleaner

Скрипт Spec-cleaner предназначен для очистки spec-файлов от ненужных и устаревших конструкций. В частности, spec-cleaner выполняет следующие действия:

По умолчанию, spec-cleaner удаляет из spec-файлов секцию %changelog, поскольку в РОСЕ перечень изменений для пакета формируется на основе истории коммитов в Git на ABF, а большинство spec-файлов в секции %changelog содержат только очень старые записи. Если же вы не хотите, чтобы spec-cleaner удалял секцию %changelog, просто выставьте переменную окружения SPEC_LEAVE_CHANGELOG в 1.

rediff_patch

Rediff_patch пытается переделать имеющийся патч под новую версию тарболла с исходным кодом. Использовать его надо следующим образом:

  1. запускать rediff_patch необходимо в директории склонированного проекта — там, где лежит spec-файл и патчи. Spec-файл используется для того, чтобы определить — как именно применяется патч;
  2. в эту же директорию необходимо поместить новый тарболл с исходным кодом, для которого надо переделать патч;
  3. непосредственно запуск скрипта выглядит так:
 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 не справился — что ж, по крайней мере, мы немного сэкономим на распаковке архива и первой попытке применить патч.