giovedì 2 Maggio 2024
Home / Corsi / Corso C / Lezione 9 – Arrivederci (make & Makefile)
Corso C

Lezione 9 – Arrivederci (make & Makefile)

Ebbene si, questa è l’ultima lezione di questo corso sul C.

Si spera che quanto promesso nella lezione 0 sia stato raggiunto.

In futuro magari qualche argomento specifico sarà proposto, ma vedremo (potrebbe anche essere una vostra richiesta specifica….)

Aver seguito questo corso non vi rende programmatori, solo programmando ci riuscirete.

Molte cose non sono state trattate ma su internet scoprirete che sicuramente prima di voi qualcuno avrà avuto il vostro stesso problema e vi fornirà una possibile soluzione.

Come ultimo argomento, (come da titolo), vogliamo vedere come è fatto un Makefile per compilare il sorgente. Tale procedura può anche essere usata per generare una libreria.

Il codice è costituito da tante piccole funzioni ognuna delle quali risolve un piccolo problema: cooperando tra di loro ed orchestrate da un programma principale sono in grado di risolvere grossi problemi.

A titolo di esempio, realizzeremo una calcolatrice con varie funzioni.

Organizzazione della directory di lavoro

Anche questa ultima lezione non prevede l’uso di un IDE. Molti forse non apprezzano questa scelta, ma la lezione è comunque utile perché spiega come impostare l’ambiente di lavoro e scrivere il codice separando le varie funzioni. Si propone anche un eseguibile in grado di generare un Makefile e compilare il codice, ma se usate un IDE, questo lo farà per voi.

Per prima cosa nella cartella in cui vogliamo sviluppare la calcolatrice, generiamo tre sotto cartelle:

  • src
  • hdr
  • obj

La prima conterrà i sorgenti, la seconda gli headers e la terza il risultato parziale della compilazione ossia i file punto o.

Vediamo prima di tutto come funziona la calcolatrice:

Fig1 – Menu principale

Nella Fig1 possiamo vedere il menu principale della calcolatrice. Supponiamo di selezionare 1, avremo: (vedi Fig2)

Fig2 – Somma

dove sono già stati inseriti i due addendi. Se si risponde s (si) si potrà eseguire un’altra somma se n (no) riapparirà il menu principale per effettuare un’altra scelta. Digitando 0 il programma si arresta.

Di seguito esamineremo solo alcune funzioni, in quanto tutto il codice è disponibile sul repository GitHub come archivio compresso (tgz).

Iniziamo con il main.c

Notate tutti gli include relativi a tutte le funzioni chiamate dal main. Si tratta di un loop infinito, interrotto solo se la funzione menu restituisce 0, altrimenti uno switch indirizza verso la funzione desiderata.

Vediamo adesso la funzione menu con il suo header, in cui abbiamo introdotto una nota di colore.

menu.c

 

menu.h 

Osserviamo prima l’header. Contiene stdlib.h perché lì è definita la funzione system ed stdio.h per tutte le funzioni di lettura e stampa. Vi è anche la dichiarazione della funzione che non prevede input ma genera un output intero. Il tutto è inglobato nel costrutto #ifndef #endif, per evitare di includere più volte la stesso punto h.

Nella funzione, la prima cosa da osservare è come cambiare colore alle scritte. E’ sufficiente stampare:

printf(“\x1b[1;31m”); 

dove 31 indica il rosso secondo questa casistica:

  • <= 29 Bianco
  • 30 Grigio
  • 31 Rosso
  • 32 Verde
  • 33 Giallo
  • 34 Blu
  • 35 Magenta (viola chiaro)
  • 36 Ciano (celeste)
  • >=37 bianco

Se nella printef, dopo la parentesi quadra, l’uno lo sostituiamo con uno 0 si ottengono gli stessi colori solo meno brillanti (il grigio su fondo nero non si vede).

Per ripristinare il colore di default basta stampare:

printf(“\x1b[0m”);

L’istruzine system(“clear”) esegue il comando di sistem clear, che pulisce lo schermo e riporta il cursure in alto a sinistra dello schermo.

A questo punto vediamo make_somma ed il suo header

make_somma.c

make_somma.h

Si noti l’inclusione di somma.h nel sorgente in quanto dopo utilizzerà quella funzione. A questo punto vediamo somma ed il suo header

somma.c

somma.h

In sostanza ogni modulo deve avere tutti gli headers  per poter essere compilata (ossia tutte le dichiarazioni delle funzioni che verranno usate.

Da ultimo vediamo la media che utilizza la somma e la divisione

make_media.c

make_media.h

e quindi nel .h solo l’inclusione per pulire lo schermo e fare i/o. Nel .c l’inclusione degli headers per fare la somma e la divisione.

A questo punto vediamo come è fatto il Makefile

Iniziamo ad esaminare come è fatto un Makefile.

  • Per prima cosa, le righe che iniziano con il simbolo #, sono dei commenti
  • Nella prima parte del Makefile vengono definite delle variabili tra cui notiamo
    • CC=gcc che definisce il compilatore,
    • WARN=-Wall che attiva tutti i possibili warning
    • DEBUG=  al momento vuoto ma se si vuole usare il debugger (p. es. gdb + wrapper DDD) da valorizzare con -g
    • OPT=-O3 livello di ottimizzazione del codice
    • CCFLAGS = -c ${DEBUG} ${OPT} ${WARN} i flag di compilazione (come negli script bash il valore della variabile lo si ottiene con ${})
    • LDFLAGS = -lm sono i flag di linking e dove mettere tutte le libreire usate nel codice
    • SRCDIR = src la cartella dei sorgenti
    • HDSDIR = hdr la cartella degli headers
    • OBJDIR = obj la caretella degli oggetti (.o)
    • EXEDIR = . la cartella in cui si vuole posizionare l’eseguibile
    • SRCS conterrà tutta la lista dei sorgenti
    • HDSS la lista degli headers
    • OBJS la lista degli oggetti
    • PROGRAM = $(EXEDIR)/calcolatrice definisce l’eseguibile
  • Da questo punto in poi, il comando make, che compila il nostro codice tramite il Makefile controlla, secondo quanto riportato sempre nel Makefile, se un risultato è più recente dei file che dovevano produrlo:
  • $(PROGRAM): $(OBJS) $(SRCS) se ${PROGRAM} non esiste o è più vecchi degli ${OBJS} e ${SRCS}, secondo le regole riportate nelle righe successive si genera l’eseguibile (si noti che le righe con le istruzioni devono iniziare con il caratter TAB (\t)
  • Se ${PROGRAM} è precedente, si passa alle righe successive
  • $(OBJDIR)/divisione.o: $(SRCDIR)/divisione.c $(HDSDIR)/divisione.h, come prima, se divisione.o è precedente rispetto a divisione.c o divisione.h viene compilato secondo le righe successive, altrimenti si salta.
  • Allo stesso modo si procede per tutti i file
  • Quando saranno tutti aggiornati si ritorna alla riga di ${PROGRAM} per genera l’eseguibile
  • L’essere un risultato precedente ai file che lo possono aver generato, indica che i sorgenti sono stati modificati e quindi bisogna ri-generare il risultato.
  • make clean consente di cancellare oggetti ed eseguibile

Per compilare il programma è sufficiente eseguire il comando make. (Se non lo avete installato tramite il comando sudo apt-get install make, lo potrete installare).

Tutti i sorgenti modificati saranno compilati ed alla fine si otterrà l’eseguibile.

Il Makefie potreste scriverlo tramite un text editor ma nel repository GitHub troverete l’eseguibile makeMakefile che potrà farlo per voi.

Fig3 – Configurazione makeMakefile

La prima volta che gira vedrete una schermata come quella di Fig3.

Selezionando 1 inserirete src, 2 hdr e 3 obj, come cartella dell’eseguibile potete lasciare quella corrente (.) e tramite 5 inserirete il nome dell’eseguibile (calcolatrice), ottenendo qualcosa del genere:

Fig4 – makeMakefile configurato

a questo punto selezionando 0, genererete il vostro Makefile in modo automatico.

Viene anche scritto un piccolo file di configurazione makeMakefile.conf, che contiene queste impostazioni. Da adesso in poi, ogni volta che aggiungerete sorgenti o .h, sarà sufficiente far rigirare maleMakefile che aggiornerà tutto il progetto compreso il Makefile. Per compilare sarà sufficiente eseguire il comando make.

Se volete salvare il progetto occupando il meno spazio possibile (come farò io per generre l’archivio su GitHub), prima eseguite make clean che cancella eseguibile e .o e salvate.

Per rigenerare l’eseguibile, ovviamente basterà eseguire make.

Questo è tutto.

Siamo al momento vero degli arrivederci. E’ stato un piacere produrre questo corso e spero che per voi leggerlo sia stato un po’ interessante. Critche e commenti saranno sempre benvenuti e se c’è qualcosa che potrebbe essere esposto meglio, spero me lo comunichiate, per rendere questo lavoro anche utile.

Come ogni volta ricordiamo:

  • qui il forum di supporto al corso.
  • Se vuoi restare aggiornato, seguici anche sui nostri social: Facebook, Twitter, Youtube
  • Se vuoi anche trovare prodotti e accessori Raspberry Pi in offerta, seguici anche su Telegram !!

Arrivederci

arkkimede

 

 

 

A proposito di arkkimede

Vedi Anche

MagPi139 doppiapagina

MagPi in Italiano! Soluzione dei Problemi: La Guida

Estratto, tradotto in italiano, di The MagPi N°139 la rivista ufficiale della Fondazione Raspberry Pi.

Powered by themekiller.com