Bociek PLD - Pisarz
I. Informacje podstawowe
II. Instalacja
III. Podręcznik użytkownika
IV. Podręcznik administratora
V. Tworzenie PLD - Praktyczny poradnik
Możliwa droga do zostania szeregowym developerem PLD
Pierwszy spec
VI. O podręczniku
O tej książce
Spis treści
Inne wersje tego dokumentu
HTML (jeden plik)
Odnośniki
Tworzymy dokumentację PLD
Strona PLD
Listy dyskusyjne PLD

Pierwszy spec

<- ->
 

No to zaczynamy. Naszym pierwszym (a właściwie moim) wykonanym specem będzie Mantis czyli system kontroli błędów oparty o stronę WWW (PHP) i bazę SQL Mysql.

Tutaj mała dygresja - większość pakietów powstaje dlatego, że danemu Developerowi był on akurat potrzebny; oznacza to że nie ma sensu pisanie na listę dyskusyjną z prośbą o stworzenie określonego pakietu bo można otrzymać parę przykrych komentarzy (w najlepszym razie).

Pierwszą czynnością jest zainstalowanie pakietu ze źródeł. Potem notujemy sobie co należy zrobić aby dany pakiet zaczął działać - wszystko po to aby przewidzieć co dany .spec powinien zrobić aby pakiet pracował w miarę bezproblemowo po instalacji RPMa - Można to zanotować np. na kartce papieru - ale od czego mamy komputery?

Moje notatki wyglądały tak:

// MANTIS
	 
// Mysql init
# cd /etc/rc.d/init.d
# ./mysql init
# /usr/bin/mysqladmin -u mysql password 'password'
	     
// Tworzenie bazy w mysql
# mysqladmin -umysql -p create bugtracker
# cd /mantis/sql
# mysql -umysql -p bugtracker < db_generate.sql
		 
// Plik config_inc.php
	  
// Sprawdzenie i poprawka
http:/mantis/admin/check.php
		    
// Pierwsze logowanie
u: administrator
p: root
Dodać nowe i skasować stare :-)
		        
// co potrzebne do uruchomienia
- mysql
- mysql-client
- php
- php-common
- php-pcre
- php-mysql
- apache
			        
// do rpma (zmiany w związku z językiem)
plik: config_defaults_inc.php
$g_default_language = 'english';
$g_default_language = 'polish'; 
// Zamiana łańcucha w config_defaults_inc.php
sed -e s/$g_default_language = 'english';/$g_default_language = 'polish';/g
config_defaults_inc.php
      
// Zamiana usera z root na mysql
w config_inc.php

Do każdego pakietu należy podchodzić indywidualnie - dlatego parę słów o samym mantisie. System jest oparty o gotowe pliki składające się na stronę WWW, dokumentacje i plik potrzebny do stworzenia odpowiedniej bazy Mysql. Nie będziemy dokonywali żadnych kompilacji - więc uprości to nasz proces budowania i testowania pakietu.

Łącząc informacje zawarte w dostarczonej dokumentacji i własnych notatek wiemy już że głównym zadaniem naszego RPMa będzie takie zaprojektowanie go, aby odpowiednie pliki PHP zostały przekopiowane w odpowiednie miejsce, dokonać niezbędnych poprawek w plikach konfiguracyjnych lub innych poprawek, które naszym zdaniem mogą ułatwić pracę przyszłym użytkownikom. Pamiętajmy jednak żeby nie przedobrzyć.

Niestety nie wszystko uda nam się zautomatyzować - dlatego stworzymy dwa pliki tekstowe (w dwóch wersjach językowych PL i EN) z krótkim opisem, co należy wykonać aby system zadziałał.

Wydaje mi się także, że dobrym zwyczajem jest po zainstalowaniu źródeł przewidzieć właściwe zależności, aby nasz pakiet działał bez problemu na innym komputerze. Na przykład w instrukcji do instalacji mantisa w wymaganiach jest wymieniony m.in. pakiet PHP - W PLD po instalacji samego PHP, mantis będzie wyświetlał błędy. Okazuje się że pakiety w PLD są maksymalnie ''rozdrobnione'' i do działania potrzebny jest jeszcze pakiet 'php-pcre' - a do tego, żeby strony PHP odpowiednio komunikowały się z bazą 'mysql' jest potrzeba zainstalowania 'php-mysql'. Zależności może być wiele i moim skromnym zdaniem lepiej żebyśmy umieścili jakiś nadmiarowy pakiet w zależnościach niż żeby jakiegoś brakowało.

W naszym przypadku po zainstalowaniu i uruchomieniu pakietu Mantis ze źródeł, wystarczy wykonać np. 'rpm -qa |grep php' aby wybrać odpowiednie pliki. To samo robimy z 'mysql' i 'apache'.

Zaczynamy od stworzenia pliku (możemy użyć polecenia 'touch') lub korzystamy z innego pliku .spec w celu modyfikacji do naszych potrzeb (np. 'cvs get SPECS/template.spec' spowoduje ściągnięcie szkieletu z CVS PLD). Otwieramy go w naszym ulubionym edytorze tekstowym (vim, emacs, pico, mcedit itp.)

Summary: The Mantis Bug Tracker
Summary(pl): Mantis - System Kontroli Błędów
Name: mantis
Version: 0.18.0a4
# define _alpha a4
Release: 1
License: GPL
Group: Development/Tools 

[...]

Zaczynamy wypełniać tzw. preambułę, czyli wstęp w którym opisujemy nasz pakiet - myślę, że wyjaśnianie powyższego nie jest specjalnie potrzebne. Zwrócę tylko uwagę na linię 'Version' i 'Ralease' - zgodnie z devel-hints-pl.txt powinno ono raczej wyglądać tak (ponieważ ta wersja mantis'a jest określona jako alpha):

Version: 0.18.0 %define alpha a4 Release: 0.%{_alpha}.1

ale u mnie powodowało to błąd przy budowaniu, gdyż jak dalej zobaczymy nazwa źródeł korzysta z pola 'Version' i każda manipulacja na nim powoduje potrzebę przebudowania .speca lub zmianę nazwy archiwum w którym są źródła (co jest bardzo złym nawykiem i karygodnym błędem!). Tak więc w końcu zostawiłem tak jak jest i nikt specjalnie nie zwrócił mi na to uwagi :-) (przyp. autora: jednak późniejsza praktyka pokaże nam, że zmiany takie są jednak chlebem powszednim więc nie bójmy się ich dokonywać)

[...]
	 
Source0: http://dl.sourceforge.net/mantisbt/%{name}-%{version}.tar.gz
# Source0-md5: 4c730c1ecf7a2449ef915387d85c1952
Source1: %{name}-doc-PLD.tar.gz
URL: http://mantisbt.sourceforge.net/
	     
[...]

Dalej mamy opis źródełek - w PLD podaje się go najczęściej w formie linku plus fraza %{name}-%{version}.tar.gz i tak naprawdę ta fraza jest najważniejsza do zbudowania pakietu, ponieważ URL (w naszym przypadku http://dl.sourceforge.net/mantisbt/) jest ignorowany. Tak więc z makra %name i %version budowana jest nazwa pakietu i taka nazwa jest wyszukiwana w ~/rpm/SOURCES/

Źródeł programu może być kilka. U nas występuje jeszcze Source1 - jest to dodatkowa dokumentacja składająca się z dwóch plików tekstowych zawierająca dodatkowe wskazówki po instalacyjne. Pierwotnie próbowałem zrobić to korzystając z mechanizmu Patch i polecenia:

diff -urN katalog_z_oryginałem katalog_z_poprawionym_oryginałem > źródła-powód.patch

opisanego w devel-manual (rozdział 1.2.2), ale mechanizm ten nie pozwala tworzyć nowych plików więc pozostało tylko wykonać dodatkowe źródła.

Pamiętajmy także aby w żadnym przypadku nie modyfikować ręcznie źródeł programu. Prawidłowy .spec powinien wykorzystywać natywne źródła, a wszelkie zmiany dokonujemy w %build, %install lub za pomocą patch'ów.

Sygnatura md5 po # jest wynikiem wykorzystania tzw. distfiles i na razie to musi nam wystarczyć. Distfiles omówimy gdy będziemy zapisywać do CVS PLD - czyli nieprędko ;-)

[...]
	 
Requires: apache >= 1.3.27-4
Requires: apache-mod_dir >= 1.3.27-4
Requires: php >= 4.0.3
Requires: php-mysql >= 4.0.3
Requires: php-pcre >= 4.3.1-4
Requires: php-common >= 4.3.1-4
Requires: mysql >= 3.23.2
Requires: mysql-client >= 3.23.56-1
Requires: sed
BuildArch: noarch
BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
		    
[...]

W 'Requires' podajemy zależności, czyli co musi być zainstalowane aby dany pakiet działał lub żeby wykonały się poprawnie polecenia wykonywane przez .spec (np. sekcja %post)

W 'BuildArch' architekturę pod który przeznaczony jest RPM - u nas jest to 'noarch' czyli bez żadnej konkretnej architektury - z moich obserwacji wynika że developerzy PLD omijają to pole - chyba że jest to właśnie 'noarch'.

'BuildRoot' jest bardzo ważnym tagiem - na szczęście występuje zawsze w takiej postaci jak u nas - a oznacza katalog w którym rpm będzie budował pakiet z sekcji %install naszego .speca.

[...] 
	
%define _mantisdir /home/services/httpd/mantis
# define _mantisdir /home/httpd/html/mantis
	  
%description
Mantis is a web-based bugtracking system.
	    
%description -l pl
Mantis jest systemem kontroli błędów opartym na interfejsie \
    WWW i MySQL. 

[...]

W tej części wykorzystujemy przydatną właściwość RPMa czyli definiowanie stałych. W naszym przykładzie '_mantisdir' jest katalogiem w którym będą zainstalowane pliki dla serwera WEB. Tutaj mała uwaga dotycząca komentarza '#' - Gdy definiujemy makro wtedy komentarz nie działa, dlatego usunęliśmy '%' przed słowem 'define' (możemy także użyć frazy '%%') czyli gdybyśmy napisali:

%define _mantisdir /home/services/httpd/mantis

# %define _mantisdir /home/httpd/html/mantis

To wtedy stała '_mantisdir' miała by wartość /home/httpd/html/mantis, mimo że nie taka jest nasz intencja - Nie muszę chyba wyjaśniać jakie to może spowodować problemy?

W '%description' opisujemy krótko charakterystykę pakietu, a niżej widzimy jak to zrobić dla opisu w języku polskim - później RPM wykorzystując zmienne locale wyświetla odpowiednią wersję językową 'description' gdy sobie tego od RPMa życzymy.

[...]
	 
%prep
%setup -q -a1
	   
[...] 

Od tego momentu skończyliśmy wypełniać dane preambuły. Sekcja %prep może wykonać skrypt potrzebny przed instalacją plików. My akurat nic przed instalacją robić nie musimy dlatego sekcja ta jest pusta.

Dalej jest '%setup -q -a1' - czyli rozpakowanie źródeł do katalogu zdefiniowanego wcześniej przez 'BuildRoot'. Dodatkowe parametry tego tagu wyłączają komunikaty przy rozpakowaniu '-q', a parametr '-a1' określa które źródła należy rozpakować. Po '%setup' możemy także korzystać z makra '%patch' który nakłada łatki na źródła. Umożliwia to taką modyfikację źródeł jakie tylko chcemy bez potrzeby zmian w samych źródłach (o czym pisaliśmy wcześniej).

[...]
	 
%install
rm -rf $RPM_BUILD_ROOT
install -d $RPM_BUILD_ROOT%{_mantisdir}
	    
cp -af *.php admin core css graphs images lang sql \
    $RPM_BUILD_ROOT%{_mantisdir}
	     
sed -e 's/root/mysql/g' config_inc.php.sample > \
    $RPM_BUILD_ROOT%{_mantisdir}/config_inc.php
      
[...]

Tak naprawdę w większości pakietów przed '%install' wykonywane jest makro '%build', które kompiluje nam źródła, a w najprostszej postaci wygląda tak:

%build %configure make

U nas nie ma potrzeby wykonywania żadnych kompilacji więc od razu wykonywana jest sekcja '%install'. Na początku czyścimy sobie katalog w którym będziemy instalowali nasz program (czyli 'fake root') - mimo że prawdopodobnie jest pusty - ale lepiej dmuchać na zimne. Potem dokonujemy instalacji pakietu przekazując mu w parametrze '-d' że docelowo ma być zainstalowany w 'fake root', ale same pliki pojawią się w naszym katalogu tymczasowym (TMPDIR), dlatego później za pomocą polecenia 'cp' kopiujemy pliki, jakie są potrzebne, do właściwego 'fake root' - zauważmy że pominęliśmy np. katalog 'doc'.

Następnie jeszcze za pomocą komendy 'SED' dokonujemy drobnej poprawki w pliku konfiguracyjnym mantisa - zamieniając domyślnego użytkownika MYSQL z 'root' na 'mysql'. Taką poprawkę mogliśmy wykonać wcześniej w sekcji '%prep' i tagu '%patch' ale przy tak małych poprawkach bardziej efektywniej jest to zrobić tutaj.

[...]
	 
%clean
rm -rf $RPM_BUILD_ROOT
	   
[...]

Tag '%clean' jest w .specach tworzonych dla PLD obowiązkowy i określa co należy zrobić gdy cały pakiet zostanie zbudowany. Tutaj mała uwaga - ten tag w tym miejscu nie oznacza że jest w tej chwili wykonany - jeżeli by tak było, to występujący później tag '%files' miałby niejakie problemy z nieistniejącymi już plikami. Czyli po poprawnym zbudowaniu pakietu, wykonywane jest makro '%clean', a w przypadku jakiegokolwiek błędu, nie jest - czyli rozpakowane i zainstalowane źródła pozostają. Umożliwia nam to np. diagnostykę w przypadku błędów podczas budowania pakietu.

[...]
	 
%post
if [ "$LANG" = "pl_PL" ]; then
#sed -e "s/= 'english';/= 'polish';/g" \
    %{_mantisdir}/config_defaults_inc.php > \
    #%{_mantisdir}/config_defaults_inc_PLD.php
#mv -f %{_mantisdir}/config_defaults_inc_PLD.php \
    %{_mantisdir}/config_defaults_inc.php
echo
echo "Mantis zapisany..."
echo "Więcej: /usr/share/doc/mantis-%{version}/PLD_Install_PL.txt.gz"
echo
else
echo
echo "Mantis loaded..."
echo "More: /usr/share/doc/mantis-%{version}/PLD_Install_EN.txt.gz"
echo
fi
		       
[...]

Tutaj mamy przykład co możemy zrobić z plikami, które będą instalowane po zbudowaniu pakietu. Makro '%post' wykonywane jest przez RPM podczas instalacji pakietu. Zakomentowane polecenia umożliwiają zmianę w zainstalowanym pliku 'config_defaults_inc.php' zgodnie z zawartością zmiennej locale 'LANG'. Później w zależności od tej zmiennej wyświetlany jest komunikat w języku PL lub EN.

Zadacie pytanie dlaczego część tych poleceń jest ''wyłączona" - otóż, później gdy dany .spec chcemy już udostępnić ogółowi zostanie on sprawdzony pod względem ''czystości rasowej'' :-) - W tym przypadku okazało się, że taka zmiana w plikach konfiguracyjnych, może spowodować kłopoty podczas np. zmiany użytkownika. Programy korzystające z 'locale' powinny odpowiednio reagować na zmiany 'locale' - np. po modyfikacji LANG na 'EN_en' zacząć pracować po angielsku - W naszym przypadku strona PHP nie zacznie pracować po angielsku, dlatego dodany został w/w komentarz, a w pliku 'PLD_Install_PL.txt.gz', który jest dodatkową instrukcją, co należy zrobić po instalacji pakietu RPM aby 'mantis' po uruchomieniu rozmawiał z nami po polsku.

[...]
	 
%files
%defattr(644,root,root,755)
%doc doc/* PLD_Install_PL.txt PLD_Install_EN.txt config_inc.php.sample
%dir %{_mantisdir}
%{_mantisdir}/admin/
%{_mantisdir}/core/
%{_mantisdir}/css/
%{_mantisdir}/graphs/
%{_mantisdir}/images/
%{_mantisdir}/lang/
%{_mantisdir}/sql/
%{_mantisdir}/account*
%{_mantisdir}/bug*
%{_mantisdir}/core.*
%{_mantisdir}/csv*
%{_mantisdir}/docum*
%{_mantisdir}/file*
%{_mantisdir}/history*
%{_mantisdir}/index*
%{_mantisdir}/jump*
%{_mantisdir}/log*
%{_mantisdir}/ma*
%{_mantisdir}/me*
%{_mantisdir}/news*
%{_mantisdir}/print*
%{_mantisdir}/proj*
%{_mantisdir}/set*
%{_mantisdir}/sig*
%{_mantisdir}/sum*
%{_mantisdir}/view*
				       
%config(noreplace) %{_mantisdir}/config_inc.php
%config(noreplace) %{_mantisdir}/config_defaults_inc.php
%exclude %{_mantisdir}/core/.cvsignore
				  
[...]

Dochodzimy powoli do finału :-). W sekcji tej określamy co, gdzie i jak ma zostać zainstalowane u użytkownika instalującego naszego RPMa. Tag %files jest bardzo ważny gdyż błędy spowodowane tutaj mogą uniemożliwić działanie pakietu u końcowego użytkownika. W 'podtagu':

%defattr(644,root,root,755)

określamy domyślne atrybuty instalowanych plików - możemy oczywiście określać atrybuty dla każdego pliku osobno.

Następnie w:

%doc doc/* PLD_Install_PL.txt PLD_Install_EN.txt config_inc.php.sample

określamy nasze pliki, które znajdą się w dokumentacji. Czyli katalog 'doc/' z katalogu 'TMPDIR' i pliki z 'SOURCE1' oraz 'config_inc.php.sample' zostaną spakowane i przy instalacji pakietu RPM umieszczone w domyślnym katalogu dokumentacji - w PLD jest to /usr/share/doc/...

I wreszcie w:

%dir %{_mantisdir}

nakazujemy podczas instalacji RPM'a stworzenie katalogu zgodnie ze stałą '%{_mantisdir}' i kopiujemy pliki jakie są poniżej tego tagu. Na początku nie wypisywałem wszystkich tych katalogów i plików indywidualnie, a po prostu użyłem frazy:

%{_mantisdir}

Jednak przy takiej konstrukcji i wykorzystaniu makra %config(noreplace), pojawi się błąd podczas budowania pakietu:

[...]
	 
RPM build errors:
File listed twice: /home/services/httpd/mantis/config_defaults_inc.php
File listed twice: /home/services/httpd/mantis/config_inc.php

Czyli dwa pliki miały podwójne znaczenie - występowały na liście do skopiowania i jako pliki konfiguracyjne. Dlatego trzeba niestety zrobić listę plików jak to my zrobiliśmy minus pliki, które znajdą się w makro '%config'. Samo makro '%config' pozwala szczególnie traktować pliki konfiguracyjnie podczas kasowania RPMa lub jego aktualizacji.

Ostatnie makro:

'%exclude %{_mantisdir}/core/.cvsignore'

nakazuje wyłączenie pliku z pakietu RPM - w tym przypadku jest to pozostałość po CVS mantisa.

I to już koniec naszej pracy. Po wykonaniu polecenia 'rpmbuild -ba mantis.spec' powinien nam zbudować się pakiet rpm i srpm. Zostaje jeszcze przetestowanie czy wszystkie pliki są tam gdzie chcieliśmy, czy mają odpowiednie prawa i czy pakiet działa tak jak powinien. Jeszcze ewentualne poprawki i musimy przepuścić naszą pracę przez zestaw adaptujący 'adapter.awk'.

Ściągamy go z CVSu:

$ cvs get SPECS/adapter.awk
U SPECS/adapter.awk
$

następnie zmieniamy nazwę pliku .speca dodając na końcu np. org i wykonujemy:

$ ./adapter.awk mantis.spec.org > mantis.spec
$

W wyniku tej operacji otrzymamy 'mantis.spec' który zostaje przystosowany do wymagań PLD. Zainteresowanych zmianami, zapraszam do przestudiowania 'nowego' .speca.

Teraz możemy szukać kogoś, kto umieści naszego .speca i źródła w repozytorium CVS PLD. Mamy do dyspozycji listę developerów: w mailu umieszczając załącznik z naszym .specem (oczywiście bez źródeł - lub jeżeli mamy jakieś własne źródła to umieszczamy je na jakieś stronie WWW lub innym ftp. i podajemy linka - źródła natywne powinny dać się ściągnąć z lokacji jaką umieściliśmy w naszym .specu.). Załącznik powinien być typu plain-text.

Można także spróbować na grupie IRC #PLD znaleźć ofiarę, która umieści naszą pracę w repozytorium.

Dobrze też w czasie nauki robienia .speców podglądać jak to robią inni - W repozytorium CVS jest naprawdę z czego wybierać. A my nabywając umiejętność czytania plików .spec możemy skupić się już tylko na odpowiednim ich napisaniu.

W końcu otrzymamy możliwość zapisu do CVS i wtedy czytamy następną część poradnika ''W krainie CVS''

 
&lt;- ->