Dobrych kilka miesięcy temu pojawił się numer specjalny Linux+ poświęcony Debianowi. Miałem w nim okazję umieścić swój tekst o budowaniu pakietów. Później uzyskałem nawet zgodę na publikację na łamach 7thGuarda, jednak sam tekst zaginął w czeluściach mojego dysku. Odnalazł się dzisiaj, więc zapraszam do lektury i podsyłania poprawek. Wersja bardziej tekstowa znajduje się na mojej stronie domowej.
Kiedy ponad rok temu przygotowywałem swój pierwszy w życiu pakiet dla  Debiana, rzucił mi się w oczy brak polskiego tekstu opisującego cały  proces budowy paczki debianowej. Konkretnie – brak tekstu dla  początkujących, gdyż w poświęconym Debianowi Potato numerze Linux+  pojawił się artykuł przeznaczony raczej dla zaawansowanych użytkowników  dpkg. Mam nadzieję, że ten tekst pomoże zapełnić tę lukę w literaturze.
W katalogu /usr/share/docs/ można znaleźć kilka dokumentów, które  przydadzą się przy tworzeniu oficjalnych pakietów i z częścią nich powinni  się zapoznać wszyscy przyszli developerzy Debiana. Jeśli chcecie stworzyć  pakiet dla własnego użytku, poniższy artykuł powinien wam wystarczyć,  jednak mimo wszystko dobrze jest zapoznać się z następującymi dokumentami  (w nawiasie podaję pakiet, w którym znajduje się każdy tekst):
Debian New Maintainer’s Guide (maint-guide) – chyba najlepszy  istniejący podręcznik tworzenia pakietów dla Debiana. Napisany z myślą o  początkującym developerze, prowadzi go praktycznie krok po kroku od momentu  przygotowywania źródeł do spakowania, aż do uploadu gotowego pakietu na  serwer oraz jego późniejszych aktualizacji.  
Debian Policy Manual (debian-policy) jak również wszystkie dokumenty z pakietu debian-policy są opisem standardów stosowanych przez wszystkich twórców Debiana i każdy pakiet, który ma trafić do dystrybucji, powinien być zgodny z opisanymi w tych dokumentach założeniami.
Debian Packaging Manual (packaging-manual) – opis technicznej części budowy pakietów, w którym można znaleźć specyfikację plików kontrolnych, a także instrukcja obsługi niektórych narzędzi niezbędnych przy pracy nad tworzeniem plików .deb.
  Debian Developer’s Reference (developers-reference) – dokument   przeznaczony głównie dla developerów i kandydatów na developerów, w którym  można znaleźć informacje na temat sposobu uploadowania gotowych pakietów  do dystrybucji, informacje na temat obsługi błędów, sposób zarządzania  kluczem gpg itp.
Jak głosi rzymskie przysłowie (przytoczone zresztą przez Josepha Rodina we  wstępie do Debian New Maintainer’s Guide), najprościej uczyć na  przykładach. W tym celu stworzyłem prosty pakiet składający się z  jednego pliku wykonywalnego, hello, makefile-a oraz krótkiej  dokumentacji — strony manuala, pliku README oraz changelog. Oznacza to, że  w jego skład wchodzą wszystkie podstawowe elementy spotykane w  zaawansowanych programach.
Do tworzenia pakietu Debiana wykorzystamy narzędzia  debhelper oraz dh_make, które zostały stworzone z myślą o  ułatwieniu całego procesu. Są one wykorzystywane również przez twórców  Debiana, tak więc nie ma obawy, że pakiet wykonany przy ich pomocy mógłby  mieć problemy ze znalezieniem się w oficjalnej wersji Debiana.
Pierwszym narzędziem, po które sięgniemy, jest dh_make – narzędzie, które  rozpakuje nam kod źródłowy opracowywanego przez nas oprogramowania, a także  założy strukturę plików wymaganą podczas budowania pakietu. Załóżmy, że  oprogramowanie skopiowane przez nas ze stron producenta jest spakowane do  pliku hello_0.02.tar.gz. Zakładamy sobie katalog ~/debian,  w którym będziemy trzymać nasze pakiety, a w nim podkatalog  hello-0.02. Jego nazwa powinna składać się z samych małych liter,  a numer wersji musi być oddzielony znakiem minus. Jeśli autor oryginalnego  oprogramowania nie numeruje wersji w sposób XX.YY.ZZ, lecz na  przykład wstawia tam datę, musimy przekształcić proponowaną przez niego  nazwę w coś o kształcie nazwa-0.0.20011218. Do tak utworzonego  podkatalogu rozpakowujemy plik ze żródłami.  
  Do katalogu debian/ kopiujemy plik z kodem źródłowym, wchodzimy  do uprzednio założonego podkatalogu i wykonujemy komendę dh_make -e  moj_adres@mojekonto.pl  -f ../hello_0.02.tar.gz. Zostaniemy zapytani o  to, czy pakiet będzie biblioteką, programem z jedną lub wieloma binarkami.  Najczęstszą odpowiedzią będzie tu s, nawet jeśli nasze  oprogramowanie udostępnia więcej niż jeden plik wykonywalny – możliwość  m (multiple binary) przydaje się przy tworzeniu dużych  pakietów, które będą się później składać z wielu plików .deb.  
  Po potwierdzeniu naszego wyboru, w katalogu debian/hello-0.02  zostanie utworzony podkatalog debian, w którym znajdują się  wszystkie pliki wykorzystywane przy budowie pakietu .deb. Jak się  za chwilę okaże, część z nich można usunąć bez obaw o konsekwencje –  dh_make tworzy ich tyle, ile możemy potrzebować, rzadko jednak zdarza  wszystkie wykorzystamy.
Pierwszą rzeczą, na którą musimy zwrócić uwagę, jest lokalizacja plików  powstałych po kompilacji oprogramowania. Zwykle – choć nie zawsze – są   one skonfigurowane tak, by pliki należące do programu lądowały w  podkatalogach /usr/local/.   Pakiety Debiana powinny kopiować pliki binarne do /usr/bin/,   manuale do /usr/share/man/, a dokumentację – do   /usr/share/doc/.  
  Dlatego też musimy poprawić plik Makefile naszego przykładowego  pakietu w taki sposób, żeby był dopasowany do wymagań stawianych przez  Debian Policy. W tym celu modyfikujemy wszystkie ścieżki w sekcji  install. Trzeba pamiętać, że w przypadku programów wykorzystujących  programy typu automake czy autoconf, edycja wynikowego  Makefile na wiele nam się nie przyda, gdyż będzie on za każdym razem  generowany na nowo. Dlatego do przygotowywania pakietów z takim  oprogramowaniem przydaje się znajomość struktury plików  Makefile.am i Makefile.in.
W chwili, kiedy rozpoczynamy generowanie pakietu, na dysku zakładany jest  katalog tymczasowy, w którym odwzorowana jest struktura plików tworzonych  podczas kompilacji. Dlatego w wykorzystywanym później do budowy pakietu  pliku Makefile przed każdą ścieżką powinniśmy dodać zmienną ustawianą przez  builder. Zmienna o nazwie DESTDIR wymagana jest tylko przy programach nie  korzystających z autoconfa, gdyż w ich przypadku odpowiednie modyfikacje  zostaną automatycznie wprowadzone przez dh_make.  
Tak więc na początku naszego przykładowego Makefile-u pojawi się teraz nowa linijka: DESTDIR =, a przed każdą ścieżką docelową – $(DESTDIR). Ostateczny wygląd pliku Makefile przedstawiony jest na rysunku 2.
  Bardzo ważne jest pamiętanie, że zmiana katalogu z danymi, z których  obrabiany przez nas program korzysta dopiero podczas uruchomienia, wymaga  nie tylko zmian w Makefile-u, lecz również ingerencji w sam kod źródłowy,  ewentualnie pliki konfiguracyjne. Nie jest do tego wprawdzie potrzebna  doskonała znajomość języka, w którym stworzono dane oprogramowanie, jednak  jeśli nie jesteśmy pewni, czy sobie dobrze poradziliśmy z modyfikacją  źródeł warto poświęcić więcej niż zwykle czasu na testowanie finalnego  pakietu.
Przyszedł czas na rzecz najważniejszą – edycję plików umieszczonych przez  dh_make w podkatalogu debian/. Pierwszym z nich jest  control, w którym umieszczane są informacje o autorze pakietu,  jego nazwie, architekturach, na których działa, a także jego krótki opis.  Pierwotnie plik ten wygląda w następujący sposób:    
Source: hello Section: unknown Priority: optional Maintainer: Debian UserStandards-Version: 3.0.1 Package: hello Architecture: any Depends: ${shlibs:Depends} Description: 
  Pierwsza linijka jest nazwą pakietu źródłowego, następnie znajduje się  miejsce na wpisanie sekcji, w której pakiet zostanie umieszczony. Może to  być main, non-free lub contrib. W związku z tym,  że nasz pakiet jest rozprowadzany na zasadach licencji GNU GPL, może on  trafić do sekcji main. Gdyby jego zainstalowanie pociągało za sobą  konieczność instalacji oprogramowania z sekcji non-free, trafiłby  on do sekcji contrib. Następnie trzeba podjąć decycję co do  podsekcji – wśród możliwych do wpisania są x11, base,  devel itp. Nasz program kwalifikuje się do kategorii  misc, co też wpisujemy w odpowiednie miejsce.
Opcja Priority określa, jak ważny jest nasz program dla całości  dystrybucji – w związku z tym, że nie straci ona na stabilności i  użyteczności bez niego, zostawiamy tam wpis optional.  
  Pod Priority powinniśmy wpisać oprogramowanie, które nie znajduje  się w standardowym Debianie, a które jest wymagane do kompilacji naszego  pakietu. Podczas jego budowy wykorzystamy możliwości dawane przez pakiet  debhelper, dlatego dodajmy tam linijkę o treści Build-Depends:  debhelper.
Kolejne pola są miejscem na wpisanie naszych danych, wersji  Debian-Policy z którą nasz pakiet jest zgodny, nazwy pakietu  binarnego oraz architekturę (zwykle any). Ostatnie trzy pola  posłużą nam na ustawienie zależności (wpis ${shlibs:Depends}  zwykle wystarczy), krótkiego opisu wyświetlanego np podczas listowania  pakietów komendą dpkg -l oraz dłuższego opisu, który pojawi się na  przykład podczas przeglądania dostępnych pakietów programem  dselect.
Oczywiście nie są to wszystkie możliwe opcje, które mogą się znaleźć w tym  pliku, jednak te wystarczają do stworzenia większości pakietów.  Wygląd pliku control po wprowadzeniu odpowiednich modyfikacji  znajdziecie na rysunku 3.
Innym dość ważnym dla dystrybucji i samego pakietu jest  copyright, który zwykle zastępuje plik z licencją dołączaną do  oprogramowania. Umieszcza się w nim dane dotyczące autora pakietu, autora  oryginalnego oprogramowania, a także adres pakietu źródłowego oraz krótką  informację o licencji – ewentualnie, jeśli jest to licencja niestandardowa  (nieznajdująca się w /usr/share/common-licenses/) – jej pełną  treść. Dzięki temu unika się istnienia na dysku kilku tysięcy jednakowych  kopii pliku z treścią GNU GPL, a pojawia się standardowe miejsce, w którym  można znaleźć informacje o sposobie licencjonowania danego pakietu.
Kiedy tworzymy pakiet, często nieuniknione są poprawki w jego źródła – czy  to zmiany w Makefile, czy też poprawione drobne błędy, które w nim się  pojawiły. Do tego, a także do informowania o różnicy pomiędzy kolejnymi  wersjami pakietów, służy plik changelog. Umieszczany później pod nazwą  changelog.Debian, jest nierzadko podstawowym źródłem informacji przy   podejmowaniu decyzji o ewentualnej aktualizacji. Jeśli tworzymy nową  wersję pakietu tylko dlatego, że pojawiła się nowa wersja oprogramowania,  umieszczamy tu linijkę w stylu New upstream release, jeśli jest to  jego pierwsza wersja – pierwszym wpisem powinno być Initial  Release..  
  Informacje zawarte w tym pliku – a konkretnie numer wersji pakietu  umieszczony w nawiasach przy jego nazwie – służy do ustalenia ostatecznej  nazwy pakietu .deb. Ostateczna zawartość debian/changelog nie jest  tu prezentowana, jednak zmodyfikowany plik znajdziecie wraz z resztą  pakietu na stronie, której adres podano na rysunku 1.
Jeśli nasz pakiet – co nie zachodzi w tym przypadku – posiada jakiekolwiek  pliki konfiguracyjne, powinniśmy je wpisać wraz z pełną ścieżką  do debian/conffiles. Dzięki temu podczas aktualizacji pakietu  zostaniemy zapytani, czy chcemy zastąpić poprzednią konfigurację – nową, a  przy usuwaniu pakietu komendą dpkg --remove ustawiona przez nas  konfiguracja nie zostanie stracona.
Jak już uprzednio wspomniałem, podczas budowy pakietu na dysku tworzony  jest katalog tymczasowy mający odwzorować późniejszą strukturę plików w  pakiecie. Do automatycznego stworzenia wszystkich katalogów, które nie są  budowane przez Makefile, wykorzystywana jest zawartość pliku  debian/dirs. Standardowo znajdziecie w nim wpis zakładający  usr/bin i usr/sbin, który powinien wystarczyć w  większości mało zaawansowanych programów.  
  W związku z tym, że z pliku Makefile nie usunęliśmy komend kopiujących  strony manuala oraz dokumentację (choć pakiet debhelper daje możliwość  automatyzacji tych procesów), musimy tu dodać wpisy zakładające  usr/share/doc oraz usr/share/man/man1
Jeśli chcemy, żeby nasz pakiet po instalacji pojawił się w menu po  uruchomeniu X Window System, musimy zmienić nazwę debian/menu.ex  na debian/menu, a także odpowiednio go zmodyfikować. W tym celu  warto zapoznać się z dokumentacją do pakietu menu, a także  stanowiącym część pakietu debian-policy dokumentem   Debian Menu sub-policy.
Najważniejszym plikiem, który zarządza budową pakietu, jest   debian/rules, który jest niczym innym jak skryptem wykonywanym  przez program make. Znajdziecie w nim wywołanie wszystkich poleceń  używanych do stworzenia pakietu. Postaram się tu pokrótce opisać te  najważniejsze, pełną instrukcję ich obsługi możecie znaleźć wśród stron  manuala.  
Sekcja build odpowiada za kompilację pakietu – tu znajduje się wywołanie make, tu też możecie dopisać informację o komendach, które powinny być wydane w celu skompilowania pakietu
Poniżej znajduje się clean, który jest wywoływany zawsze przed budową pakietu. Sekcja ta odpowiada za usunięcie wszystkich plików mogących być pozostałością po poprzednich konfiguracjach, podobnie jak install, zwykle nie wymaga większych modyfikacji.
  Kolejna sekcja – install – jest dokładnym zapisem kolejnych etapów  kompilacji – tu znajdują się wywołania programów odpowiedzialnych za  założenie katalogu debian/tmp/ (a w nim całego drzewa katalogów  używanych przez tworzony właśnie pakiet), wyczyszczenie kodu źródłowego  z niepotrzebnych plików i wreszcie samego make z odpowiednimi  parametrami.
Wreszcie – binary-arch, czyli oprogramowanie odpowiedzialne za  poskładanie zainstalowanego chwilę wcześniej do katalogu  debian/tmp/ programu w jeden pakiet. Każde z nich posiada własną  stronę manuala, ja opiszę tylko najważniejsze:  
    dh_testroot – sprawdza, czy procedura tworzenia pakietu została  uruchomiona z konta root. Pakiety Debiana muszą być tworzone przez  użytkownika z uprawnieniami administratora… lub przez osobę korzystającą  z programu rfakeroot, który potrafi oszukać dużą część programów  sprawdzających prawa uruchamiającego.
    dh_installdocs – kopiuje dokumentację programu – w tym pliki  debian/changelog oraz – ewentualnie –  debian/README.Debian i debian/TODO.Debian do katalogu  /usr/share/doc/nazwapakietu/. Jeśli utworzyliśmy plik  debian/docs, w którym znajduje się lista innych plików należących  do dokumentacji, również zostaną one skopiowane.
    dh_installmanpages odpowiada za skopiowanie wszystkich stron  manuala, które znajdą się w katalogu źródłowym, do odpowiednich katalogów w  /usr/share/man/. Może być zastąpiony odpowiednim wpisem do  pliku Makefile.
    dh_md5sums generuje sumy kontrolne wszystkich plików wchodzących  w skład pakietu.
    dh_gencontrol tworzy katalog DEBIAN, w którym umieszcza  opis pakietu i sumę kontrolną wszystkich plików w nim zawartych.  Te informacje można obejrzeć  wchodząc do dowolnego  pakietu .deb przy pomocy Midnight Commandera.
    dh_builddeb buduje pakiet.
Wśród innych programów, które mogą tu być wywołane, są odpowiadające za  aktualizację crona (dh_installcron), menu X Window System (dh_installmenu)  czy tworzenie linków symbolicznych (dh_link). Warto się zapoznać z opisem  wszystkich programów wchodzących w skład pakietu debhelper, gdyż  często mogą one znacznie ułatwić pracę przy tworzeniu pakietu.
Kiedy już będziemy gotowi do zbudowania naszego pakietu, cofnijmy się o  jeden katalog do góry (czyli po prostu do głównego katalogu ze źródłami)  i wydajmy komendę dpkg-buildpackage -rfakeroot. Jesli chcemy, żeby  część plików była podpisana naszym kluczem gpg, dodajmy do tego jeszcze  opcję -sgpg. Po chwili – jeśli nie zrobiliśmy żadnych błędów – w  katalogu nadrzędnym do aktualnego pojawi się plik  o nazwie hello_0.02-1_i386.deb. Możemy go już zainstalować w  systemie, jednak lepszym pomysłem jest jego uprzednie sprawdzenie na  zgodność ze standardami Debiana. Służy do tego pakiet Lintian.
Lintiana wywołujemy podając jako parametr plik .deb, co  zaowocuje wygenerowaniem raportu tylko dla gotowego pakietu, albo  .changes – wówczas Lintian sprawdzi wszystkie pliki, które są w  nim wymienione. Przy budowaniu pierwszych pakietów, kiedy jeszcze nie  jesteśmy nie mamy wprawy ich przygotowywaniu, pomocna może się okazać opcja  -i, która spowoduje, że Lintian poza wyświetleniem suchej  informacji o niezgodności z Policy spróbuje naprowadzić nas na  rozwiązanie problemu.
Kiedy nasz pakiet jest na takim etapie, że Lintian nie wyświetla w odpowiedzi  żadnego komunikatu, prawdopodobnie jest on zbudowany z zachowaniem  wszelkich reguł sztuki. Oznacza to też, że pora na jego dokładne  przetestowanie. W tym celu spróbujmy kilkukrotnie zainstalować i  odinstalować nasz pakiet, jeśli jest to już jego kolejna wersja – próby  upgrade’u również nie zaszkodzą. Dopiero kiedy mamy pewność, że nie ma w  nim żadnego błędu, możemy go wysłać na serwer Debiana, ewentualnie – jeśli  nie jest on przygotowywany do oficjalnej wersji tej dystrybucji – rozpocząć  jego rozpowszechnianie. Niestety, jak się okazuje nie wszyscy przestrzegają  tej prostej, wydawałoby się, reguły, a przekonali się o tym wszyscy  użytkownicy wersji unstable, którzy przez błąd w jednym z pakietów  nie mieli możliwości zalogowania się na własne komputery. No, ale to już są  uroki korzystania z niestabilnych wersji Debiana 😉
Po pewnym czasie, który możemy przeznaczyć albo na pracę nad nowymi   pakietami, albo na robieniu tego, co robić lubimy najbardziej, znienacka  dopadnie nas informacja o pojawieniu się nowej wersji oprogramowania,  którym się opiekujemy. Nie oznacza to oczywiście, że pora na panikę  – nie, nie czeka nas już tyle pracy, co nad stworzeniem pakietu od podstaw.   Życie ułatwi nam należący do pakietu devscripts program  uupdate. Chociaż do dobrych nawyków należy czytanie dokumentacji, to  jednak w jego wypadku możecie tego nie robić – cała jego obsługa sprowadza  się do wydania jednego polecenia.
Nim to jednak nastąpi, musimy skopiować  nowy plik ze źródłami (na przykład hello_0.03.tar.gz) do katalogu   ~/debian/. Następnie wchodzimy do katalogu, w którym stworzyliśmy  poprzednią wersję pakietu (czyli wydajemy komendę cd  ~debian/hello-0.02/ i wpisujemy polecenie uupdate -u  hello_0.03.tar.gz. Trzeba pamiętać, żeby nazwa pliku podana jako  parametr była identyczna, jak nazwa pliku z nowymi źródłami, który jest  umieszczony katalog wyżej. Po chwili na dysku pojawi się  ~debian/hello-0.03/, a w nim wszystkie pliki potrzebne do budowy  pakietu. Spróbujmy go teraz zbudować poleceniem dpkg-buildpackage  -rfakeroot -sgpg, a pliki wynikowe sprawdzić podobnie jak  sprawdzaliśmy poprzednią wersję pakietu – przy pewnej dozie szczęścia  aktualizacja ograniczy się do konieczności wydania tylko tych kilku poleceń  i skopiowaniu nowej wersji pakietu na serwer.  
    Ramka 1:
  Potrzebne narzędzia:  
- pakiet debhelper
 - pakiet dh-make
 - pakiet lintian
 - pakiet fakeroot
 - pakiet devscripts
 
Przykładowe oprogramowanie opisywane w tym artykule można znaleźć na stronie http://honey.7thGuard.net/lplus/hello/
Ramka 2:
DESTDIR= CC=gcc CFLAGS= all: hello hello.c install: cp hello $(DESTDIR)/usr/bin/ cp hello.1 $(DESTDIR)/usr/share/man/man1/ mkdir $(DESTDIR)/usr/share/doc/hello cp docs/* $(DESTDIR)/usr/share/doc/hello/ clean: rm hello
Ramka 3:
Source: hello Section: misc Priority: optional Maintainer: Lukasz JachowiczBuild-Depends: debhelper Standards-Version: 3.5.6.0 Package: hello Architecture: any Depends: ${shlibs:Depends} Description: Pakiet z nieprawidlowym - bo polskim - opisem Krociutki pakiet stworzony przez honeja po to, zeby pokazac czytelnikom miesiecznika Linux+ sposob tworzenia plikow .deb. A warto je robic, bo sa fajne i juz. 
Archiwalny news dodany przez użytkownika: honey.
Kliknij tutaj by zobaczyć archiwalne komentarze.




