Xwelltris to taki sympatyczny tetris w którym układa się klocki na dnie
,,studni''. Kolejny klon tej odmiany tetrisa. Nic specjalnego, ale jest
całkiem porządnie wykonany, jest napisany w C++ i może używać SDL. Jego
instalacja przysparza jednak pewnych kłopotów, a więc świetnie nadaje się na
dziewiąty przykład :)
1. Źródła wystarczy pobrać i rozpakować.
2. Próbna instalacja
Pakiet rozpakowuje się do katalogu xwelltris-1.0.1,
a więc konieczne będzie użycie opcji ,,-n'' w makrze %config. Nie ma zbyt
wielu opcji konfiguracyjnych, prawdę mówiąc jedyne dostępne sprowadzają się
do wyboru pomiędzy używaniem przez xwelltris ,,gołych'' X-ów a SDL, ja decyduję się na same X-y, bez SDL.
./configure --with-x --prefix=/usr
Konfiguracja przechodzi gładko, zaczynam kompilować, ale zauważam coś
dziwnego - w wynikach kompilatora widzę cały czas flagę
,,-fomit-frame-pointer''... A kompilowane pliki to kod w C++ (używany
kompilator to c++, a rozszerzenia plików to .cxx
- czyli C++, jak nic). Tyle, że flaga -fomit-frame-pointer jest, w obecnym
stadium rozwoju GCC, dla kodu w C++ szkodliwa i nie należy jej w takiej
kombinacji za nic w świecie używać. I ja mam odpowiednio ustawione zmienne
$CFLAGS i $CXXFLAGS. Najwidoczniej xwelltris zignorował $CXXFLAGS i wziął
ustawienia z $CFLAGS. No dobra...
tak, teraz widzę na ekranie poprawne flagi. Czekam na zakończenie kompilacji...
OK, skończył. Teraz instalacja: make install
DESTDIR=/shm... kończy się błędem.
No tak. Najwidoczniej xwelltris ignoruje też zmienną DESTDIR. Hmm, więc może
ma jakąś własną zmienną? Czasem tak bywa. W pliku INSTALL nie znajduję
jednak żadnych informacji o tym. Przeglądnięcie Makefile upewnia mnie, że
xwelltris nie używa żadnych zmiennych by przekierować instalację.
Jest to bez wątpienia jedna z najgorszych rzeczy, jakie mogą się przydarzyć. Wyjścia są tutaj dwa: 1.
Ignoruje się to, kompiluje normalnie program, a w sekcji %install olewa
mechanizmy programu i ręcznie kopiuje wybrane kąski z katalogu ze
źródłami do %{buildroot}. Można sobie na to pozwolić gdy zna się listę
plików które należy zainstalować, no i gdy lista ta nie jest specjalnie
długa (wpisywanie dwustu regułek dla ,,cp'' i ,,mkdir'' czy też ,,install''
w pliku .spec może zabić człowieka, zostało to naukowo udowodnione!) 2.
Zmienia się pliki Makefile i pochodne tak, aby zaczęły respektować jakąś
zmienną. Może i wymaga większego wysiłku, ale okazuje się być ,,tym
właściwym'' rozwiązaniem jeśli poruszamy się na ,,nieznanym terytorium''
(nowy program), lub lista instalowanych plików przekracza choćby
kilkanaście/kilkadziesiąt. Ta technika wymaga z pewnością pewnego
doświadczenia. Należy znaleźć w plikach Makefile te linijki, które
faktycznie instalują pliki, następnie znaleźć ich źródło, bowiem
pliki Makefile są często tylko czubkiem góry lodowej i swoje ustawienia
czerpią z innych plików. Na dodatek takie rzeczy rozwiązuje się
indywidualnie, bo jeśli pakiet nie respektuje $DESTDIR to zwykle jest
napisany niestandardowo. Jeśli jest napisany niestandardowo, to znaczy, że
jego autor napisał go tak, jak jemu się wydawało, że ,,będzie
dobrze''. Czyli istnieje spora szansa, że każdy zrąbany pakiet będzie
absolutnie odmienny od innego zrąbanego pakietu, że będzie miał inaczej
rozplanowaną sekwencję instalacyjną itp. W tym przypadku (xwelltris)
irytujące jest to, że autor użył mechanizmów autoconf... ale nieumiejętnie,
popełniając parę istotnych błędów.
W tym przypadku niestety w grę wchodzi tylko sposób nr 2. Niestety. Nie znam
listy plików xwelltris, więc muszę go ,,naprawić''. Notka: Powyższe jest oczywiście kłamstwem :) Spis instalowanych
plików jest łatwo poznać. Wystarczyłoby mi skompilować xwelltris z jakimś
,,bezpiecznym'' prefiksem, np. ''--prefix=/shm'', skompilować i zainstalować
przez make install. Potem obejrzeć co też xwelltris
natworzył w /shm i użyć tego jako wzornika dla pliku .spec. Na potrzeby tego
artykułu jednak muszę wciskać miejscami kit w żywe oczy :)
Po paru minutach śledzenia różnych plików dochodzę do wniosku, że winny jest
plik Makefile.in (w przypadku pakietów używających autoconf to akurat
normalne, autoconf oznacza równocześnie używanie automake. A automake tworzy
pliki Makefile z plików Makefile.in. Więc chcąc poprawić plik Makefile
modyfikuje się plik Makefile.in, a ./configure przy
następnym uruchomieniu je zaktualizuje (w świetle tego modyfikowanie
bezpośrednio plików Makefile to w przypadku automake robota głupiego, walka
z wiatrakami).
chodzi mi o ten plik usr/bin. Tak, to plik, a nie
katalog. Plik wykonywalny. Wiem, co się stało: ten głupi xwelltris próbował
kopiować binarkę do /usr/bin bez określenia, że
chce ją wkopiować do katalogu. Założył, że katalog bin będzie istniał, więc wykonał coś w stylu
cp xwelltris /usr/bin
I to był błąd. Bo w przypadku gdy bin nie istniało
w chwili kopiowania, to cp (lub inny program
kopiujący, np. install) umieściło binarkę w /usr/bin. Gdyby autor skryptów zapisał to hiper-poprawnie
jako
cp xwelltris /usr/bin/
(chodzi o ten ukośnik na końcu linii), to wtedy program kopiujący by zgłosił
błąd. Pamiętaj: jeśli piszesz skrypty kopiujące coś do jakiegoś katalogu
i masz zamiar udostępniać te skrypty innym ludziom, to wyraźnie
oznaczaj typy plików. Bywają różne systemy, różne układy katalogów itp.
Lepiej jeśli program od razu się wyłoży, niż gdyby miał po cichu zmasakrować
binarkę umieszczając ją w dziwnym miejscu.
Dobra, ten błąd nie jest groźny, wystarczy w pliku .spec utworzyć odpowiedni
katalog %{buildroot}%{_bindir} przed rozpoczęciem
instalacji.
Ale jest jeszcze jedna rzecz która mnie zastanawia - brak manuali. Hmm. Dla
pewności przeglądam katalog ze źródłami... Nie, najwidzoczniej xwelltris nie
ma dokumentacji innej, niż te parę luźnych plików README na krzyż. No dobra,
to czas wygenerować patcha. Eee, ale ja nie mam już oryginalnego pliku
Makefile.in. W ferworze walki nadpisałem go tym zmienionym. Dobra, kopiuję
Makefile.in do Makefile.in.new i jeszcze raz rozpakowuję źródła. Uruchamiam
W zasadzie tutaj nie ma już co wyjaśniać - normalna preambuła, z deklaracją
jednego patcha. Sekcja %setup z nałożeniem patcha. W sekcji %build najpierw
ustawiam $CFLAGS na wartość $CXXFLAGS (bo xwelltris ma ten dziwny błąd
z braniem flag kompilatora C do kompilacji C++). W sekcji %install najpierw
zakładam katalog %{buildroot}%{_bindir} (bo
xwelltris ma ten dziwny błąd... zresztą, sam wiesz :). Aha, opcja ,,-p''
podana mkdir powoduje, że będzie on zakładał ,,łańcuch'' katalogów, tak jak
polecenie mkdirhier.
Sekcja %files też w normie. Jedyne zmiany to wywalenie linijki dla manuali
i dodanie linijki dla %{_datadir}/xwelltris.
4. Budowanie pakietu zaczęło się, podziałało, skończyło. Pakiet
wynikowy powstał - czyli sukces na całej linii. Teraz tylko uruchamiam sobie
rpmbuild -bs --rmspec --rmsource xwelltris.spec
a rpm tworzy w ~/rpm/SRPMS pakiet źródłowy zawierający speca, patcha
i źródła w jednej milutkiej paczuszce. A ta wędruje do mojego składowiska
Rzeczy Absolutnie Wartych Przechowywania. Teraz mogę w prosty sposób
ponownie przekompilować cały pakiet, w razie upgrade'u wystarczy podmienić
paczkę ze źródłami - plik .spec i patch nie powinny się zdezaktualizować.