This is an old revision of the document!
Descărcați arhiva TODO
. Dezarhivați folosind tar:
tar xf lab06.tar.gz
Intrați în directorul tutorial/2
. Fișierul hello.c
este o sursă C completă. Compilați fișierul utilizând gcc
:
gcc hello.c
Ce fișiere s-au creat? Aflați tipul acestora utilizând comanda file
.
ls -l file a.out
Rulați fișierele executabile.
./a.out
Compilați sursa specificând și numele fișierului executabil:
gcc hello.c -o stallman
Rulați executabilul creat.
Compilați sursa afișând avertismente:
gcc hello.c -o linus -Wall
-Wall
pentru fiecare compilare.
-Wextra
și -Werror
.
Corectați warning-urile apărute. Recompilați sursa.
Rulați comenzile următoare:
gcc -o jobs -Wall hello.c gcc -Wall -o turing hello.c gcc -Wall hello.c -o dijkstra
Utilizând ls -l
comparați dimensiunile celor 3 executabile create. Verificați că cele 3 executabile sunt identice vizualizând output-ul fiecăruia.
Calculați md5-ul fiecărui executabil și verificați că este identic.
md5sum
putem obține un rezumat al conținutului unui fișier. Acest rezumat, cunoscut și sub numele de hash, are proprietatea interesantă că cea mai mică modificare posibilă în fișierul inițial va duce la modificarea completă a md5-ului. Din acest motiv, 2 fișiere cu același md5 pot fi considerate identice.
În general, ordinea parametrilor nu contează. Anumiți parametri au argumente. Aici avem parametrul -o
. Acest argument trebuie urmat întotdeauna de numele executabilului.
Intrați în directorul tutorial/3/1
. Vizualizați conținutul fișierului answer.c
. Rulați comanda
gcc -E answer.c -o answer.i
Cum s-a modificat fișierul sursă în urma etapei de preprocesare? Ce tip are fișierul generat (folosiți file
)?
Intrați în directorul tutorial/3/2
. Vizualizați conținutul fișierului answer.c
. Rulați comanda
gcc -S answer.c -o answer.s
Ce tip are fișierul generat în etapa de compilare?
Folosind gcc
efectuați etapa de asamblare:
gcc -c answer.s -o answer.o
Ce tip are fișierul obținut?
.c
adresa acestei funcții nu va fi cunoscută în momentul asamblării fișierului. Ea va fi completată în etapa următoare
Ultima etapă din procesul de compilare este cea de link-editare. Folosind gcc
, invocați această etapă pentru a obține executabilul final:
gcc answer.o
Ce fișier a fost creat? Ce tip are acest fișier? Rulați executabilul.
4.1. Intrați în directorul 1}. Fișierul sandwich.c} conține un program C valid. Rulați
<screen> make sandwich </screen>
și vizualizați fișierele create (utilizând file} pentru a vedea tipul acestora). Ce comandă este folosită pentru a compila sursa?
4.2. Intrați în directorul 2}. Fișierul makefile} va fi folosit pentru a compila sursa sandwich.c}. Rulați comenzile:
<screen> make ./sandwich </screen>
Vizualizați fișierul makefile}. Fișierul conține o singură linie sandwich}. Aceasta îi indică utilitarului make} să execute target-ul sandwich}. Deoarece nu există altceva, se va încerca folosirea unei reguli implicite.
Care este regula implicită folosită? (afișată în terminal). Diferă fată de cea anterioară?
4.3. Intrați în directorul 3}. Fisierul makefile} a fost completat astfel încât să se precizeze explicit ce sursă se compilează, pentru a putea diferenția între cele 2 surse prezente în director, sandwich.c} și reply.c}. Rulați comenzile următoare și urmăriți ce se execută:
<screen> make ls rm sandwich make sandwich ls make reply ls ./sandwich ./reply </screen>
Un target poate avea o listă de dependențe. Acestea se scriu pe aceeași linie, după }.
4.4 Modificați reply.c} adăugând porțiunea comentată. Rulați comenzile
<screen> make reply make reply </screen>
Deoarece între cele 2 comenzi nu am modificat sursa, nu se va executa nimic pentru a doua comandă.
4.5. Intrați în directorul 5}. Fișierul makefile} a fost completat astfel încât să se poată construi ambele executabile cu aceeași comandă și pentru a putea șterge toate fisierele create pe baza surselor. Rulați comenzile
<screen> ls make ls make clean ls </screen>
Pentru targetul clean} s-au introdus și instrucțiunile necesare producerii acestuia din dependențe. Acestea se pun indentate cu un tab pe liniile imediat următoare definirii targetului.
4.6. Intrați în directorul 6}. Fișierul makefile} este identic cu cel din exercițiul anterior (verificați cu diff}). Rulați comenzile
<screen> touch clean ls make ls make clean ls </screen>
De ce nu se revine la situația initială a fișierelor din director?
Redenumiți fișierul makefile.good} în makefile} și rulați din nou comenzile de mai sus. Singura diferență este linia all_clean}.
4.7. Intrați în directorul 7}. Rulați comenzile următoare și observați ce se execută:
<screen> make story rm story make story CFLAGS=-Wall rm story make story CC=gcc rm story make story CC=gcc CFLAGS=”-Wall -Wextra -O3” </screen>
Ați folosit variabile makefile} pentru a modifica regula implicită.
Un mic grafic cu etapele compilării și legătura dintre acestea și variabilele makefile este următorul
Intrați în directorul 5}. Compilați fișierul traceable.c} utilizând gcc}, salvând executabilul ca traceme}. Rulați comenzile:
<screen> ./traceme strace ./traceme </screen>
Utilitarul strace} permite evidențierea fiecărui apel de sistem din execuția programului. În cazul nostru, printf} se reduce la un apel write}.
Putem evidenția doar anumite apeluri de sistem folosind argumentul e_nume_apel}. Rulați comanda:
<screen> strace -e write ./traceme </screen>
6.1. Intrați în directorul 6}. Compilați sursa math.c} utilizând gcc}:
<screen> gcc math.c </screen>
Se observă că avem o eroare undefined_reference_to_sinh}. Compilați programul până la modulul obiect:
<screen> gcc -c math.c -o math.o </screen>
Utilitarul nm} listează simbolurile dintr-un fișier obiect sau dintr-un executabil. Rulați comanda:
<screen> nm math.o </screen>
Liniile ce conțin 'U' listează simbolurile folosite dar nedefinite în math.o}. Liniile cu 'T' listează simbolurile definite (translatate).
Pentru a putea obține executabilul va trebui să definim și simbolul sinh}. Funcția este definită în biblioteca matematică libm.so}. Pentru a da biblioteca ca argument lui gcc} pentru etapa de link-editare va trebui să folosim argumentul l} astfel: * din numele bibliotecii se elimină extensia și prefixul lib}. * ce rămâne se concatenează la l}
Rulați:
<screen> gcc -lm math.c </screen>
Compilarea reușește. Pentru a vedea bibliotecile folosite de executabil vom folosi un alt utilitar - ldd}:
<screen> ldd a.out </screen>
6.2. Folosiți următoarea comandă pentru a compila sursa static:
<screen> gcc math.c -static -o staticmath -lm </screen>
Comparați dimensiunile fișierelor a.out} și staticmath}.
Rulați
<screen> ldd staticmath </screen>