Introduzione a GCC: GNU Compiler Collection
Caratteristiche di GCC Compilatore multipiattaforma modulare Disponibile per tutti i principali sistemi operativi Può produrre programmi per la maggior parte delle architetture di processori general purpose (i386, amd64, ia-64, SPARC, PowerPC, Alpha, ARM, m68k, etc.) e numerosi microcontrollori e DSP Permette la cross-compilazione Scrivere e compilare un programma su una piattaforma A (host) da eseguire su una piattaforma B diversa (target) Dispone di moduli per la compilazione di numerosi linguaggi (C, C++, FORTRAN, ADA, etc.) Licenza GNU GPL
Hello GCC! Programma elementare in C $ vi hellogcc.c 1 #include <stdio.h> 2 3 int main(int argc, char** argv) { 4 printf("hello GCC!"); 5 return 0; 6 } Per compilare $ gcc hellogcc.c GCC produce in output l eseguibile a.out (nome predefinito); per eseguirlo $./a.out Hello GCC!
Passi eseguiti da GCC Preprocessing (hellogcc.c) Compilazione: hellogcc.s Assembly: hellogcc.o Linking: a.out Il comportamento predefinito di GCC è di eseguire tutti i passi in quest'ordine
Principali opzioni di GCC (1/2) -x language forza uno specifico linguaggio (altrimenti GCC individua il linguaggio in base all estensione dei file sorgenti) -S ferma dopo il passo di assembly -c ferma dopo il passo di compilazione -E ferma dopo il passo di preprocessing -o filename specifica il nome del file di output -v mostra a video informazioni più dettagliate sulle operazioni eseguite -g inserisce nel file eseguibile informazioni utili per eseguire sessioni di debugging con gdb, il debugger di GCC
Principali opzioni di GCC (2/2) Diverse opzioni per il compilatore in base al linguaggio scelto Opzioni per il linker: per creare una libreria o indicare a GCC dove cercare quelle utilizzate -On livello di ottimizzazione del codice, con n {0, 1, 2, 3, s} -O0 è il default (nessuna ottimizzazione); -O3 è la massima ottimizzazione per velocità d esecuzione (può causare errori a runtime in alcune condizioni; -O2 è invece generalmente sicuro) -Os ottimizza per ridurre le dimensioni del programma eseguibile N.B.: le opzioni lunghe un solo carattere devono essere scritte separate tra loro
Errori di compilazione (1/2) Un programma contenente errori non sarà compilato $ vi provaerr.c 1 #include <stdio.h> 2 3 int main(int argc, char** argv) 4 { 5 int a = 5, b = 3 // manca il ; 6 int c = a + b; 7 printf("somma = %d", c); 8 return 0; 9 } Proviamo a compilarlo $ gcc provaerr.c o provaerr
Errori di compilazione (2/2) GCC segnala gli errori trovati Intestazione riportata Per ciascuna funzione che contiene errori provaerr.c: In function main : provaerr.c:6: error: expected, or ; before int provaerr.c:7: error: c undeclared (first use in this function) provaerr.c:7: error: (Each undeclared identifier is reported only once provaerr.c:7: error: for each function it appears in.) Struttura di un messaggio di errore: sorgente:riga:error: messaggio esplicativo Un messaggio di errore può estendersi su più righe
Warning (1/2) Il warning segnala un anomalia che però non impedisce la compilazione di un programma Spesso è comunque sintomo di un problema Esempio di un programma che genera un warning $ vi provawarn.c 1 #include <stdio.h> 2 3 void main(int argc, char** argv) 4 { 5 int a = 5, b = 3; 6 int c = a + b; 7 printf("somma = %d", c); 8 return 0; // attenzione: dichiarato void 9 }
Warning (2/2) GCC segnala i warning in modo molto simile agli errori $ gcc provawarn.c o provawarn provawarn.c: In function main : provawarn.c:8: warning: return with a value, in function returning void provawarn.c:4: warning: return type of main is not int Possiamo ugualmente eseguire il programma compilato $./provawarn Risultato = 7
Errori a runtime Come ogni compilatore, anche GCC non può individuare tutte le condizioni che porteranno ad errori a runtime Il seguente programma è compilato correttamente 1 #include <stdio.h> 2 3 int main(int argc, char** argv) 4 { 5 int a = 5, b = 0; 6 int c = a / b; 7 printf("risultato = %d", c); 8 return 0; 9 } $ gcc runtimeerr.c o runtimeerr Ma eseguendolo si ha un errore $./runtimeerr Floating point error
Debugging con gdb Ecco perché è necessario uno strumento di debugging gdb è il debugger di GCC Usiamo gdb con questo programma: $ vi provadebug.c $ gcc -g provadebug.c -o provadebug $ gdb provadebug 1 #include <stdio.h> 2 3 int potenza(int b, int e) { 4 int i, r = 1; 5 for (i=0; i<e; i++) { 6 r = r * b; 7 } 8 return r; 9} 10 11 int main(int argc, char** argv) { 12 int a = 5, b = 2; 13 int c = potenza(a, b); 14 printf("risultato = %d", c); 15 return 0; 16}
Uso di gdb (1/2) gdb presenta un prompt in cui inserire i comandi per il debugging Comandi principali: run avvia l'esecuzione del programma: si fermerà al primo punto d'interruzione incontrato break function inserisce un punto d'interruzione (breakpoint) all'ingresso della funzione specificata bt backtrace: mostra lo stato dello stack
Uso di gdb (2/2) Comandi principali: c riprende l'esecuzione del programma dopo una interruzione fino al prossimo breakpoint step esegue la prossima istruzione: se essa contiene una chiamata a funzione, va alla prima istruzione del corpo della funzione (step into) next esegue la prossima istruzione: se essa contiene una chiamata a funzione, viene eseguita per intero (step over) help guida sui comandi disponibili quit esce da gdb
Esempio con gdb $ gdb provadebug GNU gdb 6.6 Copyright (C) 2006 Free Software Foundation, Inc. [...] (gdb) break potenza Breakpoint 1 at 0x804837e: file provadebug.c, line 4. (gdb) run Starting program: /home/floriano/sorgenti/provadebug Breakpoint 1, potenza (b=5, e=2) at provadebug.c:4 4 int i, r = 1; (gdb) bt #0 potenza (b=5, e=2) at provadebug.c:4 #1 0x080483d2 in main () at provadebug.c:14 (gdb) c Continuing. Risultato = 25 Program exited normally. (gdb) quit
Cross-compilazione (1/2) = scrivere e compilare un programma su una piattaforma A (host) da eseguire su una piattaforma B diversa (target) Durante l'installazione di GCC è necessario specificare le piattaforme target per cui si vorranno compilare programmi In molti casi occorrono anche le librerie di runtime di ciascuna piattaforma target per la fase di linking
Cross-compilazione (2/2) Per la programmazione di PDA e dispositivi embedded sono spesso reperibili versioni apposite di GCC (corredate dai moduli di supporto) da installare sulla piattaforma host senza interferire con un'eventuale installazione preesistente E' possibile effettuare il debugging Collegando il dispositivo target alla macchina host Oppure mediante simulatori I dettagli del setup variano in base alla coppia host-target: seguire le istruzioni!
Cross-compilazione con GCC Per cross-compilare un programma generalmente si usa l'opzione -b seguita dalla piattaforma target Una piattaforma è di solito identificata da due nomi separati da un trattino: cputype-binaryformat cputype: architettura delle famiglia di CPU target (ex. i386, sparc, arm) binaryformat: formato dei file eseguibili (ex. Elf) Se si usa una versione apposita di GCC per la cross-compilazione, si invoca il compilatore specifico (seguire le istruzioni)