%% build.tex
%%
%% Copyright (C) 1999-2007 Simone Piccardi.  Permission is granted to copy,
%% distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
%% with no Front-Cover Texts, and with no Back-Cover Texts.  A copy of the
%% license is included in the section entitled "GNU Free Documentation
%% License".
%%

\chapter{Gli strumenti di ausilio per la programmazione}
\label{cha:build_manage}

Tratteremo in questa appendice in maniera superficiale i principali strumenti
che vengono utilizzati per programmare in ambito Linux, ed in particolare gli
strumenti per la compilazione e la costruzione di programmi e librerie, e gli
strumenti di gestione dei sorgenti e di controllo di versione.

Questo materiale è ripreso da un vecchio articolo, ed al momento è molto
obsoleto.


\section{L'uso di \texttt{make} per l'automazione della compilazione}

Il comando \texttt{make} serve per automatizzare il processo di costruzione di
un programma ed effettuare una compilazione intelligente di tutti i file
relativi ad un progetto software, ricompilando solo i file necessari ed
eseguendo automaticamente tutte le operazioni che possono essere necessarie
alla produzione del risultato finale.\footnote{in realtà \texttt{make} non si
  applica solo ai programmi, ma in generale alla automazione di processi di
  costruzione, ad esempio anche la creazione dei file di questa guida viene
  fatta con \texttt{make}.}


\subsection {Introduzione a \texttt{make}}

Con \texttt{make} si possono definire i simboli del preprocessore C che
consentono la compilazione condizionale dei programmi (anche in Fortran); è
pertanto possibile gestire la ricompilazione dei programmi con diverse
configurazioni con la modifica di un unico file.

La sintassi normale del comando (quella che si usa quasi sempre, per le
opzioni vedere la pagina di manuale) è semplicemente \texttt{make}. Questo
comando esegue le istruzioni contenute in un file standard (usualmente
\texttt{Makefile}, o \texttt{makefile} nella directory corrente).

Il formato normale dei comandi contenuti in un \texttt{Makefile} è:
\begin{verbatim}
bersaglio: dipendenza1 dipendenza2 ...
        regola1
        regola2
        ...
\end{verbatim}
dove lo spazio all'inizio deve essere un tabulatore (metterci degli spazi è un
errore comune, fortunatamente ben segnalato dalle ultime versioni del
programma), il bersaglio e le dipendenze nomi di file e le regole comandi di
shell.

Il concetto di base è che se uno dei file di dipendenza è più recente (nel
senso di tempo di ultima modifica) del file bersaglio quest'ultimo viene
ricostruito di nuovo usando le regole elencate nelle righe successive.

Il comando \texttt{make} ricostruisce di default il primo bersaglio che viene
trovato nella scansione del \texttt{Makefile}, se in un \texttt{Makefile} sono
contenuti più bersagli indipendenti, si può farne ricostruire un altro che non
sia il primo passandolo esplicitamente al comando come argomento, con qualcosa
del tipo di: \texttt{make altrobersaglio}.

Si tenga presente che le dipendenze stesse possono essere dichiarate come 
bersagli dipendenti da altri file; in questo modo è possibile creare una 
catena di ricostruzioni. 

In esempio comune di quello che si fa è mettere come primo bersaglio il
programma principale che si vuole usare, e come dipendenze tutte gli oggetti
delle funzioni subordinate che utilizza, con i quali deve essere collegato; a
loro volta questi oggetti sono bersagli che hanno come dipendenza i relativi
sorgenti. In questo modo il cambiamento di una delle funzioni subordinate
comporta solo la ricompilazione della medesima e del programma finale.


\subsection{Utilizzo di \texttt{make}}

Il comando \texttt{make} mette a disposizione una serie molto complesse di
opzioni e di regole standard predefinite e sottintese, che permettono una
gestione estremamente rapida e concisa di progetti anche molto complessi; per
questo piuttosto che fare una replica del manuale preferisco commentare un
esempio di \texttt{makefile}, quello usato per ricompilare i programmi di
analisi dei dati dei test su fascio del tracciatore di Pamela.

\small
\begin{verbatim}
#----------------------------------------------------------------------
#
# Makefile for a Linux System:
# use GNU FORTRAN compiler g77
# Makefile done for tracker test data
#
#----------------------------------------------------------------------
# Fortran flags
FC=g77
FFLAGS= -fvxt -fno-automatic -Wall -O6 -DPC # -DDEBUG
CC=gcc
CFLAGS= -Wall -O6
CFLADJ=-c #-DDEBUG
#
# FC            Fortran compiler for standard rules
# FFLAGS        Fortran flags for standard rules
# CC            C Compiler for standard rules
# CFLAGS        C compiler flags for standard rules 
LIBS=  -L/cern/pro/lib -lkernlib -lpacklib -lgraflib -lmathlib
OBJ=cnoise.o fit2.o pedsig.o loop.o badstrp.o cutcn.o readevnt.o \
erasepedvar.o readinit.o dumpval.o writeinit.o

riduzione: riduzione.F $(OBJ) commondef.f readfile.o
        $(FC) $(FFLAGS) -o riduzione riduzione.F readfile.o $(OBJ) $(LIBS) 

readfile.o: readfile.c
        $(CC) $(CFLAGS) -o readfile.o readfile.c

$(OBJ): commondef.f

.PHONY : clean
clean:
        rm -f *.o 
        rm -f *~
        rm -f riduzione
        rm -f *.rz
        rm -f output
\end{verbatim}
\normalsize

Anzitutto i commenti, ogni linea che inizia con un \texttt{\#} è un
commento e non viene presa in considerazione.

Con \texttt{make} possono essere definite delle variabili, da potersi riusare
a piacimento, per leggibilità si tende a definirle tutte maiuscole,
nell'esempio ne sono definite varie: \small
\begin{verbatim}
FC=g77
FFLAGS= -fvxt -fno-automatic -Wall -O6 -DPC # -DDEBUG
CC=gcc
CFLAGS= -Wall -O6
CFLADJ=-c #-DDEBUG
...
LIBS=  -L/cern/pro/lib -lkernlib -lpacklib -lgraflib -lmathlib
OBJ=cnoise.o fit2.o pedsig.o loop.o badstrp.o cutcn.o readevnt.o \
\end{verbatim}
\normalsize

La sintassi è \texttt{NOME=}, alcuni nomi però hanno un significato speciale
(nel caso \texttt{FC}, \texttt{FLAGS}, \texttt{CC}, \texttt{CFLAGS}) in quanto
sono usati da \texttt{make} nelle cosiddette \textsl{regole implicite} (su cui
torneremo dopo).

Nel caso specifico, vedi anche i commenti, abbiamo definito i comandi di 
compilazione da usare per il C e il Fortran, e i rispettivi flag, una variabile
che contiene il pathname e la lista delle librerie del CERN e una variabile con una
lista di file oggetto.

Per richiamare una variabile si usa la sintassi \texttt{\$(NOME)}, ad esempio
nel makefile abbiamo usato:
\begin{verbatim}
        $(FC) $(FFLAGS) -o riduzione riduzione.F readfile.o $(OBJ) $(LIBS) 
\end{verbatim}
e questo significa che la regola verrà trattata come se avessimo scritto 
esplicitamente i valori delle variabili.

Veniamo ora alla parte principale del makefile che esegue la costruzione del
programma:
\begin{verbatim}
riduzione: riduzione.F $(OBJ) commondef.f readfile.o
        $(FC) $(FFLAGS) -o riduzione riduzione.F readfile.o $(OBJ) $(LIBS) 
readfile.o: readfile.c
        $(CC) $(CFLAGS) -o readfile.o readfile.c
$(OBJ): commondef.f
\end{verbatim}

Il primo bersaglio del makefile, che definisce il bersaglio di default, è il
programma di riduzione dei dati; esso dipende dal suo sorgente da tutti gli
oggetti definiti dalla variabile \texttt{OBJ}, dal file di definizioni
\texttt{commondef.f} e dalla routine C \texttt{readfile.o}; si noti il
\texttt{.F} del sorgente, che significa che il file prima di essere compilato
viene fatto passare attraverso il preprocessore C (cosa che non avviene per i
\texttt{.f}) che permette di usare i comandi di compilazione condizionale del
preprocessore C con la relativa sintassi. Sotto segue il comando di
compilazione che sfrutta le variabili definite in precedenza per specificare
quale compilatore e opzioni usare e specifica di nuovo gli oggetti e le
librerie.

Il secondo bersaglio definisce le regole per la compilazione della routine
in C; essa dipende solo dal suo sorgente. Si noti che per la compilazione
vengono usate le variabili relative al compilatore C. Si noti anche che se
questa regola viene usata, allora lo sarà anche la precedente, dato che
\texttt{riduzione} dipende da \texttt{readfile.o}.

Il terzo bersaglio è apparentemente incomprensibile dato che vi compare
solo il riferimento alla variabile \texttt{OBJ} con una sola dipendenza e
nessuna regola, essa però mostra le possibilità (oltre che la
complessità) di \texttt{make} connesse alla presenza di quelle regole
implicite a cui avevamo accennato.

Anzitutto una peculiarità di \texttt{make} è che si possono anche usare più
bersagli per una stessa regola (nell'esempio quelli contenuti nella variabile
\texttt{OBJ} che viene espansa in una lista); in questo caso la regola di
costruzione sarà applicata a ciascuno che si potrà citare nella regola stessa
facendo riferimento con la variabile automatica: \texttt{\$@}.  L'esempio
usato per la nostra costruzione però sembra non avere neanche la regola di
costruzione.

Questa mancanza sia di regola che di dipendenze (ad esempio dai vari sorgenti) 
illustra le capacità di funzionamento automatico di \texttt{make}.
Infatti è facile immaginarsi che un oggetto dipenda da un sorgente, e che 
per ottenere l'oggetto si debba compilare quest'ultimo.

Il comando \texttt{make} sa tutto questo per cui quando un bersaglio è un
oggetto (cioè ha un nome tipo \texttt{qualcosa.o}) non è necessario
specificare il sorgente, ma il programma lo va a cercare nella directory
corrente (ma è possibile pure dirgli di cercarlo altrove, il caso è trattato
nel manuale).  Nel caso specifico allora si è messo come dipendenza solo il
file delle definizioni che viene incluso in ogni subroutine.

Inoltre come dicevamo in genere per costruire un oggetto si deve compilarne il
sorgente; \texttt{make} sa anche questo e sulla base dell'estensione del
sorgente trovato (che nel caso sarà un \texttt{qualcosa.f}) applica la regola
implicita.  In questo caso la regola è quella di chiamare il compilatore
fortran applicato al file oggetto e al relativo sorgente, questo viene fatto
usando la variabile \texttt{FC} che è una delle variabili standard usata dalle
regole implicite (come \texttt{CC} nel caso di file \texttt{.c}); per una
maggiore flessibilità poi la regola standard usa anche la variabile
\texttt{FFLAGS} per specificare, a scelta dell'utente che non ha che da
definirla, quali flag di compilazione usare (nella documentazione sono
riportate tutte le regole implicite e le relative variabili usate).

In questo modo è stato possibile usare una sola riga per indicare la serie di
dipendenze e relative compilazioni delle singole subroutine; inoltre con l'uso
della variabile \texttt{OBJ} l'aggiunta di una nuova eventuale routine
\texttt{nuova.f} comporta solo l'aggiunta di \texttt{nuova.o} alla definizione
di \texttt{OBJ}.


\section{Cuncurrent Version System -- CVS}

Il programma CVS è un sistema di archiviazione dei programmi che consente di
tenere traccia di tutte le modifiche e di condividere un archivio comune per
progetti portati avanti da diverse persone.

\subsection{Introduzione}
CVS è basato sul concetto di repositorio, un archivio in cui vengono riposti
e da cui vengono presi i sorgenti dei programmi. L'archivio tiene traccia delle
diverse versioni registrate; i programmatori inviano le modifiche usando una 
copia locale che hanno nella loro directory di lavoro. 

CVS può gestire più di un progetto, esso organizza i progetti in
\textsl{moduli} identificati dal nome della directory in cui sono messi i file
relativi, ad esempio: 
\small
\begin{verbatim}
[piccardi@pcpamela ~]$ ls /usr/local/cvsroot/ 
CVSROOT  adidsp  geometry  muonacq  pamela
\end{verbatim}
\normalsize %$
in questo caso si hanno i moduli \texttt{adidsp geometry muonacq pamela}; un
utente potrà recuperare tutti i file relativi al modulo \texttt{pamela} che
andaranno nella directory \texttt{pamela}; è anche possibile gestire una
gerarchia di moduli, inseriti in un albero di directory.

CVS ha una directory base dove tiene gli archivi (che nel è appunto
\texttt{/usr/local/cvsroot}) e i vari file amministrativi; ogni progetto deve
fare riferimento ad essa; in un progetto attivo essa viene memorizzata nei
file amministrativi locali del progetto (ad esempio per un utente che ha il
progetto \texttt{muonacq} nella sua home directory sarà in
\texttt{\tild/muonacq/CVS}) e non è necessario specificarla; in generale essa
viene tenuta dalla variabile di shell \texttt{CVSROOT} (inizializzata allo
startup), o specificata direttamente dall'utente con l'apposita opzione
\texttt{-d} (ex. \texttt{cvs -d /usr/local/cvsroot comando opzioni}).

Normalmente l'archivio si tiene su una macchina remota e vi si accede via
rete. Per repositori esterni esistono varie modalità di accesso, la via più
semplice è quella dell'uso di \texttt{ssh} come rimpiazzo di \texttt{rsh} per
l'accesso esterno; in tal caso la directory del repositorio si può accedere
con la sintassi: \small
\begin{verbatim}
cvs -d :ext:utente@server:/usr/local/cvsroot comando
\end{verbatim}
\normalsize

questo però comporta che sulla macchina remota \texttt{server} sia installato
il server \texttt{ssh} ed esista l'utente \texttt{utente} con privilegi di
accesso ai file; inoltre sulla macchina ospite deve esser stata definita la
variabile di shell \texttt{CVS\_RSH=ssh}.

In questo modo ssh si collega alla macchina remota ed esegue il comando CVS con
una connessione criptata dopo aver richiesto la password di \texttt{utente}. 


\subsection{Utilizzo di \texttt{cvs}}

Per creare un repositorio a partire da un gruppo di programmi esistente basta
dare il comando \texttt{cvs import project tag release} nella directory dei
sorgenti; verrà creato nel repositorio il modulo di nome \texttt{project} a
cui poi si potrà accedere con i successivi comandi; \texttt{tag} è una
etichetta di versione iniziale (ex. \texttt{1.1.1}) dato a tutto il blocco e
\texttt{release} una etichetta di versione data ai programmi.

Una volta creato il repositorio è d'uopo cancellare la directory e ripartire
dal progetto appena creato. Per recuperare ex-novo tutti i file di un progetto
il comando da dare è:
\small
\begin{verbatim}
cvs [-d ...] checkout project [-r rel] [-D date]
\end{verbatim}
\normalsize che creerà la directory \texttt{project} nella directory corrente
con l'ultima versione dei file archiviata; se non si vuole la versione più
aggiornata, ma una versione precedente si può usare l'opzione \texttt{-r} che
scaricherà la versione identificata dall'etichetta specificata (vedi la parte
seguente sul comando \texttt{tag}) o l'opzione \texttt{-D} che scaricherà la
versione più recente prima della data specificata.

Una volta scaricato il progetto è possibile evitare di specificare la
directory base del repositorio con l'opzione \texttt{-d} qualora i comandi
vengano dati all'interno della directory creata, essa viene tenuta nel file
\texttt{CVS/Root}, e può essere cambiata (qualora si usino più repositori)
editando detto file.

Una volta creata la propria copia locale dei programmi, è possibile lavorare
su di essi stando nella relativa directory,
e apportare tutte le modifiche che si vogliono; due comandi 
permettono di schedulare la rimozione o l'aggiunta di file al repositorio:
\small
\begin{verbatim}
cvs add file1.c
cvs remove file2.c
\end{verbatim}
\normalsize
ma niente viene modificato nel repositorio fintanto che non viene dato il 
comando \texttt{commit}: 
\small
\begin{verbatim}
cvs commit [file]
\end{verbatim}
(è possibile mandare le modifiche anche per il singolo file). 

Questi comandi comunque non effettuano le modifiche se i file del repositorio
nel frattempo sono stati modificati; in questo caso rilevano le differenze e
restituiscono un \textit{merging} delle versioni locale/globale nella
directory di lavoro, che è compito del programmatore esaminare per eliminare
eventuali contrasti.

Per esempio viene eseguito un commit su una versione già modificata da un
altro sul repositorio, il programma segnalerà che c'è un conflitto e
chiederà al ``committente'' di intervenire sui file per i quali sono stati
rilevati i conflitti .

Le sezioni di codice in conflitto sono separate come:
\begin{verbatim}
<<<<<<< Makefile
        $(CC) $(CFLAGS) -o pamacq pamacq.c -lm
=======
        $(CC) $(CFLAGS) -o pamacq pamacq.c

>>>>>>> 1.22
\end{verbatim}
nel caso si c'è stata una modifica sul file (mostrata nella parte superiore)
incompatibile con quella fatta nel repositorio (mostrata nella parte
inferiore). Prima di eseguire un \textit{commit} occorre pertanto integrare le
modifiche e risalvare il file; a questo punto il \textit{commit} diventa
possibile.

\subsection{I principali sotto comandi}

I principali sottocomandi di \texttt{cvs} utilizzati per controllare lo stato
dei sorgenti sono:

\begin{itemize}
\item \texttt{cvs update} \\
  scarica le eventuali modifiche dei file del repositorio e le applica ai file
  nella directory corrente. In caso di conflitti con modifiche locali effettua
  un \textit{merging} con le caratteristiche esposte in precedenza.

\item \texttt{cvs status} \\
  compara i file nella directory locale con quelli del repositorio e stampa a
  schermo le informazioni di stato di ciascuno di essi:
\begin{itemize}
\item \texttt{Locally Modified} il file è stato modificato localmente
\item \texttt{Locally Added} il file è stato aggiunto localmente
\item \texttt{Up to date} il file è identico
\item \texttt{Needs Patch} il file è cambiato sul repositorio (va aggiornato)
\item \texttt{Needs Merge} il file è cambiato sul repositorio e localmente, le
  differenze vanno riunite prima del commit, in genere basta un \texttt{cvs
    update}, ma in caso di conflitti questi vanno sanati.

\end{itemize}

\item \texttt{cvs log} \\
  legge il giornale del modulo corrente; in questo modo si hanno le
  informazioni sullo stato del progetto all'interno del repositorio, per
  ciascun file è vengono mostrati informazioni generali su:
\begin{itemize}
\item release attuale
\item presenza di eventuali ramificazioni
\item lista di etichette simboliche
\item i messaggi di commento salvati ad ogni \textit{commit}
\end{itemize}

\item \texttt{cvs rtag Etichetta modulo} \\
  permette di associare una etichetta alla corrente versione dei file nel
  progetto così come sono nel repositorio; in modo da poter ritornare a quello
  stato del software con il comando \texttt{cvs checkout -rEtichetta module}.

\end{itemize}

%TODO mettere SVN al posto di CVS


% LocalWords:  make Makefile makefile shell FC FLAGS CFLAGS pathname CERN
% LocalWords:  OBJ commondef readfile FFLAGS Cuncurrent Version System CVS home
% LocalWords:  adidsp geometry muonacq andaranno CVSROOT startup cvs ssh rsh to
% LocalWords:  project tag Root commit update merging Locally Modified Added
% LocalWords:  Needs Patch Merge log rtag checkout module



%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "gapil"
%%% End: 
