Introducere în Debian Packaging

Sesiune de Training Debian Women IRC organizată de Lars Wirzenius, 18-Nov-2010

Acesta este un tutorial introductiv pentru crearea de pachete Debian: nu intra în detaliile de realizare ale Debian packaging, dar va arată cum se poate face un pachet Debian pentru un software care este simplu de împachetat.

Pentru acest scop va fi folosita doar comanda dh din debhelper 7.

Cerinţe

Acest tutorial porneşte de la premisa că:

Cerinţe tehnice:

Trei Concepte Centrale

Cele Trei Concepte centrale sunt upstream tarball (arhiva upstream), source package (pachet-sursă) şi binary package (pachet binar). Majoritatea oamenilor împachetează software scris de altcineva (care este denumit dezvoltator “upstream” (“upstream developer”) . Acest dezvoltator va face o lansare a software-ului şi rezultatul concret al acesteia va fi fişierul-arhivă al sursei “upstream", sau arhiva (“tarball”).

O arhivă este fişierul .tar.gz sau .tgz realizat de upstream (tarball este un fel de jargon al calculatoarelor). Din această arhivă, Debian creează un pachet. Odata ce avem arhiva upstream, următorul pas este să creăm pachetul sursă Debian , iar apoi de aici pachetul binar Debian (ceea ce se va instala de fapt va fi acest pachet binar).

Pachetul sursă conţine, în forma să cea mai simpla, 3 fişiere:

  1. Arhiva upstream , redenumită pentru a respecta regula sistemului
  2. Un fişier patch . cu orice schimbari facute la sursa upstream , plus toate fişierele create pentru pachetul Debian . Acesta are o terminaţie .diff.gz
  3. Un fişier descriptiv (cu terminaţia .dsc) care specifică cele doua fişiere de mai sus.

La prima vedere sună mai complicat decat ar fi necesar : poate ca ar fi mai simplu să avem totul intr-un singur fişier. Totusi în practica s-a dovedit ca păstrarea arhivei upstream separată de modificarile specifice salvează foarte mult spaţiu de pe disk şi laţime de banda. Totodată este mai usor de ţinut evidenta modificarilor pentru Debian.

Etapele (fluxul de lucru) pentru crearea pachetelor

Etapele pentru crearea pachetelor sunt de obicei urmatoarele:

  1. redenumim arhiva upstream pentru a respecta regulile specifice de atribuire a numelor.
  2. despachetam arhiva upstream
  3. adaugam fişierele Debian ce vor face parte din paceht (intr-un subdirector numit debian), şi facem eventual alte modificari necesare
  4. construim pachetul sursă
  5. construim pachetul binar
  6. încărcam sursa şi pachetele binare în Debian.

Pentru acest tutorial Lars a folosit această arhivă

Pasul 1-redenumirea arhivei

Instrumentele Debian pentru crearea pachetelor pornesc de la premisa că arhiva upstream are un nume alcătuit după o anumită regulă.

Numele este alcătuit astfel : numele pachetului sursă, liniuţa de subliniere (“underscore”), numărul versiunii upstream, toate acestea urmate de .orig.tar.gz. Numele pachetului sursă poate conține litere (doar litere mici!), cifre şi liniute. Sunt permise şi alte câteva caractere.

Dacă dezvoltatorul upstream a folosit un nume corespunzător unui pachet-sursă, atunci îl puteți folosi așa cum este. În caz contrar, efectuați modificările minime necesare pentru nume, astfel încât să respecte regulile Debian . În cazul prezentat aici , dezvoltatorul upstream a ales un nume potrivit , "hithere", deci nu există probleme în privinţa lui.

Ar trebui ca la final să avem un fişier numit hithere_1.0.orig.tar.gz.

Să remarcăm că numele conţine liniuta de subliniere, nu un “minus”. Acest lucru este important ; instrumentele de împachetare fac diferența între ele.

# mv hithere-1.0.tar.gz hithere_1.0.orig.tar.gz

Pasul 2-despachetarea arhivei

Ar trebui să avem acum un director denumit "hithere-1.0". În general , sursele ar trebui să fie puse intr-un director denumit dupa numele pachetului sursă şi versiunea upstream , cu o craţimă (un minus, nu bara de jos) între ele.

Această regulă trebuie respectată pentru ca instrumentele de împachetare să funcționeze corect.

În acest caz , upstream a fost din inteligent şi a creat creat pachetul arhivă în subdirectorul corespunzător.

Pasul 3- adaugarea fişierelor din pachetul Debian

Toate aceste fişiere vor fi plasate în subdirectorul debian/ din cadrul structurii arborescente a sursei.

# cd hithere-1.0
# mkdir debian

Exista un set de fişiere care sunt neaparat necesare. Să le verificam în ordine.

debian/changelog

Primul fişier este debian/changelog. Aceste este jurnalul modificarilor din pachetul Debian.

Nu este necesar să conţina toate modificarile din codul upstream, desi poate ar fi util pentru utilizatori să poata vedea rezumatul acestor modificari. Deoarece suntem la prima versiune , nu este nimic în jurnal.Totusi trebuie să cream o intrare în jurnalul de modificari, deoarece instrumentele de împachetare citesc anumite informaţii din aceste jurnale. Cel mai important este faptul ca ele citesc versiunea pachetului.

debian/changelog are un format specific. Cel mai simplu mod de a-l crea este folosind instrumentul dch

# dch --create -v 1.0-1 --package hithere

Din aceasta va rezulta un fişier de genul :

hithere (1.0-1) UNRELEASED; urgency=low

  * Initial release. (Closes: #XXXXXX)

 -- Lars Wirzenius <liw@liw.fi>  Thu, 18 Nov 2010 17:25:32 +0000

Cateva observaţii :

versiunea. Partea 1.0 este versiunea upstream.Partea -1 este versiunea Debian: prima versiune a pachetului Debian de la versoinea upstream 1.0. Dacă pachetul Debian are o eroare și aceasta se rezolvă dar versiunea upstream rămâne aceeaşi , atunci următoarea versiune a pachetului se va numi 1.0-2. Apoi, 1.0-3, şi tot aşa.

debian/compat

Acest fişier ar trebui să conţina numărul 7. Este un număr magic. Nu puneţi nici un alt număr acolo. debian/compat specifică nivelul de compaţibilitate pentru instrumentul debhelper. Nu trebuie să intelegem în profunzime acum ce anume reprezinta aceste lucuri.

debian/control Fişierul de control descrie sursa şi pachetul binar şi da cateva informaţii despre ele, cum ar fi numele lor, informaţii despre cel ce intreţine pachetul, etc. Mai jos avem un exemplu pentru unui asemenea fişier.

Source: hithere
Maintainer: Lars Wirzenius <liw@liw.fi>
Section: misc
Priority: optional
Standards-Version: 3.9.0
Build-Depends: debhelper (>= 7.3.8)

Package: hithere
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: greet user
 hithere greets the user, or the world.

Aici sunt mai multe informaţii necesare, dar le putem trata pentru moment ca fiind “magice”. Deci ,în debian/control sunt doua paragrafe.

Primul descrie pachetul sursă: "Source:"

"Maintainer:"

"Build-Depends:"

Al doilea paragraf descrie pachetul binar construit din aceasta sursă.De fapt , pot fi mai multe pachete binare construite din aceeasi sursă.

"Package:"

"Architecture:"

: i386 pentru procesoare 32-bit Intel, amd64 pentru procesoare pe 64 biti , armel pentru procesoare ARM , etc. Debian lucrează pe aproximaţiv o duzila de arhitecturi de calculator în total , deci suportul din partea acestor arhitecturi este crucial. "Architecture:" camp care poate conţine numele unor arhitecturi particulare, dar de obicei conţine una sau doua valori speciale.

"any" (ceea ce vedem în exemplul dat) inseamna ca pachetul poate fi contruit pentru orice arhitectura. Cu alte cuvinte , codul a fos scris portabil , deci nu cere prea multe particularitaţi în privinţa hardware-ului. Totusi , pachetul binar va trebui să fie construit pentru fiecare arhitectura separat.

"all"

"Depends:"

"Description:"

debian/copyright

un fişier gol.

debian/rules

        #!/usr/bin/make -f
%:
        dh $@

În realitate debian/rules poate să fie un fişier complicat. Totusi, comanda dh din versiunea 7 a debhelper face posibila păstrarea simpla a acestuia în multe cazuri.

debian/source/format Ultimul fişier de care avem nevoie este debian/source/format şi el ar trebui să conţina numărul versiunii "1.0".

Acesta este numărul versiunii pentru formatul pachetului sursă , şi chiar dacă se intampla să fie acelasi ca şi versiunea upsream , aceasta este doar o coincidenta.

Pasii 4&5- construim pachetul

Acum putem construi pachetul. Comanda care face acest lucru este:

debuild -us -uc

Sunt mai multe comezi pe care le-am putea folosi pentru aceasta , dar o vom folosi pe aceasta. Dacă executaţi comanda , veţi optine un output similar cu acesta :

make[1]: Entering directory `/home/liw/debian-packaging-tutorial/x/hithere-1.0'
install hithere  
/home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/local/bin
install: cannot create regular file  
`/home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/local/bin': No such  
file or directory
make[1]: *** [install] Error 1
make[1]: Leaving directory `/home/liw/debian-packaging-tutorial/x/hithere-1.0'
dh_auto_install: make -j1 install  
DESTDIR=/home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere returned exit code 2
make: *** [binary] Error 29
dpkg-buildpackage: error: fakeroot debian/rules binary gave error exit status 2
debuild: fatal error at line 1325:
dpkg-buildpackage -rfakeroot -D -us -uc failed

Ceva nu a functionat bine. Aceasta se intampla frecvent. Desi ne straduim să cream fişierele debian/* , aproape intotdeauna ramane ceva ce n-am inteles corect. Deci , ceea ce n-a functionat bine este partea urmatoare:

install hithere /home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/local/bin

Makefile upstream incearca să instaleze programul compilat intr-o locaţie gresita.

Sunt mai multe lucruri de remarcat aici : mai intai cate ceva despre cum functionează împachetarea Debian.

Când programul a fost construit şi este “instalat”, el nu se instalează în /usr sau /usr/local ca de obicei , ci undeva în structurile subdirectorului debian/

Cream un subset al intregului sistem de fişiere în debian/hithere , şi apoi il plasam în pachetul binar. Deci partea .../debian/hithere/usr/local/bin este corecta , cu exceptia faptului ca nu ar trebui să se instaleze sub usr/local , ci direct sub usr.

Trebuie să facem ceva ca să se instaleze în locaţia corecta (debian/hithere/usr/bin)

Modul corect pentru a rezolva aceasta este să schimbam debian/rules astfel încăt ele să precizeze pentru Makefile unde să faca instalarea :

%:
        dh $@

override_dh_auto_install:
        $(MAKE) DESTDIR=$$(pwd)/debian/hithere prefix=/usr install

Este din nou putina magie , şi ca să o intelegi , va trebui să stii cum functionează Makefiles, precum şi diverse stadia ale executiei lui debhelper.

Pentru moment , vom rezuma prin a spune ca exista o comanda pe care debhelper o derulează, comanda care supraveghează instalarea fişierelor upstream, şi acest stadiu se numeste dh_auto_install.

Trebuie să trecem peste acest stadiu şi facem aceasta cu o regula în debian/rules numita override_dh_auto_install.

Ultima linie din noul debian/rules este putin asemanatoare tehnologiei anilor 1970, pentru a invoca upstream Makefile din debian/rules cu argumentele corecte.

Să incercam să construim din nou. Tot nu functionează!

install hithere /home/liw/debian-packaging-tutorial/x/hithere-1.0/debian/hithere/usr/bin

Am incercat să instalam în locul correct, dar locaţia nu exista. Pentru a remedia situaţia, trebui să ii spunem instrumentului de împachetare să creeze initial directorul.

Ideal ar fi ca upstream Makefile să creeze directorul el insusi , dar în acest caz dezvoltatorul nu a prevazut acest lucru.

Instrumentele de împachetare (în special debhelper) asigura un mod de a face acest lucru.

usr/bin
usr/share/man/man1

Now running lintian...
W: hithere source: out-of-date-standards-version 3.9.0 (current is 3.9.1)
W: hithere: copyright-without-copyright-notice
W: hithere: new-package-should-close-itp-bug
W: hithere: wrong-bug-number-în-closes l3:#XXXXXX
Finished running lintian.

Aceastea ar trebui să fie în final rezolvate , dar nici una dintre ele nu pare a fi o problema care să ne impiedice să incercam pachetul. Deci le ignoram pentru moment.

Verificam în directorul-parinte, cautand pachetul care a fost construit.

# ls .. 

hithere-1.0                  hithere_1.0-1_amd64.deb  hithere_1.0.orig.tar.gz
hithere_1.0-1_amd64.build    hithere_1.0-1.diff.gz
hithere_1.0-1_amd64.changes  hithere_1.0-1.dsc

Urmatoarea comanda va instala pachetul pe care dumneavoastra tocmai l-am construit.NU il executam pe un calculator pentru care ne ferim să avem probleme.

Masini virtuale sunt un loc bun pentru a face dezvoltarea.

# sudo dpkg -i ../hithere_1.0-1_amd64.deb

Şi iata rezultatul afisat :

liw@havelock$ sudo dpkg -i ../hithere_1.0-1_amd64.deb
[sudo] password for liw: 
Selecting previously deselected package hithere.
(Reading database ... 154793 files and directories currently installed.)
Unpacking hithere (from ../hithere_1.0-1_amd64.deb) ...
Setting up hithere (1.0-1) ...
Processing triggers for man-db ...
liw@havelock$ 

Cum testam pachetul ? Putem lansa comanda.

# hithere

Functionează! Dar nu este perfect. Nu uitaţi, lintian a afisat cateva probleme, debian/copyright e gol , etc.

Avem un pachet care functionează , dar nu este încă de o calitate inalta, conform asteptarilor pentru un pachet Debian.

Concluzii

Odata ce aţi generat propriile pachete, probabil veţi dori să invataţi cum să setaţi propriile apt repository, astfel încăt pachetele să fie usor de instalat. Cel mai bun instrument pe care il cunosc eu este reprepro.

Pentru testari ulterioare ale pachetului, puteţi cauta instrumental numit piuparts. (Initial l-am scris eu, asa ca e perfect, nu are niciodată erori. aaa...)

Şi, în fine, dacă faceţi modificari pe sursă upstream, va trebui să invataţi să lucraţi cu instrumentul numit quilt.

Mai exista şi alte lucruri interesante, în pagina http://www.debian.org/devel/.

Întrebari şi răspunsuri

Întrebare: Pot crea un pachet multi-arch?

Răspuns: Nu cred cã Debian suportã pachetele multi-arch încã, dar mă voi ocupa de pachetele "Architecture: all".

Întrebare:Vă rog să explicaţi împachetarea acelor pachete care sunt deja în formă binară ca de exemplu nvidia blob sau likewise.

Răspuns:Pentru pachete binare blob , luaţi în considerare arhiva ca şi cum ar fi pachetul-sursă şi evitaţi să îl compilaţi de la sursă.

Întrebare: Există ceva asemănător cu PPA în S.O Ubuntu?

Răspuns: Debian nu executã un serviciu PPA ca şi Ubuntu, dar toate instrumentele/utilitarele sunt la îndemâna dvs.,doar că este foarte mult de lucru pentru o singură persoană

Întrebare: Trebuie să reîmpachetăm arhiva orginală chiar dacă aceasta nu conţine un folder denumit corect foo-1,0?

Răspuns: Nu mai trebuie sã o reîmpachetaţi. Ele au fost necesare cu mai mulţi ani în urmã, dar acum comanda dpkg-source-x va denumi directorul în mod corespunzător (dacă este necesar)

Întrebare: De ce văd pachetele oficiale DEB în var/cache/apt/arhive fãrã changelog şi fişierele compat?

Răspuns: Pachetele DEB sunt pachete binare. Changelog este inclusã în configuraţie (sub un alt nume),fişierul compat fiind numai pachetul sursă.

Întrebare: Liw a spus cã fişierul compat ar trebui să conţina numărul magic 7.Presupun că asta semnifică atâtea documente char, câte sunt produse de 'echo 7 >debian/compat' ?

Răspuns: Da, este suficient un singur caracter 7 pentru a avea în Debian/Compat

Întrebare:Am auzit de un format specific pentru numerele de revizie Debian.

Răspuns:Cred că te referi la formatul "native package"(în care numărul versiunii ar fi numai 1.0, nu 1.0-1) sau la formatul "non-maintainer upload" - în acest caz sunt prea multe pentru această sesiune ca să iasă corect în toate cazurile dar "1.0-1.1" ar fi un exemplu.

ÎntrebareCând se derulează"dpkg-source -x" ? Se face manual ?

Răspuns:"dpkg-source -x" este comanda care despachetează pachetul-sursă Debian după ce a fost deja construit(de obicei de altcineva.De obicei nu se derulează când se crează pachetul.

Întrebare:Cum poate cineva să determine pachetele necesare folosirii de Build-Depends?

Răspuns:De obicei eu fac asta prin a)încercare şi eroare b) citind sursa programului. Cam amândouă sunt necesare.

Întrebare:pot să construiesc un pachet pentru armel din propriul i386 , şi daca da pot sa o fac simplu ?

Răspuns:Ar rezulta o compilare încrucişată şi mă îndoiesc de existenţa vreunui mod uşor de a-l face.Există instrumente pentru aceasta , dar nu îmi sunt familiare din păcate.

Întrebare:Care este diferenţa dintre Depends şi Build Depends , şi în ce situaţii trebuie sa folosim numai Depends sau numai Build Depends?

Răspuns:Build Depends sunt necesare numai în timpul construirii pachetului , în timp ce se compilează şi testarea lui e în derulare.Depends e necesar numai cand pachetul este în folosinţă , după ce a fost instalat.Unele lucruri ar putea fi simultan construite şi dependenţe de derulare şi în acest caz va trebui să le pui în ambele Build Depends şi Depends

De exemplu , dacă un pachet conţine un script PHP dar nu se derulează în timp ce pachetul este construit , atunci PHP va ajunge în Depends nu şi în Build Depends.

Totuşi, dacă scriptul PHP este folosit numai ca să derulăm un test şi nu este inclus în pachetul binar atunci va ajunge numai în Build Depends nu şi în Depends.

Întrebare:Există posibilitatea de a avea un Build Depends care nu are un Depends corespunzător?

Răspuns:Dependencies şi Build Dependencies sunt două lucruri diferite şi este foarte OK (din punctul de vedere al instrumentelor de împachetare) sa aveţi numai unul dintre ele , dar se poate şi amandouă.

Întrebare:Dacă vreau să creez un NMU , ar trebui sa îmi scriu numele în câmpul Uploader , ân câmpul Maintainer sau în nici unul ?

Răspuns:În nici unul , dar prima linie din changelog ar trebui să fie "Non-maintainer upload"

Întrebare:Când construiesc un pachet cu un câmp "Architecture: all" , o parte din fişierul rezultat (b.build, .changes) tot au arhitectura construită în nume.Este corect aşa ?

Răspuns:Da,este corect , nu trebuie să te îngrijorezi în această privinţă

Întrebare:Există un alt pachet pentru pachetul-sursă sau este unul şi acelaşi cu pachetul binar ? Voi genera şi întreţine două pachete(binar şi sursă)

Răspuns:Editezi pachetul-sursă şi apoi execuţi o comandă (pe care o sa ţi-o spun imediat)pentru a genera pachetul binar din pachetul sursă.

Întrebare:Nu îmi este clar daca opţiunile "Architecture" vor avea efect asupra pachetului-sursă (procesul de generare ) sau asupra pachetului binar (instalare şi execuţie).

Răspuns:Câmpul "Architecture" precizează celui care generează pachetului dacă este oportună generarea pachetlui pe o arhitectură particulară astfel încât dacă se precizează doar pe i386 atunci nu este oportună generarea pe amd64

Întrebare:acest exemplu debian/rules conţine numai #!make -f , ce facem cu ./configure sau cmake sau scons sau orice altă parte?

Răspuns: dh are o mulţime de euristică , astfel încât un pachet cu un script/configure sau unul cu alte modalitaţi uzuale de generare a pachetelor va putea fi generat fara alte adăugări.

Întrebare:euristica este benefică , dar ce se întâmplă dacă trebuie să trecem --with-something-special pentru a configura sau argumente cmake, poate euristica să trateze acele pachete sursă care necesită /waf şi alte instrumente pentru a fi generate ?

Răspuns:Îmi place răspunsul lui dapal: folosind dh7 dacă vrei să transferi ceva lui /configure , faci ceva de genul override_dh_auto_configure <TAB>dh_auto_configure -- --your-params gh are un mecanism de extensie/suprascriere care permite suprascrierea anumitor părţi. E uşor de folosit dacă ai citit documentaţia.

Întrebare: Unde găsim documentaţie pentru a suprascrie părti din debhelper 7 ?

Răspuns: dh rulează o secventă specifica de comenzi pentru a genera un pachet.Fiecare comandă este numită dh_something şi fiecare astfel de comandă poate fi suprascrisă avand o intrare debian/rules numită override_dh_something.

Adaugă opţiunea --no-act la comanda dh în debian/rules pentru a vedea ce comenzi lansează.Trebuie apoi să citiţi pagina din manual referitoare la acea comandă pentru a vedea dacă o puteţi configura.(via fişier cum ar fi debian/hithere.dirs) sau dacă trebuie suprascrisă.

Întrebare:De unde lansezi de obicei comenzile? Din interiorul directorului hithere-1.0?Ar trebui sa existe un director extern numit hithere(fără număr)?

Răspuns:Întotdeauna lansez comenzile în hithere-1.0 şi deobicei am un director cu un nivel mai sus care a apelat hithere , dar directorul părinte nu e necesar , e doar mai ordonat astfel încăt nu se amestecă fişiere din proiecte diferite.

Întrebare:Am un upstream care necesită un qmake (foloseste Qt) inaine de make.Pot sa il adaug la debian/rules ? Cum anume ?

Răspuns:dbhelper suportă qmake începând cu varianta 7.4.12 (aşa că nu mai trebuie nimic în plus) . Înainte de asta trebuie o override_dh_auto_configure :\n\tqmake

Întrebare:cum arată o metoda bună pentru a actualiza un pachet la o nouă versiune upstream ?

Răspuns:Nu sunt sigur ca e cea mai bună metodă , dar în principiu despachetezi sursa upstream într+un nou director , copiezi directorul debian/* din vechiul pachet , actualizezi debian/changelog ("dch -v 1.2.3-4")şi încerci să generezi , corectezi tot ce trebuie . Nu e cea mai bună metoda dar te scuteşte de a trebui să înveţi prea mult şi e un subiect prea complex pentru acest moment.

Întrebare:Am un pachet debian generat care depinde de alte câteva pachete.Singurul lucru pe care îl face pachetul este acela de a configura celelalte pachete astfel încât să satisfacă cerinţele anumitor persoane. În acest scop el face de asemenea câteva schimbări critice în sistem cum ar fi activarea network routing în kernel etc.. Există vreo regula privind ceea ce poate sau nu să facă un pachet oficial ? Poate un asemenea pachet să primească un pachet oficial?

Răspuns:http://www.debian.org/doc/debian-policy/ este cel mai bun set de reguli scris pentru a preciza permisiunile pe care le are un pachet Debian sau ceea ce este obligatoriu să facă.

Pachetelor Debian nu le este permis să modifice configurările altor pachete decât dacă acele pachete oferă o interfaţă documentată în acest scop.

Alte informaţii de interes

* http://www.debian.org/devel/

* http://www.debian.org/doc/debian-policy/

* http://liw.fi/manpages/