Przy budowaniu pakietów system rpm kieruje się zawsze specjalnym, pojedynczym plikiem - skryptem opisującym proces budowy. Jest to tak zwany plik .spec

Pliki .spec mają własną składnię i gramatykę, która może być nieprzejrzysta. Jest to jednak ,,serce'' procesu budowania pakietów i trzeba przez to przebrnąć. Spec podzielony jest na sekcje. Kolejność sekcji zwykle jest obojętna i nie gra roli, chyba że nie jest obojętna i rolę gra ;) Sekcje mogą być banalnie proste lub diabelnie złożone, w zależności od autora pliku .spec, dystrybucji oraz samego pakietowanego programu. A poniżej zamieszczam przykładowy plik .spec (niespecjalnie ładny) wraz z oznaczeniem każdej z sekcji.

Przykładowy plik .spec Objaśnienie sekcji
Name:      procps
Version:   3.1.7
Release:   1
Summary:   System and process monitoring utilities
License:   LGPL, GPL, BSD-like
Group:     Applications/System
Packager:  <procps-feedback@lists.sf.net>
Source:    http://procps.sf.net/procps-%{version}.tar.gz
URL:       http://procps.sf.net/
BuildRoot: %{_tmppath}/procps-root

%description
The procps package contains a set of system utilities
which provide system information.  Procps includes ps,
free, sysctl, skill, snice, tload, top, uptime, vmstat,
w, and watch. You need some of these.
Preambuła podaje informacje o pakiecie. Składa się z szeregu jednolinijkowych pól, oraz dłuższego opisu rozpoczętego obowiązkową dyrektywą %description. Część pól jest fakultatywna (np. Packager:), inne, jak np. Name:, są obowiązkowe. Część tych pól (jak np. Packager: można zdefiniować np. w pliku ~/.rpmmacros - ale definicje w specu mają zwykle pierwszeństwo. Preambuła może (w nieco zmienionej postaci) wystąpić kilkukrotnie w pliku .spec, w połączeniu ze zwielokrotnionymi sekcjami %files - pozwala to na tworzenie z jednego speca kilku różnych pakietów (np. *-libs, *-static, *-devel itp.).
%prep
%setup -q
Sekcja rozpoczęta linią %prep służy przygotowaniu źródeł do konfiguracji i kompilacji. Zwykle używa się tu po prostu makra %setup, które weźmie pakiet ze źródłami i rozpakuje go do katalogu przeznaczonego na kompilację. A wszystkie te dane (plik ze źródłami, katalog docelowy) zawarte są albo w preambule, albo w plikach konfiguracyjnych RPM. W sekcji %prep dokonuje się także nakładania patchy na rozpakowane źródła (za pomocą makra %patch). Tutaj też często wywołuje się popularne ./configure i nawet istnieje do tego celu specjalne makro %configure (czego by się można spodziewać) - generalnie robi się tutaj wszystko to, co musi nastąpić przed samą kompilacją, przed wywołaniem ,,make''.
%build
make CC="gcc $RPM_OPT_FLAGS" LDFLAGS=-s
Sekcja %build odpowiada za kompilację pakietu. Zwykle wywołuje się tutaj tylko ,,make'' z odpowiednimi w danej sytuacji parametrami. Oprócz makr można w plikach .spec posługiwać się zwykłymi poleceniami shella (sekcje pliku .spec są parsowane trochę jak skrypty shellowe), tak że można umieszczać tutaj polecenia tak, jakby się je wpisywało w linii poleceń. Co widać w tym tutaj wywołaniu ,,make'', redefiniującym sobie własne ustawienia zmiennych $CC i $LDFLAGS.
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
Sekcja %install odpowiada za zainstalowanie skompilowanych plików. Jednak pliki nie są instalowane w /, ale w pustym katalogu $RPM_BUILD_ROOT (co zwykle oznacza jakiś katalog w obrębie /var/tmp. A więc ważne tutaj jest, by proces instalacji pozwolił się dać ,,przekierować'' do jakiegoś katalogu (zwanego zwyczajowo ,,fake root''). Większość plików Makefile pozwala na to za pośrednictwem zmiennej $DESTDIR, ale niektóre używają innych metod, lub nie posiadają takiej możliwości. W najgorszym wypadku trzeba będzie poprawić Makefile programu aby zbudować pakiet rpm.
%clean
rm -rf $RPM_BUILD_ROOT
Sekcja %clean nie jest wprawdzie obowiązkowa, ale jej zadaniem jest zwykle usunięcie zawartości ,,fake root''. Ja lubię dodawać tutaj od razu usuwanie rozpakowanych źródeł, ale to tylko kwestia moich przyzwyczajeń. Ot, takie udogodnienie które wysprząta poligon po budowie pakietu.
%post
# add libproc to the cache
/sbin/ldconfig
Sekcja %post jest jedną z czterech sekcji, które nie są wykonywane przy budowie pakietu, ale później, przy jego instalacji/usuwaniu. Istnieją sekcje %post, %pre, %postun, %preun które mogą wykonywać różne czynności odpowiednio po instalacji plików, przed instalacją plików oraz po odinstalowaniu i przed odinstalowaniem. Np. po instalacji pakietów zawierających biblioteki warto uruchomić ldconfig - ale trzeba to zrobić po tym, jak pliki zostaną umieszczone gdzie trzeba - dlatego też jest to robione w sekcji %post. Podobnie można by to robić po odinstalowaniu pakietu, w sekcji %postun. Sekcje %pre* też znajdują swoje zastosowanie, gdy trzeba wykonać jakąś ostatnią akcję przy odinstalowywaniu a jest do tego jeszcze potrzebny rzeczony pakiet (np. przywrócenie starego bootsektora przy odinstalowywaniu lilo)
%files
%defattr(0644,root,root,755)
%doc NEWS BUGS TODO COPYING COPYING.LIB README
%attr(555,root,root) /lib/libproc.so*
%attr(555,root,root) /bin/*
%attr(555,root,root) /sbin/*
%attr(555,root,root) /usr/bin/*
%attr(0644,root,root) /usr/share/man/man1/*
%attr(0644,root,root) /usr/share/man/man8/*
%files to druga obok preambuły sekcja która może wystąpić wielokrotnie. Ta sekcja odpowiada za oznaczenie plików które mają być umieszczone w wynikowym pakiecie, dodatkowo określane są domyślne prawa dostępu do plików i inne opcje które nie zostały jednak wykorzystane w tym przykładowym pliku :) Pliki które są tutaj ,,wybierane'' będą wzięte z ,,fake root'', więc muszą tam zostać umieszczone przez działania z sekcji %install

Struktura pliku .spec może wydawać się skomplikowana, a używane polecenia niezrozumiałe, ale na szczęście wszystkie spece są do siebie bardzo podobne, a zestaw poleceń logiczny i uporządkowany. Ważna jest w sumie jedynie pewna konstrukcja - najpierw, w preambule, opisuje się pakiet - nazwa, wersja, zależności, dane osoby pakietującej itp. Potem następuje sekcja %prep, czyli rozpakowanie, patchowanie, konfigurowanie źródeł. Potem sekcja %build, czyli kompilacja. Następna jest sekcja %install, która musi poukładać pliki wynikowe gdzieś w obrębie ,,fake root''. Następnie trzeba podać pliki które mają być włączone w pakiet i określić ich atrybuty, oraz ewentualnie doczepić do pakietu jakieś czynności które mają być wykonywane przy okazji instalowania/usuwania pakietu. I w zasadzie to są jedyne obowiązkowe ,,cechy'' speca. Reszta zależy całkowicie od autora specyfikacji - np. sekcja %install może do zainstalowania plików w ,,fake root'' użyć polecenia ,,make'', może też użyć owijki w postaci makra %makeinstall, można też kopiować pliki za pomocą polecenia ,,install'', makra %install, albo nawet zwykłego ,,cp''. Systemowi RPM jest to absolutnie obojętne, a wynikowy pakiet będzie identyczny niezależnie od użytych technik. Użytkownik ma wolną rękę i naprawdę nie ma ,,jedynej słusznej'' metody na napisanie specfile. Owszem, są zalecenia, przyjęte techniki itp., ale ma się tutaj taką samą dowolność, jak przy pisaniu skryptu shellowego - liczy się zadanie i końcowy efekt, szczególiki są zwykle mało istotne. Może te dodane słowa nadadzą rpm-owi bardziej ,,ludzką'' twarz.

Hmm, może polecę teraz ze szczegółowym opisem każdej z sekcji wraz z rozpiską dostępnych poleceń, tak aby mogło to potem służyć jako referencja przy pisaniu plików .spec.