# Menadżer Pakietów RedHat-a (RPM) - Jak To Zrobić

## Autor: Donnie Barnes
djb@redhat.com
V2.0, 8 Kwietnia 1997
Wersja polska: Jacek Pliszka pliszka@fuw.edu.pl

Niniejszy dokument jest tłumaczeniem RPM-HOWTO i w skrócie opisuje jak coś zrobić używając rpm-a czyli Menadżera Pakietów RedHat-a (RedHat Package Manager). Dokument ten został napisany w standardzie ISO-8859-2. Oryginał tłumaczenia tego dokumentu znajduje się pod adresem http://www.jtz.org.pl. http://www.jtz.org.pl a także na ftp://ftp.icm.edu.pl/pub/Linux/sunsite/docs/HOWTO/.

## 1. Wprowadzenie

Skrót RPM pochodzi od ang. Red Hat Package Manager co oznacza w wolnym tłumaczeniu menadżer pakietów RedHat-a. Jednak pomimo tego, że w nazwie znajduje się Red Hat, to w zamierzeniu jest on systemem otwartym, dostępnym dla każdego. Umożliwia on spakowanie zarówno kodu źródłowego jak i programów binarnych do zwartej postaci zawierającej dodatkowo informacje istotne przy zarządzaniu oprogramowaniem. Umożliwia to łatwą instalację, odświeżanie oraz usuwanie oprogramowania. Informacja o zainstalowanym oprogramowaniu jest łatwo dostępna jako że RPM tworzy bazę danych o wszystkich pakietach zainstalowanych w naszym systemie. Pozwala to na szybkie sprawdzenie czy dany pakiet jest zainstalowany, a jeśli tak to co zawiera, jaka jest jego wersja, jakie pliki zostały przez niego w systemie zainstalowane oraz jakich innych pakietów wymaga. Pozwala też sprawdzić do jakiego pakietu należy dany plik.

Przyp. tłum. rpm jest obecnie używany zarówno do plików w postaci źródłowej jak i binarnej. W oryginale autor odwołuję się głównie do tej pierwszej. Jednak ponieważ obecnie częściej używa się pakietów w postaci binarnej to pliki z których powstał rpm a które mają być zainstalowane również będę nazywał plikami źródłowymi zaś proces instalacji bądź kompilacji - instalacją.

Firma Red Hat Software zachęca inne firmy i grupy tworzące oprogramowanie do bliższego zapoznania się z RPM i wykorzystania go przy tworzeniu własnych pakietów. Będąc dość elastycznym i łatwym w użyciu, RPM pozwala budować nawet bardzo obszerne zbiory pakietów. Pomimo tego, że jest to system całkowicie otwarty i dostępny, jego autorzy chętnie wysłuchają informacji o błędach i ewentualnych poprawkach. (Jednak przed zgłoszeniem ``błędu'' należy, tak jak zawsze, najpierw sprawdzić czy ma się najnowszą stabilną wersję, przejrzeć dokumentację oraz przeszukać archiwa USENET i jeśli i tam nie będzie odpowiedzi - spytać na odpowiedniej grupie dyskusyjnej np. pl.comp.os.linux -przyp. tłum.) Używanie i rozpowszechnianie RPM jest wolne od opłat i regulowane Publiczną Licencją GNU - GPL (ang. GNU Public Licence).

Bardziej szczegółowa dokumentacja dotycząca RPM jest zawarta w książce Eda Bailey'a, Maximum RPM, która można ściągnąć bądź zakupić w www.redhat.com.

## 2. Do czego służy RPM?

Na początku warto powiedzieć co nieco o ``filozofii'' RPM. Celem jego projektantów było umożliwienie użycia pierwotnych kodów źródłowych. Zanim powstał RPM, jego autorzy używali RPP (przy czym podkreślają, że RPM nie nie jest na nim oparty ), w którym udostępniano poprawione kody źródłowe, konkretnie te, które były używane do instalacji. Teoretycznie mogłoby to wystarczyć, bo można było zainstalować pakiet źródłowy RPP i skompilować go (poleceniem `make`) bez większych problemów. Jednakże nie były to oryginalne źródła i trudno było na pierwszy rzut oka powiedzieć co w nich zostało zmienione. Niezbędnym było ściągnięcie również oryginalnych źródeł. RPM zaś zawiera oryginalne źródła wraz z poprawkami których dokonano. W opinii autorów rozwiązanie to jest znacznie lepsze. Dlaczego?

Z paru powodów. Po pierwsze, jeśli pojawi się nowa wersja programu to nie zaczynamy od zera. Niektóre poprawki, które były dobre dla poprzedniej wersji, mogą być właściwe, najwyżej po minimalnych zmianach i dla obecnej. By się o tym przekonać, wystarczy do nich zajrzeć. Poza tym wszystkie domyślne opcje potrzebne do instalacji są w ten sposób łatwo dostępne.

Poza tym RPM zaprojektowano tak, aby umożliwić sprawdzanie wielu istotnych informacji dotyczących zarówno pojedyńczego, konkretnego pakietu jak i ich zestawu bądź też wszystkich pakietów zainstalowanych w danym systemie. Przykładem takiej informacji jest lista pakietów, których dany pakiet wymaga wraz z numerami wersji. Możliwe jest również sprawdzenie z jakiego pakietu pochodzi konkretny plik oraz gdzie można znaleźć jego wersję źródłową. Pliki RPM są już wewnętrznie spakowane, ale sprawdzanie informacji dotyczących konkretnego pakietu jest proste i szybkie dzięki specjalnemu binarnemu nagłówkowi który zawiera praktycznie wszystkie niezbędne informacje o pakiecie.

Innym atutem RPM jest umiejętność weryfikacji pakietów. Jeśli boisz się, że skasowałeś jakiś ważny plik, to możesz to po prostu sprawdzić. RPM poinformuje Cię o wykrytych nieprawidłowościach. Jeśli zajdzie potrzeba, to możesz łatwo odnowić zainstalowany pakiet przy czym Twoje pliki konfiguracyjne zostaną zachowane. Oczywiście możesz też zainstalować je od nowa.

Autorzy chcą podziękować grupie ludzi od dystrybucji BOGUS za wiele ich idei i pomysłów które wykorzystano w RPM. Gdyż o ile RPM został napisany w całości przez Red Hat Software, to zasady jego działania są oparte na kodzie stworzonym przez BOGUS (PM oraz PMS).

## 3. Informacje ogólne

## 3.1 Skąd wziąć RPM?

Najprostszym sposobem jest instalacja Linux-a Red Hat. Jeśli ktoś nie chce tego robić to może używać RPM bez tego. W Polsce RPM jest dostępny np. pod adresem: ftp.icm.edu.pl - polskim mirrorze ftp.redhat.com.

## 3.2 Wymagania RPM

Podstawowym wymaganiem RPM-a jest cpio o numerze wersji 2.4.2 lub wyższym. Mimo że RPM jest pomyślany do pracy pod Linux-em to równie może być przeniesiony na inne systemy Unix. W rzeczywistości udało się go już uruchomić pod SunOS, Solaris, AIX, Irix, AmigaOS i wieloma innymi systemami. Jednak należy pamiętać, że pakiety binarne stworzone na różnych Unix-ach mogą nie być ze sobą zgodne.

Są to minimalne wymagania by zainstalować RPM-y. By tworzyć RPM-y z kodu źródłowego potrzebne jest również wszystko to co normalnie jest wymagane przy tworzeniu pakietu np. `gcc`, `make`, itd.

## 4. Używanie RPM

Najprostszym wykorzystaniem RPM jest instalacja nowego pakietu:

> `

>             rpm -i foobar-1.0-1.i386.rpm

> `

Równie proste jest jego odinstalowanie:

> `

>             rpm -e foobar

> `

Przykładem bardziej złożonego, ale bardzo użytecznego polecenia jest instalacja pakietów poprzez FTP. Jeśli jesteś podłączony do sieci i chcesz zainstalować nowy pakiet, to wszystko co musisz zrobić to podać nazwę pliku jako poprawny URL, np.:

> `

>             rpm -i ftp://ftp.pht.com/pub/linux/redhat/rh-2.0-beta/RPMS/foobar-1.0-1.i386.rpm

> `

Chciałbym podkreślić, że w tym przypadku RPM sprawdzi bądź zainstaluje pakiet poprzez FTP.

Były to w miarę proste polecenia, lecz rpm może być użyty na wiele więcej sposobów jak można się łatwo przekonać pisząc w linii komend

> `

>             rpm

> `

i naciskając Enter:

> `

>     RPM version 2.3.9
>     Copyright (C) 1997 - Red Hat Software
>     This may be freely redistributed under na warunkach
>      of the
>     GNU Public License

>     usage: rpm {--help}
>            rpm {--version}
>            rpm {--initdb}   [--dbpath <dir>]
>            rpm {--install -i} [-v] [--hash -h] [--percent] [--force] [--test]
>                             [--replacepkgs] [--replacefiles] [--root <dir>]
>                             [--excludedocs] [--includedocs] [--noscripts]
>                             [--rcfile <file>] [--ignorearch] [--dbpath <dir>]
>                             [--prefix <dir>] [--ignoreos] [--nodeps]
>                             [--ftpproxy <host>] [--ftpport <port>]
>                             file1.rpm ... fileN.rpm
>            rpm {--upgrade -U} [-v] [--hash -h] [--percent] [--force] [--test]
>                             [--oldpackage] [--root <dir>] [--noscripts]
>                             [--excludedocs] [--includedocs] [--rcfile <file>]
>                             [--ignorearch]  [--dbpath <dir>] [--prefix <dir>]
>                             [--ftpproxy <host>] [--ftpport <port>]
>                             [--ignoreos] [--nodeps] file1.rpm ... fileN.rpm
>            rpm {--query -q} [-afpg] [-i] [-l] [-s] [-d] [-c] [-v] [-R]
>                             [--scripts] [--root <dir>] [--rcfile <file>]
>                             [--whatprovides] [--whatrequires] [--requires]
>                             [--ftpuseport] [--ftpproxy <host>] [--ftpport <port>]
>                             [--provides] [--dump] [--dbpath <dir>] [targets]
>            rpm {--verify -V -y} [-afpg] [--root <dir>] [--rcfile <file>]
>                             [--dbpath <dir>] [--nodeps] [--nofiles] [--noscripts]
>                             [--nomd5] [targets]
>            rpm {--setperms} [-afpg] [target]
>            rpm {--setugids} [-afpg] [target]
>            rpm {--erase -e} [--root <dir>] [--noscripts] [--rcfile <file>]
>                             [--dbpath <dir>] [--nodeps] [--allmatches]
>                             package1 ... packageN
>            rpm {-b|t}[plciba] [-v] [--short-circuit] [--clean] [--rcfile  <file>]
>                             [--sign] [--test] [--timecheck <s>] specfile
>            rpm {--rebuild} [--rcfile <file>] [-v] source1.rpm ... sourceN.rpm
>            rpm {--recompile} [--rcfile <file>] [-v] source1.rpm ... sourceN.rpm
>            rpm {--resign} [--rcfile <file>] package1 package2 ... packageN
>            rpm {--addsign} [--rcfile <file>] package1 package2 ... packageN
>            rpm {--checksig -K} [--nopgp] [--nomd5] [--rcfile <file>]
>                                package1 ... packageN
>            rpm {--rebuilddb} [--rcfile <file>] [--dbpath <dir>]
>            rpm {--querytags}

> `

Wszystkie te opcje są opisane w podręczniku systemowym "man" dotyczącym RPM.

## 5. A co tak naprawdę można zrobić z RPM?

RPM jest bardzo wygodnym narzędziem i jak można było się przekonać, ma sporo opcji. Najlepszą metodą zapoznania się z nimi są przykłady.

Pokazałem już najprostszą instalację i usuwanie pakietów, czas na trochę ciekawsze przykłady:

- W praktyce instalując pakiet chce się usunąc jego starą wersję (opcja -U od ang. upgrade). Często chcemy również widzieć postęp instalacji (-h od ang. hash) oraz dostać poszerzone komunikaty o błędach (-v od ang. verbose), tak więc praktycznie najczęściej pakiety instaluje się poprzez:

  > `

  >             rpm -Uhv foobar-1.0-1.i386.rpm

  > `

- Powiedzmy, że skasowałeś przypadkiem jakieś pliki, niestety, nie znasz nawet ich nazw. Jeśli więc chcesz zweryfikować cały system i sprawdzić czego może brakować, zrób tak:

  > `

  >     rpm -Va

  > `

  (od ang. Verify all)
- Powiedzmy, że natknąłeś się na plik, którego nie znasz. Żeby sprawdzić do jakiego pakietu należy, zrób:

  > `

  >     rpm -qf /usr/X11R6/bin/xjewel

  > `

  (od ang. query file). W wyniku otrzymasz nazwę pakietu:

  > `

  >     xjewel-1.6-1

  > `

- Natknąłeś się na jakiś plik RPM i chciałbyś sprawdzić co jest w środku. Zrób tak:

  > `

  >     rpm -qpi koules-1.2-2.i386.rpm

  > `

  Wyświetli Ci się coś takiego:

  > `

  >     Name        : koules                      Distribution: Red Hat Linux Colgate
  >     Version     : 1.2                               Vendor: Red Hat Software
  >     Release     : 2                             Build Date: Mon Sep 02 11:59:12 1996
  >     Install date: (none)                        Build Host: porky.redhat.com
  >     Group       : Games                         Source RPM: koules-1.2-2.src.rpm
  >     Size        : 614939
  >     Summary     : SVGAlib action game with multiplayer, network, and sound support
  >     Description :
  >     This arcade-style game is novel in conception and excellent in execution.
  >     No shooting, no blood, no guts, no gore.  The play is simple, but you
  >     still must develop skill to play.  This version uses SVGAlib to
  >     run on a graphics console.

  > `

  (od ang. query package info).
- A teraz chciałbyś sprawdzić jakie pliki wchodzą w skład tego pakietu:

  > `

  >     rpm -qpl koules-1.2-2.i386.rpm

  > `

  W wyniku otrzymasz ich listę:

  > `

  >     /usr/doc/koules
  >     /usr/doc/koules/ANNOUNCE
  >     /usr/doc/koules/BUGS
  >     /usr/doc/koules/COMPILE.OS2
  >     /usr/doc/koules/COPYING
  >     /usr/doc/koules/Card
  >     /usr/doc/koules/ChangeLog
  >     /usr/doc/koules/INSTALLATION
  >     /usr/doc/koules/Icon.xpm
  >     /usr/doc/koules/Icon2.xpm
  >     /usr/doc/koules/Koules.FAQ
  >     /usr/doc/koules/Koules.xpm
  >     /usr/doc/koules/README
  >     /usr/doc/koules/TODO
  >     /usr/games/koules
  >     /usr/games/koules.svga
  >     /usr/games/koules.tcl
  >     /usr/man/man6/koules.svga.6

  > `

  (od ang. query package list)
- Chcesz wyświetlić listę pakietów zainstalowanych w Twoim systemie? Nic prostszego:

  > `

  >     rpm -qa

  > `

  (od ang. query all).
- Chcesz sprawdzić czy pakiet jest kompletny, nie przekłamany i mam poprawny podpis PGP?

  > `

  >     rpm -K -vv pakiet.rpm

  > `

To było tylko parę przykładów, więcej znajdziesz np. w man-ie. Na pewno wpadniesz na ciekawsze w miarę jak będziesz lepiej poznawał RPM.

## 6. Tworzenie rpm-ów.

Tworzenie rpm-ów jest dość proste, szczególnie jeśli oprogramowanie które chcesz w nie włożyć poprawnie się instaluje.

Procedura tworzenia RPM-ów wygląda tak:

- Upewnij się, że plik `/etc/rpmrc` jest obecny i poprawnie skonfigurowany w Twoim systemie.
- Doprowadź to tego, że pliki źródłowe dla których tworzysz rpm poprawnie się instalują.
- Przygotuj listę poprawek jakich musiałeś dokonać by kod kompilował się poprawnie.
- Przygotuj plik specyfikujący (.spec) dla Twojego pakietu.
- Upewnij się, że wszystko jest na swoim miejscu.
- Zbuduj pakiet używając rpm.

Zazwyczaj RPM tworzy zarówno pakiety binarne jak i źródłowe.

## 6.1 Plik rpmrc

W chwili obecnej, jedyny sposób konfiguracji RPM-a jest dostępny poprzez plik `/etc/rpmrc`. Przykładowy plik wygląda tak:

> `

>     require_vendor: 1
>     distribution: Moja własna dystrybucja!
>     require_distribution: 1
>     topdir: /usr/src/me
>     vendor: Kubuśsoft
>     packager: Pakujący RPM w Kubuśsoft <pakiety@kubuśsoft.com.pl>

>     optflags: i386 -O2 -m486 -fno-strength-reduce
>     optflags: alpha -O2
>     optflags: sparc -O2

>     signature: pgp
>     pgp_name: Pakujący RPM w Kubuśsoft
>     pgp_path: /home/pakiety/.pgp

>     tmppath: /usr/tmp

> `

Wiersz `require_vendor` zmusza RPM-a do szukania wiersza z nazwą producenta pakietów (vendor). Ta może pochodzić z pliku `/etc/rpmrc` lub z nagłówka pliku .spec. By wyłączyć tę opcję, zmień liczbę na `0`. Analogicznie jest w przypadku wierszy `require_distribution` oraz `require_group`.

Następnym wiersz zawiera `distribution` i określa nazwę dystrybucji. Możesz ją zdefiniować tutaj, bądź później, w nagłówku pliku specyfikującego. Tworząc pakiet dla konkretnej dystrybucji warto zadbać by wiersz ten zawierał poprawną informację, nawet pomimo tego, że nie jest wymagany. Tyczy się to również wiersza `vendor` (producent), choć nazwa może być zupełnie dowolna (np. Joe's Software, Rock Music Emporium).

RPM pozwala również tworzyć pakiety dla różnych platform sprzętowych. Plik `rpmrc` może zawierać zmienną ``optflags'' wykorzystywaną przy building budowaniu tych elementów pakietu, które wymagają opcji zależnych od platformy. Dokładniejszy opis tej zmiennej pojawi się w jednym z następnych rodziałów.

Nie są to oczywiście wszystkie etykiety/makra. Jest ich więcej. By się im przyjrzeć spróbuj komendy:

> `

>     rpm --showrc

> `

która powinna wypisać wszystkie możliwe etykiety wraz z ich wartościami (o ile są ustawione).

## 6.2 Plik specyfikujący .spec

Niniejszy rozdział zawiera opis pliku specyfikującego dla pakietu. Plik taki są niezbędne by stworzyć pakiet. Zawiera on opis oprogramowania wraz z instrukcjami instalacyjnymi oraz listę wszystkich plików binarnych przez niego instalowanych.

Plik specyfikujący warto jest nazwać zgodnie z konwencją. Powinno to wyglądać mniej więcej tak: nazwa pakietu-kreska-numer wersji-kreska-numer modyfikacji-kropka-spec.

A tak wygląda przykładowy plik specyfikujący (eject-3.0-1.spec):

> `

>     Summary: ejects ejectable media and controls auto ejection
>     Name: eject
>     Version: 1.4
>     Release: 3
>     Copyright: GPL
>     Group: Utilities/System
>     Source: sunsite.unc.edu:/pub/Linux/utils/disk-management/eject-1.4.tar.gz
>     Patch: eject-1.4-make.patch
>     Patch1: eject-1.4-jaz.patch
>     %description
>     This program allows the user to eject media that is autoejecting like
>     CD-ROMs, Jaz and Zip drives, and floppy drives on SPARC machines.

>     %prep
>     %setup
>     %patch -p1
>     %patch1 -p1

>     %build
>     make RPM_OPT_FLAGS="$RPM_OPT_FLAGS"

>     %install
>     install -s -m 755 -o 0 -g 0 eject /usr/bin/eject
>     install -m 644 -o 0 -g 0 eject.1 /usr/man/man1

>     %files
>     %doc README COPYING ChangeLog

>     /usr/bin/eject
>     /usr/man/man1/eject.1

> `

## 6.3 Nagłówek

Nagłówek pliku .spec zawiera kilka standardowych pól które powinny być wypełnione. Oto znaczenie poszczególnych pól:

- `Summary:` Jest to jednowierszowy, skrócony opis pakietu.
- `Name:` To pole zawiera nazwę pliku rpm. Ściśle jest to string będący tą częścią nazwy pliku rpm która odpowiada nazwie pakietu.
- `Version:` To pole zawiera wersję pliku rpm. Ściśle jest to string będący tą częścią nazwy pliku rpm która odpowiada wersji pakietu.
- `Release:` To pole zawiera numer modyfikacji pliku rpm. Jest to liczba mówiąca z którą modyfikacją (podwersją) obecnej wersji pakietu mamy do czynienia (tzn. jeśli dokonany w pakiecie tylko minimalnych poprawek błędów to wypuszczamy pakiet w tej samej wersji ale z numerem modyfikacji większym o jeden).
- `Icon:` To pole zawiera nazwę pliku z ikoną przeznaczoną do wykorzystania przez narzędzia instalacyjne wyższego poziomu (np. ``glint'' RedHat-a). Plik ten powinien być zapisany w formacie GIF i znajdować się w katalogu SOURCES.
- `Source:` This wiersz zawiera nazwę pliku źródłowego z którego jest budowany dany rpm. Jest to pomocne w sytuacji gdy chce się kiedyś zajrzeć do odpowiednich kodów źródłowych lub sprawdzić czy nie ma ich nowszej wersji. Uwaga: Nazwa pliku w tym wierszu MUSI odpowiadać nazwie pliku obecnego w Twoim systemie. (tzn. nie zmieniaj nazw plików źródłowych po ich ściągnięciu). Można podać więcej niż jeden plik źródłowy pisząc w poniższy sposób:

  > `

  >     Source0: blah-0.tar.gz
  >     Source1: blah-1.tar.gz
  >     Source2: fooblah.tar.gz

  > `

  Te pliki powinny się znaleźć w katalogu `SOURCES`. (Struktura tego katalogu jest opisana w rozdziale "Katalogi z plikami źródłowymi".)
- `Patch:` To pole zawiera miejsce w którym będzie można znaleźć poprawki(patch) jeśli zainstnieje potrzeba ich ponownego ściągnięcia. Uwaga: Nazwa tego pliku musi odpowiadać nazwie pliku jaki jest użyty do naniesienia Twoich poprawek. Można też podać wiele plików z poprawkami analogicznie do wielu plików źródłowych:

  > `

  >     Patch0: blah-0.patch
  >     Patch1: blah-1.patch
  >     Patch2: fooblah.patch

  > `

  Te pliki powinny się znaleźć w katalogu `SOURCES`.
- `Copyright:` Ten wiersz opisuje do jakiej kategorii ze względu na prawo autorskie należy dane oprogramowanie. Najlepiej wykorzystać jedną z dobrze zdefiniowanych kategorii: GPL, BSD, MIT, public domain, distributable, lub commercial.
- `BuildRoot:` Ten wiersz pozwala zdefiniować główny katalog (``root'') dla tworzenia i instalacji pakietu. Można to wykorzystać np. do testowania instalacji pakietu zanim się go zainstaluje w docelowym miejscu.
- `Group:` Ten wiersz służy do tego, by programy instalacyjne wyższego poziomu (wspomniany ``glint'') wiedziały w jakim miejscu ich hierarchicznej struktury grup pakietów umieścić dany pakiet. W chwili obecnej drzewo grup pakietów wygląda mniej więcej tak:

  > `

  >     Applications
  >         Communications
  >         Editors
  >             Emacs
  >         Engineering
  >         Spreadsheets
  >         Databases
  >         Graphics
  >         Networking
  >         Mail
  >         Math
  >         News
  >         Publishing
  >             TeX
  >     Base
  >         Kernel
  >     Utilities
  >         Archiving
  >         Console
  >         File
  >         System
  >         Terminal
  >         Text
  >     Daemons
  >     Documentation
  >     X11
  >         XFree86
  >             Servers
  >         Applications
  >             Graphics
  >             Networking
  >         Games
  >             Strategy
  >             Video
  >         Amusements
  >         Utilities
  >         Libraries
  >         Window Managers
  >     Libraries
  >     Networking
  >         Admin
  >         Daemons
  >         News
  >         Utilities
  >     Development
  >         Debuggers
  >         Libraries
  >             Libc
  >         Languages
  >             Fortran
  >             Tcl
  >         Building
  >         Version Control
  >         Tools
  >     Shells
  >     Games

  > `

- `%description` Nie jest to element nagłówka w ścisłym tego słowa znaczeniu ale jego opis powinien się znaleźć wraz z opisem nagłówka. Dla każdego pakietu lub subpakietu potrzebne jest jedno takie pole zawierające przejrzysty i zrozumiały opis pakietu.

## 6.4 Sekcja Prep

Jest to druga część pliku specyfikującego. Używa się jej do przygotowania źródeł do kompilacji/instalacji. W niej powinny znajdować się wszystkie czynności niezbędne by nanieść poprawki do źródeł i doprowadzić je do stanu w którym będzie można wydać komendę `make`.

Jedną rzecz należy podkreślić: Każda z tych części jest tak naprawdę tylko miejscem do umieszczenia odpowiednich skryptów. Możesz po prostu napisać skrypt w `sh` a następnie umieścić go po znaczniku `%prep` by rozpakować i wprowadzić poprawki do swoich programów. By to ułatwić powstały specjalne makra.

Pierwszym z nich jest makro `%setup`. W swojej najprostszej formie (bez dodatkowych opcji w linii poleceń), rozpakowywuje ona źródła i zmienia bieżący katalog na katalog zawierający źródła. Poza tym ma jednak dodatkowe opcje:

- `-n name` ustawi nazwę roboczego katalogu na `name`. Domyślnie jest to `$NAZWA-$WERSJA`. Do innych możliwości należą `$NAZWA`, `${NAZWA}${WERSJA}`, czy jakakolwiek inna używana przez główny plik tar. (Proszę zauważyć, że zmienne ``$'' nie są faktycznymi zmiennymi dostępnymi wewnątrz pliku specyfikującego. W rzeczywistości są one tutaj użyte w miejsce przykładowej nazwy. W pakiecie należy użyć rzeczywistej nazwy i wersji, a nie zmiennej.)
- `-c` utworzy i wejdzie do wymienionego katalogu zanim zacznie się rozpakowywanie poprzez untar.
- `-b #` wykona untar (rozpakuje) Source# zanim wejdzie do katalogu roboczego (nie ma sensu łączenie tej opcji z `-c`, a więc się tego nie robi). Jest to przydatne w przypadku wielu plików źródłowych.
- `-a #` wykona untar (rozpakuje) Source# po wejściu do katalogu.
- `-T` Ta opcja zmienia domyślną procedurę rozpakowywania (untar) źródeł i wymaga `-b 0` lub `-a 0` by główny plik źródłowy został rozpakowany (untar). Komenda ta jest potrzebna gdy używany jest więcej niż jeden komplet plików źródłowych.
- `-D` Nie usuwaj katalogu przed rozpakowaniem. Jest ona przydatna tylko wtedy, gdy ma się więcej niż jedno makro konfiguracyjne. Powinna być używana wyłącznie w makrach konfiguracyjnych wyłącznie po wykonaniu pierwszego z nich (ale nigdy węwnątrz pierwszego z nich).

Następne dostępne makra znajdują się w makrze `%patch`. Makro te pomaga zautomatyzować proces nanoszenie poprawek do źródeł. Możliwe są liczne opcje opisane poniżej:

- `#` zastosuje Patch# jako plik z poprawkami.
- `-p #` podaje liczbę katalogów do odrzucenia z nazwy przed wykorzystaniem polecenia patch(1)
- `-P` Domyślnie stosowana jest `Patch` (lub `Patch0`). Ta flaga wyłącza to zachowanie a więc wymaga dodatkowo `0` by główne pliki źródłowe zostały rozpakowane. Opcja ta jest przydatna w drugim (bądź dalszym) makrze `%patch` które wymaga innego niż pierwsze makro numeru poprawki.
- Można też napisać `%patch#` zamiast : `%patch # -P`

To są wszystkie makra jakich potrzebujesz. Po ich poprawnym napisaniu można wykonać dowolne inne komendy konfiguracyjne poprzez stworzenie odpowiednich fragmentów skryptów w `sh`. Wszystko co zostanie umieszczone aż do makra `%build` (omawianego w następnym rozdziale) będzie wykonane przez `sh`. Przykłady powyżej mogą sugerować rzeczy jakie chciałbyś tam umieścić.

## 6.5 Sekcja Build

Dla tej sekcji nie ma jakichś specjalnych makr. Powinno się w niej umieszczać dowolne polecenia potrzebne do stworzenia pakietu po rozpakowaniu źródeł, naniesieniu poprawek i przejściu do katalogu roboczego. Jest to po prostu następny zbiór poleceń przekazany do `sh`, więc można tu używać dowolnych poprawnych poleceń `sh` (włącznie z komentarzami). Katalog roboczy na początku każdej z sekcji jest ustawiany na katalog główny z plikami źródłowymi, o czym trzeba pamiętać i w razie potrzeby przechodzić do odpowiednich podkatalogów.

## 6.6 Sekcja Install

Tu również nie ma jakichś specjalnych makr. Sekcja ta powinna zawierać listę poleceń potrzebnych do instalacji pakietu. Jeśli wykonujesz `make install` by zainstalować pakiet, umieść to tu. Możesz również nanieść poprawki do makefile'a zanim wykonasz `make install`. Jeśli nie to umieść tu sekwencję poleceń `sh` jakich potrzebujesz. Katalog roboczy, identycznie jak w poprzednim przypadku, jest ustawiany przed wykonaniem tych poleceń na główny katalog z plikami źródłowymi.

## 6.7 Opcjonalne sekcje pre i post dla sekcji Install/Uninstall

Możesz tu umieścić skrypty do wykonania przed i po instalacji/deinstalacji (tzn. sekcjami Install/Uninstall). Główny powód to np. potrzeba wykonania komendy `ldconfig` po instalacji bądź usuwaniu pakietów zawierających biblioteki dzielone. Makra są zdefiniowane jak poniżej:

- `%pre` makro z poleceniami wykonywanymi przed sekcją Install.
- `%post` makro z poleceniami wykonywanymi po sekcji Install.
- `%preun` makro z poleceniami wykonywanymi przed sekcją Uninstall.
- `%postun` makro z poleceniami wykonywanymi po sekcji Uninstall.

Sekcje te mogą zawierać dowolne poprawne polecenia `sh` ( nie potrzebujesz wstawiać `#!/bin/sh` na początku).

## 6.8 Sekcja Files

W sekcji tej musisz wypisać pliki jakie wchodzą w skład pakietu. RPM nie potrafi określić jakie pliki zostają zainstalowan na skutek np. `make install`. Tego się po prostu NIE DA rozsądnie zrobić. Owszem, była propozycja wykonywania polecenia `find` przed i po instalacji pakietu. Jednak w systemach wieloużytkownikowych nie jest to zbyt sensowne gdyż w tym samym czasie mogło powstać wiele innych plików nie mających najmniejszego związku z instalowanym pakietem.

W tej sekcji dostępne jest pare specjalnych makr. Są one opisane poniżej:

- `%doc` służy do zaznaczenia które pliki pakietu są jego dokumentacją. Dokumentacja ta zostanie umieszczona w katalogu: `/usr/doc/$NAZWA-$WERSJA-$MODYFIKACJA`. Można zarówno podać nazwy kilku plików w linii zawierającej to makro jak i podać te nazwy oddzielnie używając makra dla każdej z nich.
- `%config` służy do zaznaczenia plików konfiguracyjnych w obrębie pakietu. Chodzi tu o pliki typu: sendmail.cf, passwd, etc. W trakcie deinstalacji pliki te są usuwane o ile nie były zmieniane. Jeśli były, to ich nazwa zostaje zmieniona poprzez dodanie końcówki `.rpmsave`. Analogicznie jak dla plików z dokumentacją jedno makro może służyć do zdefiniowania kilku takich plików.
- `%dir` zaznacza dany katalog jako należący do pakietu. Domyślnie, jeśli pojawi się nazwa katalogu BEZ makra `%dir`, WSZYSTKO w tym katalogu jest włączane w liste plików i następnie instalowane jako część pakietu. To makro pozwala tego uniknąć.
- `%files -f <filename>` pozwala na włączenie listy plików znajdującej się w jakimś pliku w obrębie katalogu z plikami źródłowymi. Jest to wygodne gdy procedura instalacji buduje własną listę plików którą następnie można włączyć jedną komendą bez podawania nazw tych plików.

Największą trudnością w liście plików jest podawanie katalagów. Jeśli np. podasz przez pomyłkę `/usr/bin`, to Twój pakiet rpm będzie zawierał wszystkie pliki w katalogu `/usr/bin` w Twoim komputerze.

## 6.9 Tworzenie pakietu

### Katalogi z plikami źródłowymi

Jedną z podstawowych rzeczy jest poprawnie skonfigurowane katalogów w których RPM będzie budował pakiet. Robi się to poprzez plik `/etc/rpmrc`. Większość osób używa po prostu `/usr/src`.

Możliwe, że będziesz potrzebował utworzyć poniższe katalogi:

- `BUILD` jest katalogiem w którym RPM buduje pakiet. Próbne tworzenie pakietu możesz wykonać w jakimkolwiek katalogu który tu podasz.
- `SOURCES` jest katalogiem w którym powinieneś umieścić oryginalne pliki źródłowe i pliki z poprawkami. Jest to miejsce do którego RPM będzie zaglądał domyślnie.
- `SPECS` jest katalogiem w którym powinny się znaleźć wszystkie pliki specyfikujące (spec).
- `RPMS` RPM umieści tu binarme pliki RPM po ich zbudowaniu.
- `SRPMS` RPM umieści to pliki RPM z plikami źródłowymi.

### Próbne tworzenie pakietu

Pierwszą rzeczą do zroienia jest doprowadzenie plików źródłowych do takiego stanu by kompilowały i/lub instalowały się bez pomocy RPM-a. By to osiągnąć, rozpakuj źródła i zmień nazwę katalogu na $NAZWA.orig. Następnie ponownie rozpakuj źródła i pracuj na nich. Wejdź do ich katalogu i postępuj zgodnie z instrukcjia ich instalacji/kompilacji. Jeśli będzie konieczna edycja jakichś plików to konieczne będzie wygenerowanie pliku z poprawkami (patch). Jeśli doprowadzisz źródła do stanu w którym będą się poprawnie instalować/kompilować - wyczyść katalog źródłowy. Upewnij się, że wszystkie pliki stworzone w skrypcie konfiguracyjnym (`configure`) zostały usunięte. Następnie wyjdź z katalogu źródłowego i wykonaj coś takiego:

> `

>             diff -uNr dirname.orig dirname > ../SOURCES/dirname-linux.patch

> `

(dirname w tym przykładzie to to samo co $NAZWA parę linii powyżej). Polecenie to stworzy plik z poprawkami jaki będzie mógł być wykorzystany w pliku specyfikujący. Zauważ, że ``linux'' w nazwie pliku z poprawkami jest jakimś wybranym identyfikatorem. Zamiast tego można użyć czegoś bardziej precyzyjnego jak np. ``config'' lub ``bugs'' (błędy) by opisać dlaczego poprawki były potrzebne. Przed użyciem pliku z poprawkami warto do niego zajrzeć by się upewnić, że przypadkiem nie znalazło się w nim coś niewłaściwego jak np. pliki binarne.

### Tworzenie listy plików

Teraz, gdy źródła się kompilują i instalują i wiadomo jak to robić to zrób to, skompiluj i zainstaluj. Przyjrzyj się wynikowi instalacji i stwórz w ten sposób listę plików do użycia w pliku specyfikującym. Zazwyczaj plik specyfikujący powstaje równocześnie z opisywanymi tu krokami. Po prostu tworzy się go na początku wstawiając to co jest znane i potem w miarę postępu prac uzypełnia się go o brakujące kawałki.

### Tworzenie pakietu RPM

Gdy plik specyfikujący jest gotowy, można już próbować tworzyć nowy pakiet. Najwygodniej jest to zrobić poniższym poleceniem:

> `

>             rpm -ba foobar-1.0.spec

> `

Opcja `-b` ma parę interesującyh podopcji:

- `p` oznacza wykonanie sekcji `prep` pliku specyfikującego.
- `l` wykona parę różnych testów na plikach `%files`.
- `c` wykonaj sekcję `prep` i kompiluj. Jest to przydatne gdy jest się niepewnym czy źródła w ogóle będą się kompilować/instalować. Owszem, na pierwszy rzut oka może to wyglądać na zbędne gdyż można dotąd pracować ze źródłami aż będą się kompilować jednak gdy przyzwyczaisz się do wykorzystania RPM-a to spotkasz się z sytuacjami w którach ta opcja okaże się przydatna.
- `i` wykonaj prep, kompiluj i instaluj.
- `b` prep, kompiluj, instaluj, i buduj jedynie pakiet binarny.
- `a` zbuduj wszystko - zarówno pakiet źródłowy jak i binarny.

Jest też parę dodatkowych podopcji do opcji `-b`:

- `--short-circuit` przejdzie prosto do określonego etapu (może być użyte wyłącznie z c oraz i)
- `--clean` usuwa katalog ze źródłami stworzony w czasie budowania pakietu.
- `--keep-temps` zachowa wszystkie pliki temporalne i skrypty które zostały umieszczone w /tmp. Jakie są to pliki można się dowiedzieć wykorzystując opcję `-v`.
- `--test` nie wykonuje żadnych rzeczywistych etapów choć wykonuje keep-temps.

## 6.10 Testowanie pakietu

Po stworzeniu pakietu rpm źródłowego i binarnego należy je przetestować. Najprościej i najlepiej jest wykorzystać do tego zupełnie inny komputer niż ten na którym pakiet był tworzony. W końcu przy tworzeniu pakietu był on dość często instalowany i na komputerze na którym powstawał powinno być to zrobione dość dobrze.

Można też próbować `rpm -u nazwapakietu.rpm` na testowanym pakiecie ale może być to zdradliwe w sytuacji w której jakieś pliki zostały pominięte w liście plików i nie zostaną wtedy usunięte. Wtedy zainstalowany program będzie kompletny mimo tego, że rpm będzie błędny. Pamiętaj, że ponieważ Ty już zrobiłeś `rpm -ba package`, to zdecydowana większość osób instalujących Twój pakiet wykona jedynie `rpm -i package`. Upewnij się, że nie wykonujesz w sekcjach `build` lub `install` czegoś co powinno być zrobione gdy instalowany jest wyłącznie pakiet binarny.

## 6.11 Co robić z Twoimi nowymi RPM-ami ?

Gdy już stworzyłeś swój własny pakiet RPM (zakładając, że nie ma już takiego pakietu dostępnego pod postacią RPM) możesz udostępnić wynik swojej pracy innym (zakładając że to czego pakiet stworzyłeś może być tak udostępniane). By udostępnić, umieść to na ftp.redhat.com.

## 6.12 Co teraz?

Prosimy sprawdzić się, że nic nie zostało pominięte jeszcze raz czytając rozdziały o "Testowaniu" i "Co robić z nowymi RPM-ami". Chcemy mieć jako RPM wszystko co się da ale chcemy, żeby były to dobre RPM-y. Prosimy więc poświęcić trochę czasu na ich dokładne przetestowanie i prosimy też o umieszczenie ich w archiwum ftp tak, by każdy mógł z nich skorzystać. A także, prosimy upewnić się, że umieszczasz jedynie bezpłatne oprogramowanie. Oprogramowanie komercyjne i shareware nie powinno być umieszczane w archiwum o ile nie zawierają klauzuli w ich prawach autorskich to dopuszczającej. Dotyczy to np. Netscape, ssh, pgp, etc.

## 7. Tworzenie RPM-ów na wiele platform.

RPM może być wykorzystywany do tworzenia pakietów dla Intel i386, Digital Alpha pracujących pod Linux, oraz Sparc. Są też doniesienia o jego wykorzystaniu na platformach SGI i HP. RPM ma parę cech które czynią tworzenie pakietów na wiele platform prostszymi. Pierwszą z nich jest dyrektywa ``optflags'' w pliku `/etc/rpmrc`. Może ona być wykorzystana do ustawienia odpowiednich opcji i flag, specyficznych dla architektury, potrzebnych do kompilacji bądź instalacji. Następną cechą ułatwiającą tworzenie pakietów na wiele platform są makra ``arch'' w pliku specyfikującym. Mogą one być wykorzystane do wykonania różnych rzeczy zależnych od architektury na której pakiet jest instalowany. Następną taką cechą jest dyrektywa ``Exclude'' w nagłówku.

## 7.1 Przykładowy plik specyfikujący .spec

Poniżej zamieszczona jest część pliku specyfikującego dla pakietu ``fileutils''. Jest on przygotowany do instalacji na dwóch platformach: Alfach i Intelu.

> `

>     Summary: GNU File Utilities
>     Name: fileutils
>     Version: 3.16
>     Release: 1
>     Copyright: GPL
>     Group: Utilities/File
>     Source0: prep.ai.mit.edu:/pub/gnu/fileutils-3.16.tar.gz
>     Source1: DIR_COLORS
>     Patch: fileutils-3.16-mktime.patch

>     %description
>     These are the GNU file management utilities.  It includes
>     programs
>     to copy, move, list, etc, files.

>     The ls program in this package now incorporates color ls!

>     %prep
>     %setup

>     %ifarch alpha
>     %patch -p1
>     autoconf
>     %endif
>     %build
>     configure --prefix=/usr --exec-prefix=/
>     make CFLAGS="$RPM_OPT_FLAGS" LDFLAGS=-s

>     %install
>     rm -f /usr/info/fileutils*
>     make install
>     gzip -9nf /usr/info/fileutils*

>     .
>     .
>     .

> `

## 7.2 Dyrektywa optflags

W powyższym przykładzie przedstawione zostało użycie dyrektywy ``optflags'' z `/etc/rpmrc`. `RPM_OPT_FLAGS` przyjmują odpowiednią wartość w zależności od tego na jakiej platformie instalowany jest pakiet. Do pliku Makefile użytego w pakiecie należy nanieść poprawki by korzystał z tej zmiennej zamiast standardowych opcji (np. `-m486` lub `-O2`). Możesz się zorientować co powinno być zrobione poprzez zainstalowanie pakietu źródłowego, jego rozpakowanie i przyjrzenie się plikowi Makefile. Następnie należy zajrzeć do plików z poprawkami dla pliku Makefile i sprawdzić jakie zmiany powinny być wprowadzone.

## 7.3 Makra

Makro `%ifarch` jest bardzo istotne dla tworzenia pakietów na wiele architektur. W większości przypadków potrzebujesz nanieść jedną lub dwie poprawki specyficzne tylko dla jednej, konkretnej architektury. W takiej sytacji RPM pozwala na naniesienie poprawki wyłącznie dla niej.

W powyższym przypadku, pakiet fileutils ma poprawkę dla maszyn 64-bitowych. To naturalnie w chwili obecnej stosuje się tylko do Alf. Tak więc dodajemy makro `%ifarch` nanoszące odpowiednią poprawkę:

> `

>     %ifarch axp
>     %patch1 -p1
>     %endif

> `

To zapewni, że poprawka nie będzie naniesiona na żadnej innej architekturze a wyłącznie na alfach.

## 7.4 Wyłączanie pewnych platform w pakietach

Można opiekować się źródłowymi RPM-ami w jednym katalogu dla wszystkich platform. Uzyskuje się to poprzez ``wyłączenie'' (ang. exclude) pewnych pakietów z tworzenia ich dla pewnych architektur, tak, że ciągle możliwym jest:

> `

>     rpm --rebuild /usr/src/SRPMS/*.rpm

> `

dające w wyniku poprawne pakiety. Jeśli aplikacja nie została jeszcze do tej pory przeniesiona na daną platformę to wystarczy dodać wiersz wygladający mniej więcej tak:

> `

>     ExcludeArch: axp

> `

do nagłówka pliku specyfikującego pakiet źródłowy. Następnie przebuduj pakiet na platformę na której już pracuje. W ten sposób uzyskuje się pakiet, który kompiluje się/tworzy się np. na Intel-u podczas gdy może być łatwo opuszczony na Alfie.

## 7.5 Ostatnie poprawki

Wykorzystanie RPM to tworzenia pakietów przeznaczonych na wiele platform jest zazwyczaj prostsze niż doprowadzenie pakietu do stanu w którym daję się on na nich zainstalować. Jednakże w miarę jak powstaje więcej i więcej pakietów w postaci binarnej staje się to coraz prostsze. Jeśli przy tworzeniu pakietu zabrniesz w ślepą uliczkę to jak zwykle, rozwiązaniem może być zajrzenie do kodu źródłowego podobnego pakietu.

## 8. Uwaga o prawach autorskich

Poniższy dokument i jego zawartość są chronione prawem autorskim. Rozpowszechnianie go i jego zawartości jest dozwolone tak długo jak długo jego pozostają one nie zmienione. Innymi słowy można go wyłącznie przeformatowywać, drukować i rozpowszechniać.