summaryrefslogtreecommitdiff
blob: 29bf8a9334d9704b1f9716b1a2ece77154adba4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE sections SYSTEM "/dtd/book.dtd">

<!-- $Header: /var/cvsroot/gentoo/xml/htdocs/proj/it/devrel/handbook/hb-guide-eclass.xml,v 1.7 2010/08/26 14:40:37 scen Exp $ -->

<!-- The content of this document is licensed under the CC-BY-SA license -->
<!-- See http://creativecommons.org/licenses/by-sa/2.5 -->

<!-- This document was last synched to:
cvs://gentoo/gentoo/xml/htdocs/doc/en/eclass-howto.xml :: R1.17.  -->

<sections>
<version>1.0.3</version>
<date>2010-07-13</date>

<section>
<title>Introduzione alle eclass</title>
<subsection>
<title>L'idea che sta dietro le eclass</title>
<body>

<p>
Le eclass sono moduli di codice condiviso. Sono scritte in bash, hanno la stessa
sintassi dei normali ebuild e vengono derivate ('ereditate') dagli ebuild e
altre eclass, in modo da fornire impostazioni e funzionalità predefinite
attraverso molti ebuild simili tra loro.
</p>

<p>
Questo serve per assicurare il massimo riutilizzo del codice tra ebuild simili.
</p>

<p>
Questo capitolo mostra brevemente come scrivere una eclass incorporando i
trucchi standard e le tecniche usate nelle eclass esistenti.
</p>

</body>
</subsection>
<subsection>
<title>Esempio di una semplice eclass</title>
<body>

<p>
Questa è una eclass fittizia sourceforge.eclass, progettata per fornire
l'homepage e l'ubicazione dei download per i progetti presenti su
sourceforge.net:
</p>

<pre caption="Esempio: sourceforge.eclass">
# Copyright 2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License, v2 or later
# Author Dan Armak
# &lt;danarmak@gentoo.org&gt; &#36;Header: &#36;

# questa eclass imposta ${HOMEPAGE} e ${SRC_URI} ai valori standard per
# sourceforge.net - progetti ospitati.

HOMEPAGE="http://${PN}.sourceforge.net/"
SRC_URI="http://download.sourceforge.net/${PN}/${P}.tar.gz"
</pre>

<p>
Le prime quattro linee sono intestazioni (headers) proprio come quelle presenti
in ogni ebuild. Le seguenti due linee sono una breve descrizione dell'eclass. Il
resto del codice fa il lavoro effettivo - impostando SRC_URI e HOMEPAGE.
</p>

<p>
la maggior parte delle eclass va oltre l'impostare variabili e fornire funzioni
d'aiuto; esse contengono delle versioni predefinite di funzioni speciali degli
ebuild (src_unpack, src_compile e così via). Prima di scrivere una funzione
predefinita in una eclass, bisogna essere a conoscenza delle funzioni
predefinite già contenute in ebuild.sh, che saranno quelle che verranno eseguite
se non viene messa alcuna funzione nel proprio ebuild (non sempre tramite una
eclass); è usata spesso la predefinita src_unpack(). Se non è ancora fatto,
guardare le implementazioni predefinite in ebuild.sh.
</p>

<p>
Questo è tutto quello che serve sapere per scrivere delle eclass. Posizionare la
propria nuova eclass in <path>${PORTDIR}/eclass/</path>, e inserire questa linea
all'inizio del proprio ebuild:
</p>

<pre caption="Come ereditare le eclass">
inherit sourceforge
</pre>

<p>
A questo punto il contenuto delle eclass verrà derivato. Ricordarsi che tutte le
variabili o funzioni definite nella eclass possono essere sovrascritte
nell'ebuild, il cui codice viene eseguito dopo qualsiasi eclass. Pertanto,
bisogna cercare di mettere nelle proprie eclass il maggior numero possibile di
impostazioni predefinite e codice comune. Qualsiasi impostazione non standard o
modifica può quindi essere messa negli ebuild.
</p>

<p>
Si possono ereditare più eclass contemporaneamente tramite la sintassi:
</p>

<pre caption="Ereditare eclass multiple">
inherit eclass1 eclass2 [...]
</pre>

<p>
...ma guardare bene il loro ordine! Ricordarsi che le eclass possono ereditarsi
una dall'altra e sovrascriversi a vicenda le relative impostazione, per questo
bisogna fare molta attenzione quando si ha a che fare con eclass multiple, le
quali potrebbero influenzarsi l'una con l'altra.
</p>

<p>
Ora verranno spiegati tutti i trucchi nella scrittura delle eclass, prima di
passare alle attuali eclass in portage.
</p>

</body>
</subsection>
<subsection>
<title>inherit()</title>
<body>

<p>
Questa funzione risiede in ebuild.sh e gestisce l'ereditarietà (derivazione)
delle eclass. Viene invocata con una lista di nomi di eclass da ereditare:
inherit &lt;eclass1&gt; [eclass2 eclass3...].
</p>

<p>
Oltre all'effettiva derivazione dei file delle eclass, questa funziona imposta
le variabili ECLASS e INHERITED che vengono usate da portage per memorizzare i
gli orari (timestamp) di modifica delle eclass. La variabile INHERITED potrebbe
essere d'aiuto nella scrittura delle eclass: essa contiene una lista di tutte le
eclass ereditate (derivate) fino a quel punto, in ordine. In questo modo una
eclass può usare questa variabile per determinare se essa stessa viene chiamata
o meno da un'altra eclass.
</p>

</body>
</subsection>
<subsection>
<title>EXPORT_FUNCTIONS</title>
<body>

<p>
Delle buone funzioni predefinite di un'eclass possono essere spesso usate così
come sono; in questo modo l'ebuild conterrà pochissimo codice (che è una buona
cosa). Qualche volta, ciononostante, l'eclass non fa esattamente quello di cui
si ha bisogno. In questo caso si può scrivere una nuova funzione nel proprio
ebuild, sovrascrivendo la funzione definita nell'eclass. tuttavia questo
minimizzerà i benefici del riutilizzo del codice. Per cui si proverà ad
'estendere' la funzione dell'eclass.
</p>

<p>
Si supponga di voler estendere src_compile(). Si può scrivere una definizione
per src_compile() nel proprio ebuild, che includerà solo le parti mancanti della
funzione src_compile() presente nell'eclass. A questo punto si invocherà la
funzione src_compile() dell'eclass dall'interno del codice della propria
funzione personalizzata.
</p>

<p>
Tuttavia, se si crea una nuova funzione chiamata src_compile(), bash si
dimenticherà quella vecchia e non sarà più capace di chiamarla! Qui entra in
gioco la macro EXPORT_FUNCTIONS.
</p>

<p>
Ora verrà analizzato momentaneamente un altro problema. Si supponga che entrambe
le eclass foo.eclass e bar.eclass definiscano src_compile(). Ereditando sia foo
che bar si otterrà una diversa funzione src_compile() in base all'ordine in cui
esse vengono ereditate. Questo è normale, in quanto si suppone di tener conto
dell'ordine dell'ereditarietà. Ma si potrebbe voler invocare entrambe le
dichiarazioni di src_compile() esplicitamente.
</p>

<p>
Così, ogni eclass aggiunge un prefisso alle funzioni che definisce . Per
esempio, foo.eclass definirà una funzione chiamata foo_src_compile(), e
rispettivamente bar.eclass definirà bar-src_compile(). In questo modo, l'ebuild
può chiamare entrambe le funzioni sapendo cosa otterrà.
</p>

<p>
Tuttavia, si può voler disporre di una qualche funzione predefinita chiamata
semplicemente src_compile(), altrimenti l'ebuild dovrà definirne una. La macro
EXPORT_FUCTIONS risolve sia questo problema che quello presentato prima.
</p>

<pre caption="EXPORT_FUNCTIONS() (da ebuild.sh)">
EXPORT_FUNCTIONS() {
    while [ "$1" ]; do
        eval "$1() { ${ECLASS}_$1 ; }" &gt; /dev/null
        shift
    done
}
</pre>

<p>
La funzione inherit() imposta ${ECLASS} con il nome dell'eclass prima di
derivarla. Alla fine l'eclass chiama EXPORT_FUNCTIONS(), passando come parametri
la lista delle funzioni predefinite che fornisce. Per esempio, se si chiama
</p>

<pre caption="Esempio di chiamata a EXPORT_FUNCTIONS">
EXPORT_FUNCTIONS src_compile src_install
</pre>

<p>
allora EXPORT_FUNCTIONS chiamerà eval() sulla seguente stringa:
</p>

<pre caption="Risultato di EXPORT_FUNCTIONS">
src_compile() { foo_src_compile ; }
src_install() { foo_src_install ; }
</pre>

<p>
Ora, qualsivoglia eclass venga ereditato per ultimo, definirà la funzione
predefinita src_compile(), ma, se necessario, entrambe le funzioni potranno
essere chiamate direttamente dall'ebuild.
</p>

<p>
È possibile anche estendere la funzione predefinita src_compile() chiamando la
funzione dell'eclass dall'interno della propria funzione. In questo modo si
dovrà usare il nome completo della funzione predefinita foo_src_compile. Un
esempio:
</p>

<pre caption="Estendere le funzioni predefinite dell'eclass nel proprio build">
#in foo.eclass:
foo_src_compile() {
        [qui codice predefinito]
}

EXPORT_FUNCTIONS src_compile

#fine codice eclass

#in un ebuild:

inherit foo

src_compile() {
        [qui codice personalizzato]
        foo_src_compile
        [altro codice personalizzato]
}
</pre>

</body>
</subsection>
<subsection>
<title>Sezioni delle funzioni</title>
<body>

<p>
A volte, estendere le funzioni predefinite eseguendo il codice prima e dopo non
è abbastanza flessibile. Quando  si ha a che fare con funzioni lunghe e
complesse, spesso ci sarà la necessità di voler eseguire il proprio codice
personalizzato all'interno di queste funzioni.
</p>

<p>
Le sezioni delle funzioni provvedono a fornire una maggiore flessibilità,
richiesta in questo caso. Esse suddividono le funzioni in sezioni e permettono
di eseguire il codice tra due sezioni qualsiasi.
</p>

<p>
L'implementazione è semplice. Viene presa come esempio la funzione src_compile()
da base.eclass. (Nota: non esiste più, ma è un buon esempio :-) Essa è fatta
così:
</p>

<pre caption="Esempio da base.eclass di origine">
base_src_compile() {
    econf || die
    emake || die
}
</pre>

<p>
Qui c'è la stessa funzione, divisa in sezioni:
</p>

<pre caption="La stessa funzione divisa in sezioni.">
base_src_compile() {

    [ -z "$1" ] &amp;&amp; base_src_compile all

    while [ "$1" ]; do
        case $1 in
            configure)
                econf || die;;
            make)
                emake || die;;
            all)
                base_src_compile configure make;;
        esac
    shift
    done

}
</pre>

<p>
Il codice è stato suddiviso in due sezioni: <c>configure</c> e <c>make</c>.
In questo semplice esempio, esse corrispondono ai due comandi presenti nella
funzione originale.
</p>

<p>
Nel centro della nuova funzione c'è un blocco while;case...esac;shift;done.
Questo blocco esegue un controllo di corrispondenza dei parametri della funzione
con i nomi di sezioni definiti ed esegue le corrispondenti linee di codice.
</p>

<p>
Il caso speciale <c>all</c> chiama la stessa funzione ricorsivamente con una
lista ordinata di sezioni. È compito dello sviluppatore mantenere questa lista.
</p>

<p>
La prima linea del blocco dice che una chiamata senza parametri dovrà essere
trattata come una chiamata con il singolo parametro <c>all</c>. Come si può
notare, questa funzione è molto ricorsiva.  Notare, però, che anche la chiamata
<c>base_src_compile configure all make</c> è legale; essa eseguirà
<c>base_src_compile configure configure make make</c>.
</p>

<p>
A questo punto nel proprio ebuild (o eclass) che eredita da base.eclass, si avrà
la funzione fittizia src_compile, la quale chiamerà base_src_compile senza
parametri. Questo fa eseguire base_src_compile <e>all</e>, che significa
eseguire ogni sezione. Si può lasciarla così com'è. Se si vuole estenderla, è
possibile definire una nuova funzione src_compile e chiamare base_src_compile
una sezione alla volta:
</p>

<pre caption="Usare la funzione src_compile() sezionata">
src_compile() {
    esegui_mio_codice1
    base_src_compile configure
    esegui_mio_codice2
    base_src_compile make
    esegui_mio_codice3
}
</pre>

<p>
Come si può vedere, le sezioni aggiungono flessibilità in quanto ora è possibile
inserire codice tra le due sezioni, come anche poterle eseguire in un ordine
diverso oppure eseguire solo alcune delle sezioni fornite. Questo permette un
maggiore riutilizzo complessivo del codice.
</p>

</body>
</subsection>
<subsection>
<title>Le funzioni debug-print-*</title>
<body>

<p>
Ci sono molte altre funzioni fornite da ebuild.sh. Esse aggiungono alle eclass
un output prolisso in fase di debug, per permettere di seguire più facilmente la
loro esecuzione senza dover leggere i lunghi messaggi forniti dal metodo di
debug di bash. Tutte le eclass dell'autore di questa guida usano molto spesso
queste funzioni.
</p>

<p>
debug-print() stampa semplicemente tutti i suoi parametri con il prefisso
'debug:'. Viene chiamata ogni volta che c'è qualcosa di interessante da mettere
nel log del debug.
</p>

<p>
debug-print-function() stampa 'debug: entering function $1, parameters: $2
[$3 ....]. Viene chiamata all'inizio di una funzione.
</p>

<p>
debug-print-section() mostra 'debug: now in section $1'. Viene chiamata
all'inizio di una sezione di funzione.
</p>

<p>
L'output di debug, normalmente va in ${T}/eclass-debug.log. È possibile
impostare la variabile d'ambiente ECLASS_DEBUG_OUTPUT (in make.globals/conf o
nell'ambiente) e l'output sarà inviato pure lì. Si può anche impostarla con lo
speciale valore 'on', in modo da mostrare l'output insieme a tutti gli altri
messaggi di emerge.
</p>

<p>
Ecco come aggiungere delle tipiche dichiarazioni di output di debug alla
precedente funzione di esempio:
</p>

<pre caption="Aggiungere dichiarazioni di debug">
base_src_compile() {

    debug-print function
    [ -z "$1" ] &amp;&amp; base_src_compile all

    while [ "$1" ]; do
        case $1 in
            configure)
                debug-print-section configure
                ./configure || die;;
            make)
                debug-print-section make
                make || die;;
            all)
                debug-print-section all
                base_src_compile configure make;;
        esac
    shift
    done

    debug-print "${FUNCNAME}: il risultato è ${RESULT}"
}
</pre>

<p>
${FUNCNAME} è una varibile incorporata in bash che restituisce il nome corrente
delle funzione.
</p>

</body>
</subsection>
<!-- <subsection>
<title>newdepend()</title>
<body>

<p>This ebuild.sh function simply adds all its parameters to both DEPEND and
RDEPEND, saving you the trouble of writing and maintaining two lists of
dependencies.
</p>

<p>
If called with a special parameter, it adds predefined dependencies. I don't
think this is very elegant (anymore), I rather prefer explicit dependancies now;
so you can consider this slightly deprecated ;-)
</p>

<p>
These special parameters exist as of now:
</p>
<p>newdepend /autotools: add sys-devel/autoconf sys-devel/automake
sys-devel/make to DEPEND (but not RDEPEND).
</p>

<p>
newdepend /c: add virtual/glibc sys-devel/ld.so to both DEPEND and RDEPEND.
Also, add sys-devel/gcc to DEPEND.
</p>

</body>
</subsection> -->
</section>
<section>
<title>Eclass esistenti</title>
<subsection>
 <title>eclass-manpages</title>
<body>

<p>
È possibile effettuare l'emerge di app-portage/eclass-manpages per ottenere la
documentazione delle eclass esistenti.
</p>

</body>
</subsection>
</section>
</sections>