Hierophant do zbudowania pakietu używa katalogu o określonej strukturze. Układa ona w pewnej hierarchii dane potrzebne do kompilacji pakietu:
katalog_pakietu/ | |-FILES/ | |-arch1.tar.gz | |-arch2.tar.bz2 | +-patch1.diff.gz | |-BUILD/ | |-rozpakowane_źródła/ | +-ukryte_pliki_tymczasowe | |-SCRIPTS/ | |-PREIN | |-POSTIN | |-PREUN | +-POSTUN | +-schemat_budowy.plan |
Jak widać katalog zawiera cztery główne pozycje - trzy podkatalogi (FILES, BUILD, SCRIPTS) oraz jeden plik (*.plan). Katalog FILES służy do przechowywania ogólnie pojętych plików źródłowych. Archiwa ze spakowanym kodem źródłowym, patche, dodatkowe manuale, stworzone wcześniej gotowe pliki konfiguracyjne dla danej aplikacji itp. Katalog BUILD jest wykorzystywany przez Hiero przy kompilowaniu. To w nim pojawiają się rozpakowane drzewka z kodem źródłowym, w nim odbywa się kompilacja, w nim też zapisywane jest parę ukrytych plików zawierających dane tymczasowe potrzebne Hierophantowi przy budowaniu pakietu. Użytkownik nie ma tam po co zaglądać, chyba że w celach diagnostycznych. Użytkownik nie umieszcza też nic w tym katalogu, jego zarządzaniem zajmuje się Hiero. Ręcznie umieszczone w tym katalogu dane zapewne zostaną w którymś momencie automatycznie skasowane. Katalog SCRIPTS to miejsce, w którym użytkownik może umieścić przygotowane wcześniej skrypty skojarzone z pakietem. Hiero w określonych sytuacjach generuje również automatycznie swoje własne skrypty, w zbudowanej paczce będą one łączone z ew. skryptami użytkownika. Plik foo.plan to tzw. "planfile", odgórny schemat działania którego będzie się trzymał Hiero. On steruje większością aspektów pracy Hiero. W nim też opisana jest wersja pakietu, jego krótki opis itp. |
Ale warto opisać niektóre elementy dokładniej...
FILES, jak powiedziałem, ma przechowywać ogólnie rozumiane źródła.
Hiero rozróżnia tu trzy rodzaje danych - "źródła" (paczki *.tar kompresowane
programem gzip/bzip2), "patche" (pliki o nazwach *.diff/*.patch, ewentualnie
kompresowane gzipem/bzip2), oraz "inne" (czyli wszystko co się nie załapało
do poprzednich kategorii). Hiero zestawia sobie listę wszystkiego co
znajdzie w FILES, segreguje na kategorie po czym przystępuje do działania.
Paczka źródłowa zostanie rozpakowana, a patche automatycznie zaaplikowane
z patchlevel ustawionym na "-p1". Kolejność aplikowania patchy zależna jest
od ich nazw, a więc można nią sterować tak jak np. kolejnością uruchamiania
skryptów startowych SysV, dodając do nazw numeryczne
przedrostki.
Jeśli Hiero wykryje więcej niż jedną paczkę źródłową, będzie próbował
namierzyć "tę właściwą" używając paru dopasowań nazwy pakietu i jego wersji
by wyłonić prawdopodobnego kandydata. Jeśli zgadywanie zawiedzie (bardzo
nieprawdopodobne), weźmie po prostu pierwszą paczkę z listy. W przypadku
prostych źródeł (jedna paczka) nie ma oczywiście żadnego problemu. Paczki
które nie są źródłami ani patchami zostaną po prostu przypisane pewnym
zmiennym środowiskowym, by podczas budowania paczki można było się łatwo do
nich odwołać. Wszystkie te zachowania można jednak wyłączyć i przejść na
"sterowanie ręczne" używając pewnych konstrukcji w pliku .plan.
W SCRIPTS umieszcza się skrypty "okołoinstalacyjne". Można z pakietem powiązać 4 skrypty, wykonywane przez system zarządzania pakietami stosownie: po instalacji, po usunięciu, przed instalacją i przed usunięciem pakietu. Zwroty "przed instalacją" czy "przed usunięciem" mogą brzmieć nieco dziwnie, ale chodzi po prostu o moment na chwilę przed umieszczeniem plików pakietu na dysku lub na chwilę przed ich usunięciem. Np. skrypt "PREUN" będzie mógł jeszcze wykorzystywać programy zawarte w pakiecie który jest usuwany, podczas gdy "POSTUN" już tego zrobić by nie mógł. Skrypty te powinny być pisane w narzeczu /bin/sh, nie muszą zawierać deklaracji #!/bin/sh i nie muszą mieć ustawionego bitu wykonywalności. System obsługi pakietów będzie je source-ował, aby uniknąć niepotrzebnego wywoływania kolejnych shelli (ze względu na specyfikę operacji przeprowadzanych przez "zarządzarkę pakietów" uruchamianie skryptów w pod-shellach mogłoby się czasem nie powieść, np. gdy w przypadku glibc należy uruchomić ldconfig). Co oznacza jednak, że skrypty te stają się w pewnym momencie integralną częścią procesu instalującego/usuwającego pakiety. A to z kolei oznacza, że nigdy, ale to przenigdy nie wolno w skryptach tych używać poleceń "exec" ani "exit", bo załatwi to na amen odgórny proces managera pakietów. Czyli zasada jest prosta: skrypty muszą wyglądać tak, by skrypt interpretowany przez /bin/sh mógł je source-ować i się nimi nie zadławić.
Jeśli jakieś polecenie w skryptach tych "zawiedzie", to nie będzie to miało bezpośredniego wpływu na działanie całego mechanizmu. W przypadku RPM jeden błąd w takim skrypcie zwykle wieszał cały proces RPM, często psując też wpisy w bazie danych. To bardzo nierozsądne, delikatnie mówiąc, więc ja zdecydowałem się na ignorowanie błędów.
Aby plik skryptu został dołączony do pakietu wystarczy umieścić go pod odpowiednią nazwą w SCRIPTS. Jeśli nie masz zamiaru używać skryptów, to nie musisz nawet zakładać katalogu SCRIPTS.
O BUILD nie ma co mówić - tam Hiero wypakowuje źródła, tam je też patchuje, tam je konfiguruje i kompiluje. Tam też umieszcza ukryte pliki ".hbs_*" zawierające wszystkie skrypty i dane używane przy budowaniu pakietu. Jeśli przerwiesz budowanie pakietu (lub zakończy się ono niepowodzeniem), to te ukryte pliki pozostają i możesz je podejrzeć. Ale nie sądzę by komukolwiek oprócz mnie zależało na ich czytaniu. Ogólnie rzecz biorąc jest to jeden plik wykonywalny (#!/bin/sh), pełniący rolę koordynatora i uruchamiający poszczególne podskrypty, odpowiadające za kolejne fazy budowania paczki. Ostatnią część akcji wykonuje jednak już odgórny, pythonowy proces hbs. Takie tam bebechalia, nic ciekawego. Aha, źródła po rozpakowaniu nie są usuwane, chyba że zażyczysz sobie ponownego ich rozpakowania. Hiero mógłby je automatycznie czyścić po udanym zbudowaniu paczki, ale na razie, gdy samemu uczę się jego obsługi, obecne zachowanie jest lepsze - pozwala mi po zbudowniu już paczki zbudować ją jeszcze raz, z drobnymi modyfikacjami, ale pomijając czasochłonne rozpakowywanie czy kompilację źródeł. Ale o przeskakiwaniu etapów budowania jeszcze opowiem. W każdym razie po zbudowaniu paczki możesz spokojnie skasować cały BUILD.
No i najważniejsza część - plik .plan. Powinien nazywać się tak, jak paczkowany pakiet - czyli np. pakując gcc plan powinien nazywać się gcc.plan. To właśnie nazwa pliku .plan decyduje o nazwie wynikowego pakietu!
Plik .plan należy sobie stworzyć i wypełnić treścią. Treść składa się z sekcji. Sekcje to takie logiczne obszary odpowiadające za jakiś wycinek funkcjonalności. Wszystkie sekcje są opcjonalne, oprócz jednej, która musi być koniecznie obecna i nie wiem nawet co Hiero by zrobił gdyby jej nie znalazł. A sekcją tą jest [info]...
[info] to bardzo sformalizowana sekcja. Zawiera dokładnie dwa wiersze tekstu. A oto przykład:
[info] The GIMP - GNU Image Manipulation Program. 2.0pre4-1 | Wiersz pierwszy zawiera jednolinijkowy, krótki opis zawartości pakietu. Tak, jeden wiersz musi wystarczyć. Jeśli budujesz sobie samodzielnie pakiety to naprawdę nie potrzebujesz więcej. A wiersz drugi zawiera wersję programu i wersję pakietu, połączone znakiem minusa. Nie możesz w wersji programu użyć minusa, czyli np. "2.0-pre4-1" jest niewłaściwe. Jeśli koniecznie musisz w wersji programu użyć jakiegoś separatora, to użyj np. podkreślenia - 2.0_pre4-1. Minus ma być tylko jeden. Możesz za to użyć minusa w nazwie samego pakietu, np. dozwolone jest "slrn-pl-1.4.3-1", ale niedozwolone byłoby już "slrn-pl-1.4.4-rc1-1" |
Ciąg opisujący "version-revision" pakietu można też pobierać z rurki, z zewnętrznego polecenia. Np. Łukasz Horodecki swego czasu wymyślił sobie, że przy kompilowaniu IceWM z CVS można wygrzebywać aktualną wersję z jakiegoś ChangeLoga czy czegoś takiego. Ja prywatnie wolę numerować kompilacje z CVS za pomocą aktualnej daty. Można by też zrobić tak, by pole version-revision ustawiało się w zależności od nazwy użytego pliku ze źródłami (uruchomić "ls" w katalogu FILES i wyciąć z rezultatu wersję - wtedy aktualizowanie pakietów mogłoby sprowadzać się do podmienienia paczki ze źródłami) - ale to tylko akademicki przykład. Ja proponuję coś nieakademickiego - coś, co sam często robię, a mianowicie wersjonowanie za pomocą daty:
[info] The GIMP - GNU Image Manipulation Program. PIPE:date +%Y%m%d-1 |
To spowoduje, że w rezultacie linijka zostanie ustawiona np. na '20040321-1'. Można używać tu oczywiście bardziej złożonych konstrukcji, z warunkami, grepowaniem, sedem itp. shellowymi rzeczami, ale musisz się zmieścić w jednym wierszu. Może być bardzo długi, ale nie wolno Ci go złamać. No i polecenie które zaprojektujesz powinno zwracać jeden wiersz, w formie zgodnej z opisanym już modelem version-revision. |
I to by było tyle jeśli idzie o [info]
A teraz kolejna sekcja - [files]. Jest to sekcja opcjonalna, pozwala wskazać Hierophantowi co jest główną paczką ze źródłami a co jest patchem, przy patchach pozwala też wybrać im patchlevel inny niż -p1. Wymusza też w naturalny sposób określoną kolejność patchowania. Wyłącza też wszelką automatykę wyszukiwania źródeł (co znaczy, że jeśli umieścisz w [files] jeden plik, to musisz też umieścić wszystkie pozostałe (o ile oczywiście istnieją jakieś "pozostałe"), bo inaczej nie zostaną zauważone. Jest to też sposób by wykryć brak jakiegoś pliku ze źródłami. Jest to też jedyny sposób by wykorzystać "źródła rozpakowane", ale nie uprzedzajmy faktów ;) Najlepiej będzie jeśli pokażę serię przykładów:
[files] gqview-1.5.0.tar.bz2 |
Bardzo prosty przykład, włączający pojedyncze źródła. Chyba najczęściej spotykany przypadek, zupełnie bezsensowny bo nie wymagający używania [files], takie rzeczy Hiero bez problemu obsługuje sam z siebie. |
[files] gqview-1.5.0.tar.bz2 manpages-pl.tar.gz sample_config.rc | Bardziej złożony przykład. Jedne źródła główne, które zostaną przez Hiero rozpakowane (padnie na gqview-1.5.0.tar.bz2, bo są pierwsze na liście - decyduje kolejność). Jedne źródła dodatkowe, które będą dostępne przez zmienną $SOURCE1, no i jeden plik dodatkowy (sample_config.rc) który będzie dla wygody dostępny zapewne przez $SOURCE2. |
[files] gqview-1.5.0.tar.bz2 1:patch1.diff 0:another.patch 0:patch3.diff.gz 2:patch4.diff |
A tutaj deklaruję 1 źródła i 4 patche. Patche można poznać po tych cyferkach
i dwukropku na początku - te cyferki to nie numery patchy, ale ich
"patchlevels". Patche nałożone zostaną według kolejności ich deklaracji,
w tym przypadku da to ciąg poleceń zgodny mniej więcej z tym: Do tego zadania również nie trzeba było deklarować sekcji [files], bo można patche ponazywać np. "10_patch1.diff", "20_another.patch" itp. (co wymusi kolejność ich aplikowania), oraz przerobić je tak, by każdy z nich aplikował się z -p0. |
[files] /home/grzegorz/CVS/main/ /home/grzegorz/CVS/ffmpeg/libavcodec/ |
No i na koniec katalogi z plikami... Tutaj małe objaśnienie - używam paru programów pobieranych bezpośrednio z CVS. Tak jest np. z mplayerem. I w miarę regularnie je sobie kompiluję. Dlatego też można Hierophantowi podać w [files] namiary na jakiś katalog położony poza jego katalogiem FILES. Katalog ten zostanie uznany za rozpakowane już źródła, które należy przekopiować do BUILD. Ot, takie ułatwienie dla tych paru projektów kompilowanych z CVS - nie trzeba się martwić o kopiowanie samemu, Hierophant zrobi to automatycznie. Założy odpowiedni podkatalog w BUILD, przekopiuje tam zawartość ~/CVS/main/* (czyli kod mplayera). A ten drugi wpis, libavcodec, zostanie mi udostępniony pod zmienną $SOURCE1, dzięki czemu będę mógł go łatwo dokopiować do kodu mplayera. Tutaj niestety nie mogłem wprowadzić żadnej automatyzacji, bo w przypadku dodatkowych źródeł nie da się odgadnąć co użytkownik by chciał z nimi zrobić. |
Jakub Panachida dodał do HBS dwa rozszerzenia dla ludzi ze stałym łączem
- nie testowałem ich nigdy, więc mogę coś pokręcić w opisie :)
1. Istnieje też możliwość zadeklarowania źródeł "zdalnych", tzn. takich które
leżą gdzieś na jakimś serwerze www/ftp i mają zostać przed budowaniem
pakietu pobrane. Wystarczy zamiast nazwy pliku zadeklarować go
w [files] jako pełny URL, np.
"ftp://ftp.gnu.org/pub/coreutils/coreutils-5.2.1.tar.gz" albo
"http://foo.pl/foo.tar.bz2". HBS automatycznie pobierze te źródła do
podkatalogu BUILD/ po uruchomieniu polecenia "hbs -d".
2. Dodatkowo można w sekcję [files] wplatać polecenia shellowe - zostało to dodane z myślą o CVS, aby można było stworzyć paczkę która sama by potrafiła pobrać sobie jakieś repozytorium i zbudować kod. Robi się to wpisując po prostu polecenia linijka po linijce, ale prefiksując je ciągiem "CVS:", trochę jak to jest z PIPE: w [info].
Następną sekcją wartą opisania jest [mods]. Steruje ona uprawnieniami plików umieszczanych w wynikowej paczce. Hierophant nie paczkuje plików tak, jak je kompilator i "make install" stworzył, ale aplikuje swój standardowy "bezpieczny wzorzec", ustawiając globalnie prawa "root.root,0644" na wszystkich plikach, a potem dodając "+x" na plikach w /bin, /sbin, /usr/X11R6/bin i innych standardowych lokacjach. To pokrywa potrzeby 90% pakietów dając jednocześnie gwarancję, że żaden plik nie prześliźnie się z niewłaściwymi uprawnieniami. Ale czasem to za mało, np. jakiś program zainstaluje gdzieś w /usr/lib/foo/ parę binarek... z których Hiero zdejmie bit wykonywalności (domyślnie nic w /usr/lib nie ma być wykonywalne)... co jednak okaże się w tym wypadku błędem. I wtedy można użyć sekcji [mods], która pozwoli zmienić uprawnienia operując regexpowymi maskami:
[mods] 0755:root:root:"^usr/lib/foo/.*" |
ten drobny wpis spowoduje, że /usr/lib/foo/ razem z zawartością dostaną uprawnienia 0755. Oczywiście do dyspozycji jest cała potęga regexpów, np. oryginalny wpis z mojego gcc.plan wygląda tak:
[mods] 0755:root:root:"^usr/lib/.*/(cc1|cc1plus|collect2)$" 0755:root:root:"^usr/lib/.*/install-tools/(fixinc.sh|fixincl|mkheaders)$" |
A teraz może opiszę składnię. Sekcja zbudowana jest z wierszy, każdy postaci 'perm:owner:group:"regexp"'. Poszczególne pola są oddzielone od siebie dwukropkami (opcjonalnie można też do dwukropków dodawać spacje, co według Pewnych Ludzi podnosi czytelność zapisu). Pierwsze pole to bity. Podane ósemkowo. Najchętniej w notacji czterocyfrowej. Nie pamiętam czy trójcyfrowa też jest wspierana, pewnie jest (wydaje mi się, że o to zadbałem) , ale jej nie polecam. Wygląda nieprofesjonalnie ;)
Po bitach podać trzeba nazwę właściciela. Nazwę symboliczną, a nie numeryczny UID! Można podać nazwę nieistniejącą w momencie budowania paczki, to nie problem. Nazwy są tłumaczone na uidy dopiero w momencie instalowania.
Trzecie pole to nazwa grupy. Uwagi identyczne jak poprzednio.
Ostatnie pole to regexp. Tutaj mam 2 zastrzeżenia - po pierwsze, cały regexp
musi być cytowany. To umyślnie wprowadzony wymóg, którego jednak nie umiem
teraz już wytłumaczyć. Wiem jednak, że jest to jakoś związane z estetyką
:)
Drugie zastrzeżenie to początek regexpu. Zobacz, że zawsze zaczynam
od "usr/", a nie od "/usr". Dokładnie o to chodzi - nie możesz podać
pierwszego ukośnika. Po prostu nie możesz. Znowu wprowadziłem to umyślnie,
ze względu na zgodność z pewną inną sekcją używającą regexpów, w której
z kolei jest to podyktowane pewnymi zaszłościami histerycznymi których nie
mam teraz ochoty tłumaczyć. Po prostu tak jest, tak ma być, tak jest dobrze
i tak jest ładnie. No :)
Podsumowując - sekcja [mods] w prosty sposób pozwala sterować uprawnieniami plików w budowanej paczce. Używa przy tym "wirtualnego" podejścia, tzn. uprawnienia ustawiane są bezpośrednio w archiwum tar w paczce, a nie w fake root, dzięki czemu można budować dowolne paczki na uprawnieniach zwykłego użytkownika.
A, zapomniałbym - jak wiadomo katalogi potrzebują bitu wykonywalności by można je było zwiedzać. A co się stanie, jeśli nałożysz uprawnienia 0644 na "usr/share/.*"? Czy podkatalogi w /usr/share staną się niedostępne? Otóż nie, Hiero automatycznie propaguje bity "+r" na "+x" w przypadku katalogów. To znaczy, że dla katalogów maska 0644 zostanie po cichu przekształcona na 0755. A np. maska 0640 przeszłaby w 0750... Zauważ że nie pojawił się tu już bit "+x" dla "all", bo nie było żadnego bitu "+r" dla "all".
Regexpy są dopasowywane w kolejności zdefiniowania, co znaczy że każdy kolejny regexp może zmieniać to co wprowadzili jego poprzednicy. Regexp ".*" łapie oczywiście wszystkie poprzednie regexpy, forsując swoje własne ustawienia na wszystkich plikach.
Kolejna opcjonalna sekcja to [ban]. Ustawia ona maski uwzględniane przy tworzeniu końcowego pakietu. Żaden plik pasujący do wzorców zawartych w [ban] nie dostanie się do paczki. Sekcja ta rozwiązuje dwa praktyczne problemy: po pierwsze, jak powstrzymać paczki od zawierania w sobie "popularnych" obiektów, jak np. "katalog /usr" czy "katalog /usr/lib/pkgconfig" (bez sensu by było, gdyby każdy pakiet twierdził, że /usr należy do niego - z drugiej strony nie można uczynić katalogów całkowicie bezpańskimi, bo to by skomplikowało nadmiernie usuwanie pustych, osieroconych katalogów przy usuwaniu pakietów). Tak że np. żaden zwykły pakiet nie powinien uzurpować sobie prawa do posiadania katalogów /usr/lib, /usr/share/doc itp. (to powinien robić najwyżej jeden pakiet w systemie, jakiś "FHS-dirs"), ale też np. pakiet gimpa powinien jak najbardziej brać sobie we władanie katalog /usr/lib/gimp/. Sekcja [ban] daje gwarancję, że te popularne, zdefiniowane w FHS katalogi nigdy nie staną się członkiem zwykłego pakietu. Najłatwiej wytłumaczyć to na przykładzie:
/usr/ /usr/bin/ /usr/bin/gqview /usr/share/ /usr/share/gqview/ /usr/share/gqview/README /usr/share/man/ /usr/share/man/man1/ /usr/share/man/man1/gqview.1.gz |
To co widzisz po lewej to surowe drzewko katalogów w fake root. Niestety, doprowadza to do stanu w którym każdy jeden program zainstalowany np. w /usr/bin będzie próbował usunąć ten katalog (/usr/bin) przy swojej deinstalacji. Oczywiście nie powiedzie mu się to, bo katalog nie będzie pusty, ale mimo wszystko jest to głupotą bo do niczego nie prowadzi. Po prawej stronie widzisz to co Hierophant zamieści w wynikowej paczce po nałożeniu standardowej maski [ban]. Jest to już dużo bardziej rozsądny schemat. | /usr/bin/gqview /usr/share/gqview/ /usr/share/gqview/README /usr/share/man/man1/gqview.1.gz |
Takie rzeczy [ban] robi automatycznie, bez deklarowania tej sekcji w pliku z planem. Po prostu założyłem, że takie działanie jest pożądane dla wszystkich pakietów (oprócz może tego jednego, hipotetycznego "FHS-dirs"), więc jest realizowane w tle, użytkownik nie musi specjalnie o nie prosić ani go włączać.
Ale takie wykluczanie katalogów to nie jedyne zastosowanie dla [ban]. Można też okazjonalnie blokować konkretne pliki, występujące tylko w danej paczce. Załóżmy np., że mamy jakiś program GTK+ przychodzący z dodatkowymi, zlokalizowanymi manualami (które nie są nam potrzebne, np. "/usr/share/man/ja/man1", "/usr/share/man/ru/man1", "/usr/share/es_ES/man1") oraz z plikami dla środowiska Gnome, którego też nie używamy (które to pliki by lądowały gdzieś w "/usr/share/gnome"). Aby wyłączyć te pliki z końcowej paczki można użyć następującej sekcji [ban+]:
[ban+] "^usr/share/man/(ja|ru|es_ES)/.*" ".*/share/gnome/.*" |
choć manuale można ująć dużo bardziej uniwersalnym regexpem (po prawej), który wychwyci też ewentualne nowe języki, jeśli dojdą w przyszłych wersjach paczkowanego programu: | [ban+] ".*/man/..(_..)?/.*" ".*/share/gnome/.*" |
Składnia tej sekcji bardzo przypomina sekcję [mods], z tym że każdy wiersz ograniczony jest tylko do ostaniego pola - do samego wyrażenia regularnego. Zasady tworzenia regexpów są identyczne - każdy ujęty w 'cytatniki' ;), każdy jest dopasowywany do nazw z uciętym pierwszym ukośnikiem, więc nie używaj go w regexpie.
Jak widać mówię cały czas o sekcji [ban], ale w przykładach używałem zapisu [ban+]. Dlaczego? Bo jest to sekcja która ma tzw. alternatywną deklarację, właśnie z tym plusem na końcu. Sekcję tę można definiować zarówno jako [ban], jak i [ban+]. Składnia jest absolutnie identyczna, ale jest pewna istotna różnica... powiedziałem, że istnieje pewna automatyczna część sekcji [ban], której nie trzeba nigdy deklarować. Która zawsze wyłącza "standardowe katalogi" z paczki. Używając formy [ban+] powoduję, że regexpy które wpiszę zostaną dodane do tych "wbudowanych" regułek. Jeśli bym użył sekcji [ban], te standardowe regexpy zostałyby zastąpione tym co samemu wpisałem. Co spowodowałoby, że pozbyłbym się tego automatycznego wykluczania katalogów. Z tego wynika, że w normalnych warunkach należy używać sekcji [ban+] aby nie niszczyć wbudowanych regexpów (ten znak plusa po nazwie sekcji oznacza właśnie "dopisywanie danych na końcu tego, co Hiero ma wbudowane"). Sekcji [ban] z kolei można użyć jeśli te wbudowane regułki banowania są niepożądane, np. przy budowaniu owego hipotetycznego pakietu "FHS-dirs". Użycie pustej sekcji [ban] (bez żadnych wpisów) powoduje w ogóle wyłączenie banowania (dostajesz wtedy maskę która akceptuje wszystko "jak leci", bo nie zna żadnych kryteriów wykluczania).
Istnieje jeszcze jedna sekcja o identycznej składni. Jest nią [keep]. Zadaniem tej sekcji jest wskazywanie które pliki w pakiecie są szczególnie "cenne" (a raczej że cenne są zmiany które użytkownik być może powprowadzał w tych plikach). Pliki wymienione w sekcji [keep] będą bacznie obserwowane przy odinstalowywaniu pakietu lub wykonywaniu upgrade-ów, Hierophant będzie kontrolował ich sumy kontrolne. Jeśli Hiero ustali, że pliki te zostały zmodyfikowane przez użytkownika, wtedy uruchomi procedury mające uniemożliwić zniszczenie zawartości tych plików. Generalnie odnosi się to do plików konfiguracyjnych wszelkiej maści, np.:
[keep] "^etc/wwwoffle/.*" |
Gdy po zainstalowaniu pakietu wwwoffle zmienię plik /etc/wwwoffle/wwwoffle.conf, to nie chciałbym by przy jakimś upgradzie Hiero nadpisał mi ten wycyzelowany, dopieszczony plik konfiguracyjny wersją która przyszła w nowej paczce. Sekcja [keep] kontroluje właśnie ten aspekt pracy Hiero. Oczywiście Hiero będzie chronił ten plik tylko jeśli wykryje, że to jakaś zmodyfikowana wersja, a nie default z poprzedniej paczki. W końcu defaulty można nadpisywać nowszymi wersjami defaultów. |
W praktyce działa to tak, że jeśli plik jest "fabrycznie nowy", to jest tak samo szmatławie traktowany jak wszystkie inne pliki. Jeśli jednak Hiero wykryje że plik był "tuningowany", to na pewno nie będzie on kasowany. Przy upgradzie jego nowsza wersja zostanie zapisana z dodanym rozszerzeniem ".hbs_new", ale nie nadpisze starego pliku. Przy usuwaniu pakietu taki plik też nie zostanie po prostu usunięty, Hiero wykona najpierw jego kopię o rozszerzeniu .hbs_saved. Przy ponownej instalacji pakietu Hiero wykorzysta tę zachowaną kopię. Brzmi to może skomplikowanie, ale w rzeczywistości jest banalnie proste. Po prostu włączaj w tej sekcji pliki, w których będziesz być może wprowadzał zmiany i nie chciałbyś potem tych zmian utracić.
Jeśli nie zdefiniujesz samodzielnie [keep], to zostaną użyte domyślne ustawienia, chwytające wszystkie pliki znajdujące się w /etc, /usr/local/etc itp. Jeśli jednak użyjesz [keep], to te domyślne ustawienia zostaną "zapomniane" - [keep] działa tylko w tym jednym trybie, nie ma żadnego [keep+], bo uznałem że w tym wypadku nie byłoby to potrzebne. Zdefiniowanie pustej sekcji [keep] oczywiście wyłącza całkowicie specjalne traktowanie plików w danym pakiecie.
Teraz kolej na trzy inne sekcje, związane bezpośrednio z mechaniką pracy Hierophanta. Są to sekcje [prep], [build] i [inst]. Odpowiadają one za trzy główne etapy budowania pakietu. [prep] to rozpakowywanie i patchowanie źródeł. [build] to ew. generowanie skryptu ./configure, uruchamianie go, oraz obowiązkowa kompilacja. [inst] zaś odpowiada za przetransportowanie skompilowanych danych z przepastnych czeluści katalogu BUILD do /var/tmp/hbs/pakiet-wersja-release/, czyli po prostu za instalację w fake root. Wszystkie trzy sekcje są opcjonalne. Jeśli nie zabierzesz się do ich definiowania, to Hiero użyje własnych, przewidzianych przeze mnie "defaultów" - które powinny w mniejszym lub większym stopniu pokrywać jakieś 70-80% przypadków. Zawartość tych sekcji to, dla odmiany, już nie jakieś wymyślone przeze mnie regułki, ale zwykły kod shella. Takie małe fragmenty skryptów #!/bin/sh.
Najpierw sekcja [prep]. Jej domyślna, zautomatyzowana wersja bierze źródła i rozpakowuje je gdzieś w BUILD (lub kopiuje je tam, w przypadku podania zewnętrznego katalogu ze źródłami poprzez sekcję [files]). Następnie aplikuje wszystkie patche, przerywając swoje działanie jeśli któraś z tych operacji się nie powiedzie. Sekcja ta definiuje również zmienną $BUILDSUBDIR wskazującą położenie katalogu z rozpakowanymi źródłami (ale to teraz nieistotne - zmienne używane przez Hiero i sposób ich używania opiszę w innym miejscu). I na tym kończy się jej "sfera odpowiedzialności".
Sekcja ta występuje w trzech typach deklaracji, mianowicie
[prep], [prep+] oraz [+prep]. Wersja "zwykła", [prep],
powoduje całkowite zastąpienie domyślnego kodu tej sekcji. Wersja
[prep+] służy do doklejenia własnych poleceń do tej sekcji, tak by najpierw
zostały wykonane defaulty, a dopiero potem Twój kod - np. jeśli po
rozpakowaniu i popatchowaniu źródeł należy poprzesuwać tam jakieś pliki,
albo przepuścić je przez sed-a czy coś w tym stylu. Jak widać znak plusa ma
tutaj identyczne znaczenie jak w przypadku [ban] - oznacza "przyklejenie
własnych modyfikacji na końcu tego, co domyślne".
Ostatnia forma, [+prep], jest podobna do [prep+], z tym że modyfikacje nie
są doklejane na końcu, a na początku. Wszystko co podasz w [+prep] zostanie
wykonane zanim Hiero pozwoli zagrać swoim defaultom. Nie wiem na ile jest to
użyteczne, ale nigdy nic nie wiadomo. Przykładem zastosowania tej sekcji
może być np.:
[prep+] touch $BUILDSUBDIR/*/doc/*.texi* touch $BUILDSUBDIR/etc/*.texi* |
Jest to żywy przykład wyjęty z mojego binutils.plan. Po rozpakowaniu źródeł "dotykam" źródeł dokumentacji texinfo, przez co stają się one najnowszymi plikami w pakiecie. Dzięki temu make na nowo wygeneruje z nich dokumentację Info. A po co to wszystko? Bo używam nowego pakietu texinfo, który przy generowaniu plików Info nie rozbija ich już na dziesiątki drobnicy, której serdecznie nie lubię - a która standardowo przychodzi z binutils i potem ląduje w /usr/share/info. Jeśli zmuszę make do wygenerowania dokumentacji na nowo, to stanie się to przy użyciu moich narzędzi. Które nie pozwolą na rozdrobnienie dokumentacji. A wygodnym sposobem by to osiągnąć jest dotknięcie plików źródłowych dokumentacji gdzieś pomiędzy rozpakowaniem źródeł a ich kompilacją. Automatycznie ustawiana zmienna $BUILDSUBDIR zawiera ścieżkę do rozpakowanych źródeł, np. "/home/grzegorz/hbs/binutils/BUILD/binutils-2.14.90.0.8" |
Drugą sekcją w tej triadzie jest [build]. Sekcja ta odpowiada z grubsza wydaniu poleceń "./configure&&make", ale oczywiście z parunastoma ulepszeniami. Po pierwsze, automatyczna sekcja [build] potrafi wykryć, że pakiet nie posiada pliku ./configure i spróbuje wygenerować go używając ./autogen.sh albo podejścia bardziej "ręcznego", chyba że uzna, iż pakiet nie używa tego modelu - wtedy po prostu uruchamia make. Poleceniu ./configure przekazywana jest automatycznie plejada standardowych opcji, takich jak --prefix=/usr --mandir=/usr/share/man itp. Można też, używając specjalnych zmiennych, wpływać na inne aspekty pracy automatu. Ale o tym później. Sekcja ta również działa w trzech trybach - [build], [build+] i [+build], z uwagami identycznymi jak przy [prep]. Myślę, że nie trzeba tu dawać teraz żadnych przykładów. Podanie pustej sekcji [build] powoduje w ogóle przeskoczenie tej fazy (a w zasadzie zastąpienie jej pustym kodem) - przydatne dla pakietów których się nie kompiluje, np. paczki z fontami dla ghostscriptu.
Ostatnia z sekcji to [inst]. Ona włada procesem instalacji, co
standardowo oznacza uruchomienie jakiegoś ekwiwalentu
"make install DESTDIR=/var/tmp/hbs/name-version-revision". Używając pewnych
zmiennych można wpływać na proces instalacji, np. zamienić "make install" na
"make install-libs install-docs", ale, jak się pewnie domyślasz, nie będę
o tym jeszcze mówił :) Sekcja ta pracuje w trzech trybach, [inst],
[inst+] i [+inst]. Przewidywalne, prawda? Sekcji tej można
użyć aby zmodyfikować pliki po zainstalowaniu ich w fake root (np. przenieść
jakiś katalog w inne miejsce, stworzyć jakieś symlinki itp.), można też jej
użyć by zastąpić procedurę instalacyjną czymś własnym, co np. nie posługuje
się wcale "make install":
[inst+] ln -s vim $HBS_DESTDIR/$BINDIR/vi | To kod wyjęty z mojego vim.plan. Tworzy on, po zainstalowaniu plików w fake root, symlink vim->vi (bo z przyzwyczajenia zawsze wpisuję "vi plik"). Jak widać posłużyłem się zmiennymi $HBS_DESTDIR i $BINDIR, ale to znowu nie czas i miejsce na objaśnianie zmiennych. Sorry :P |
[inst]
mkdir -p $HBS_DESTDIR/usr/{lib/firefox,bin}
cp -a $BUILDSUBDIR/* $HBS_DESTDIR/usr/lib/firefox
ln -s ../lib/firefox/firefox $HBS_DESTDIR/usr/bin/firefox
|
A to z kolei sekcja z mojego firefox.plan. Firefox to kobyła i jakoś
przyzwyczaiłem się, że najpierw sobie go w spokoju gdzieś kompiluję, potem
przechodzę do katalogu xpinstall/packager, tam wydaję magiczne
polecenie
make MOZ_PKG_APPNAME=firefox \ po czym z katalogu ../../dist/ wyjmuję gotową paczkę zawierającą drzewko plików Firefoxa. Potem pozostaje mi tylko taką paczkę przekształcić w pakiet możliwy do zainstalowania managerem pakietów. To jednak znaczy, że w paczce źródłowej dla Hiero mam już gotowe binaria, których się nie kompiluje ani nie instaluje za pomocą make (bo nie ma w ogóle żadnego Makefile). Dlatego też procedurę instalacyjną piszę samemu i polega ona z grubsza na założeniu odpowiednich katalogów w $HBS_DESTDIR i przekopiowaniu tam wszystkich plików. |
Jest jeszcze jedna sekcja o której nie wspomniałem do tej pory. Ta sekcja to [vars] i służy do ustawiania zmiennych modyfikujących działanie Hierophanta. Istnieje tylko w jednej formie, bez żadnych plusów, i jest interpretowana przez Hiero zanim zacznie działać [prep]. Jej treść to zwykły skrypt shella który może robić dowolne rzeczy, ale jak powiedziałem jego zadaniem jest ustawianie zmiennych. A przynajmniej tak powinno być. Prosty przykład:
[vars] SBINDIR=/sbin CONF_OPTS="--disable-nls --disable-evms" MAKEINST_OPTS="install install-libs" |
Ustawiam tu trzy zmienne - po pierwsze, definiuję $SBINDIR na wartość /sbin (jeśli bym tego nie zrobił, to Hiero ustawiłby to na /usr/sbin). Po drugie, ustawiam CONF_OPTS - zawartość tej zmiennej zostanie automatycznie dodana do wywołania ./configure przez automat sekcji [build]. Ustawiam też MAKEINST_OPTS, co spowoduje że sekcja [inst] zamiast "make install" użyje "make install install-libs". A przykład ten pochodzi z mojego e2fsprogs.plan i jest jak najbardziej autentyczny. SBINDIR muszę przedefiniować, aby takie programy jak e2fsck wylądowały w /sbin, a nie /usr/sbin. MAKEINST_OPTS jest też konieczne, jeśli oprócz narzędzi chcę zainstalować również biblioteki do obsługi ext2 (wymagane przez któryś z moich projektów). |
No i to by było na tyle :)