Differences

This shows you the differences between two versions of the page.

Link to this comparison view

uso:laboratoare:laborator-03 [2016/10/16 10:38]
mbarbulescu [[4] Detectarea și corectarea erorilor de linkare (2p)]
uso:laboratoare:laborator-03 [2022/10/18 15:39] (current)
iustina.caramida
Line 1: Line 1:
-====== Laborator 03 - Dezvoltarea programelor în C sub mediul Linux  ​====== +====== Laborator 03 - Lucrul cu fișiere (partea a 2-a) ======
-<​hidden>​ +
-<note important>​Încercați să vă încadrați în **__30-35 de minute__ de Demo**, chiar dacă ei pun întrebări cu grămada. Vedeți care se mapează pe anumite exerciții și le răspundeți când ajung la exercițiul respectiv. **__Mai bine learn by doing__**. De asemenea, reamintiți-le de WoUSO, cupa ar trebui să fie deja în laborator sau va fi adusă săptămâna aceasta.+
  
-**Rugaminte:​** Dacă termină în timp util, încurajați începerea rezolvării exercițiilor de la Karma (măcar să le înceapă în lab și să le termine acasă). Îi vor ajuta în egală măsură cum îi ajută task-urile obligatorii.</​note>​  +===== Pregătirea laboratorului =====
-</​hidden>​+
  
-===== Obiective laborator ===== +Pentru pregătirea suportului ​de laborator, ​rulați următoarele comenzi ​în ordine:
- +
-  * Familiarizarea cu etapele prin care trece codul sursa de la sursa la executabil +
-  * Familiarizarea cu toolurile necesare acestui lucru (gcc) +
-  * Automatizarea procesului de compilare (make & Makefiles) +
-  * Prezentarea unor principii de bază în scrierea/​editarea ​de cod +
- +
- +
-===== Suport ​laborator ​===== +
- +
-  * [[http://​books.google.com/​books?​id=_JFGzyRxQGcC&​pg=PA319|11. Compilare și linking]] +
-  * [[http://​books.google.com/​books?​id=_JFGzyRxQGcC&​pg=PA469|14. Utilitare pentru dezvoltarea programelor]] +
-  * [[http://​makefiletutorial.com|Makefile Tutorial by Example]] +
-  * [[http://​xkcd.com/​303/​|My code is compiling]] +
-==== Pachete necesare ===== +
- +
-Pe unele sisteme este posibil ca aceste pachete necesare să lipsească:​ +
- +
-  * ''​build-essential''​ +
-  * ''​manpages-dev''​ +
- +
-În cazul în care nu sunt instalate implicit pe sistemul vostrupe un sistem Ubuntu se poate folosi comanda<​code bash> +
-student@uso:​~$ sudo apt-get install build-essential manpages-dev +
-</​code>​ +
- +
-======= Demo ====== +
- +
-Pentru demo deschidem un terminal (folosim combinația de taste ''​**Alt+Ctrl+t**''​) șclonăm [[https://​github.com/​systems-cs-pub-ro/​uso|repository-ului oficial uso]].  +
- +
-<note important>​Ne asigurăm că suntem ​în ''/​home/​student''</​note>​ +
- +
-Folosim comanda+
  
 <code bash> <code bash>
-student@uso:​~$ ​git clone https://github.com/systems-cs-pub-ro/uso  +student@uso:​~$ ​cd ~ 
-</code> ​+student@uso:​~$ wget http://elf.cs.pub.ro/uso/​res/​labs/​lab3/​lab3.zip 
 +--2021-10-18 22:​44:​01-- ​ http://​elf.cs.pub.ro/uso/​res/​labs/​lab3/​lab3.zip 
 +Resolving elf.cs.pub.ro (elf.cs.pub.ro)... 141.85.227.116 
 +Connecting to elf.cs.pub.ro (elf.cs.pub.ro)|141.85.227.116|:​80... connected. 
 +HTTP request sent, awaiting response... 200 OK 
 +Length: 14908126 (14M) [application/zip] 
 +Saving to: ‘lab3.zip’
  
-În directorul ''​/home/​student/​uso/​lab03''​ găsim fișierele necesare pentru laboratorul 3.+lab3.zip ​                                          ​100%[===============================================================================================================>​] ​ 14,​22M ​ 7,61MB/s    in 1,9s    ​
  
 +2021-10-18 22:44:03 (7,61 MB/s) - ‘lab3.zip’ saved [14908126/​14908126]
  
-===== Compilarea unui singur fișier sursă ===== +student@uso:​~$ unzip lab3.zip 
-În cele ce urmează, vom consideră ca verbul **a compila** înseamnă a obține dintr-unul sau mai multe fișiere sursă un fișier executabil.+Archive: ​ lab3.zip 
 +   ​creating:​ archive/ 
 +  inflating: archive/​inregistrare_lab03.mp4 ​  
 +  inflating: archive/​inregistrare_lab01.mp4 ​  
 +  inflating: archive/​inregistrare_lab04.mp4 ​  
 +  inflating: archive/​inregistrare_lab02.mp4 ​  
 +   ​creating:​ redirection/​ 
 +  inflating: redirection/​RL ​          
 +  inflating: redirection/​USO ​         
 +  inflating: redirection/​EGC ​  
  
-Mergem în directorul ''/​home/​student/​uso/​lab03/​simple-gcc''​ unde găsim fișierul ''​simple_hello.c''​+# Când vi se cere parola pentru student, scrieți: ​student și apăsați enter. 
 +# Nu va apărea pe ecran nimic în timp ce tastați.
  
 +student@uso:​~$ sudo apt update
 +[sudo] password for student:
  
-<code bash> +student@uso:~sudo apt -y install vlc
-student@midgardpwd +
-/​home/​student/​ +
-student@midgard$ cd uso/​lab03/​simple-gcc +
-student@midgard$ ls +
-Makefile ​ hello.c ​ simple_hello.c ​ utils.h +
-errors.c ​ help.c ​  ​utils.c ​        ​warnings.c +
-student@midgard$ gcc simple_hello.c ​                                 +
-student@midgard$ ls +
-Makefile ​ errors.c ​ help.c ​         utils.c ​ warnings.c +
-a.out     ​hello.c ​  ​simple_hello.c ​ utils.h +
-student@midgard$ ./a.out +
-Hello world!+
 </​code>​ </​code>​
  
-Anterior am folosit comanda ''​gcc''​ căreia i-am dat un singur parametru ca intrare. A generat un binar numit ''​a.out''​. Mai jos putem vedea cum obținem un nume //custom// pentru binarul rezulat în urma comiplării fișierului ''​simple_hello.c''​. ​ 
- 
-<code bash> 
-student@midgard$ ls 
-Makefile ​ errors.c ​ help.c ​         utils.c ​ warnings.c 
-a.out     ​hello.c ​  ​simple_hello.c ​ utils.h 
-student@midgard$ gcc simple_hello.c -o hello                          ​ 
-student@midgard$ ls                      ​ 
-Makefile ​ errors.c ​ hello.c ​ simple_hello.c ​ utils.h 
-a.out     ​hello ​    ​help.c ​  ​utils.c ​        ​warnings.c 
-student@midgard$ ./hello 
-Hello world! 
-student@midgard$ pwd 
-/​home/​student/​uso/​lab03/​simple-gcc/​ 
-</​code>​ 
- 
-Observați că anterior am folosit o cale relativă la directorul curent pentru a executa fișierul ''​hello'',​ prin apelul ''​./​hello''​. Puteam folosi și o cale absolută: ''/​home/​student/​uso/​lab03/​simple-gcc/​hello''​ pentru executare. 
- 
-<note important>​ 
-Reamintiți-vă de la laboratorul trecut ce înseamnă ''​.''​ (punct, //dot//): **directorul curent**. 
-</​note>​ 
- 
-Pentru a vedea ce tip de fișier binar/​executabil este ''​hello'',​ putem folosi comanda ''​file'': ​ 
- 
-<code bash> 
-student@midgard$ file ./hello 
-hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x92a8cd0efe5b5dd5587b5965d8bc6fa27fac32af,​ not stripped 
-</​code>​ 
- 
-Comanda ''​gcc simple_hello.c''​ a fost folosită pentru compilarea fișierului sursă ''​simple_hello.c''​. Rezultatul a fost obținerea fișierului executabil ''​a.out''​ (nume implicit utilizat de ''​gcc''​). Dacă se dorește obținerea unui executabil cu un alt nume se poate folosi opțiunea ''​-o''​. 
- 
-În mod similar se folosește ''​g++''​ pentru compilarea unui program sursă C++. 
- 
-===== Alte exemple de comenzi folosind compilatorul gcc ===== 
- 
-Pentru compilarea de programe C, respectiv C++ folosim în linie de comandă compilatoarele ''​gcc'',​ respectiv ''​g++''​. O invocare tipică este pentru compilarea unui program dintr-un singur fișier sursă, în cazul nostru ''​simple_hello.c''​. ​ 
- 
-Pornim de la programul simplu din fișierul ''​simple_hello.c''​ pe care îl găsim în directorul ''​~/​uso/​lab03/​simple-gcc''​ care tipărește la ieșirea standard un șir de caractere: 
- 
-<code c simple_hello.c>​ 
- 
-#include <​stdio.h>​ 
- 
-int main(void) ​ 
-{ 
-      printf("​Hello world!\n"​);​ 
-      return 0; 
-} 
-</​code>​ 
- 
-Formatul general al unei comenzi de compilare cu ''​gcc'': ​ 
- 
-<code bash> 
-gcc fisiere.c -o nume_executabil COMPILING_FLAGS LINK_BIBLIOTECI 
-</​code>​ 
- 
-  * ''​COMPILING_FLAGS''​ sunt opțiuni ale gcc (precum ''​-g'',​ ''​-w'',​ ''​-Wall''​) 
-  * ''​LINK_BIBLIOTECI''​ ține de opțiuni precum ''​-lm''​ sau ''​-L''​. 
- 
-<note warning> 
-După ''​-o''​ trebuie să se găsească numele fișierului de ieșire. Acesta suprascrie fișierele pe care le primește ca argument. 
-</​note>​ 
- 
-Comanda poate fi, la fel de bine, structurată și astfel: 
- 
-<code bash> 
-gcc COMPILING_FLAGS -o nume_executabil fisiere.c LINK_BIBLIOTECI 
-</​code>​ 
- 
-<note warning> 
-După ''​-o''​ nu punem fișiere sursă sau alte fișiere. Dacă vom face asta, fișierele vor fi suprascrise și vom pierde conținutul acestora. 
-</​note>​ 
- 
-Exemple concrete: ​ 
- 
-**Intrați în directorul ~/​uso/​lab03/​simple-gcc** 
- 
-  - Compilarea unui program simplu: <code bash> gcc simple_hello.c -o simple_hello </​code>​ 
-  - Compilarea unui program simplu, și afișarea tuturor warning-urilor <code bash> gcc -Wall simple_hello.c -o simple_hello </​code>​ 
-  - Compilarea unui program, cu afisarea tuturor warning-urilor care are nevoie de legatura catre biblioteca matematica <code bash> gcc -Wall simple_hello.c -o math_hello -lm </​code>​ 
-  - Compilarea unui program, cu afișarea tuturor warning-urilor,​ din mai multe fișiere sursă <code bash> gcc -Wall hello.c utils.c help.c -o hello</​code>​ 
- 
-Paginile de ajutor ale [[http://​linux.die.net/​man/​1/​gcc|GCC]] (''​man gcc'',​ ''​info gcc''​) oferă o listă cu toate opțiunile posibile ale GCC. 
- 
-  
-===== Compilarea și link-editarea programelor===== 
- 
-== Separarea compilării de link-editare pentru obținerea unui fișier obiect == 
- 
-<code bash>gcc -c simple_hello.c -o hello-obj.o</​code>​ 
- 
-<​hidden>​ 
-Întrebări posibile adresate studenților:​ Ce credeți că s-a întâmplat acum? E fișier binar, de ce nu merge ''​./​hello-obj.o''?​ 
-</​hidden>​ 
- 
-La acest pas, obținem programul în limbaj ''​cod mașină'',​ cod care nu mai poate fi înțeles deloc de către oameni, fiind practic doar șiruri de biți 1/0. Acest tip de cod generat mai este cunoscut și sub numele de ''​cod obiect''​ și poate fi executat direct de către procesor. ​ 
- 
-Fișierul intermediar produs are extensia ''​.o''​. 
- 
-== Editare de legături(linking phase) == 
- 
-<code bash> gcc hello-obj.o -o hello </​code>​ 
- 
-Odată ce fișierul obiect este generat în etapa de asamblare, toate simbolurile (funcții, variabile globale etc) trebuie ''​rezolvate'',​ adică, de exemplu pentru funcții, trebuie găsită implementarea efectivă (corpul funcției) care se poate afla în alt fișier obiect sau într-o bibliotecă a sistemului. De exemplu atunci când scriem ''​printf(...)'',​ pentru a afișa un șir de caractere pe ecran, codul aferent funcției de bibliotecă ''​printf()''​ trebuie efectiv copiat în programul nostru sau măcar făcută o legătură către el (de aici și numele de editare de legături). De asemenea, dacă programul nostru constă din mai multe fișiere ''​.c'',​ fiecare dintre ele va produce câte un fișier obiect separat, dar în final noi vom obține un singur fișier și anume programul executabil. De legătura dintre fișierele obiect mai sus menționate se ocupă, bineînțeles,​ linkerul. ​   
- 
-==Executarea codului== 
- 
-Se face apelând din Bash (Terminal) fișierul executabil, folosind calea către acesta: ​ 
- 
-   - Fie relativă la directorul curent <code bash> 
-   ​student@midgard$:​ pwd 
-   /​home/​student/​uso/​lab03/​simple-gcc/​ 
-   ​student@midgard$:​ ./hello </​code>​ 
-   - Fie absolută <code bash> student@midgard$:​ /​home/​student/​uso/​lab03/​simple-gcc/​hello </​code>​ 
-    ​ 
-Exemplu: Putem rula ''​ls''​ folosind binarul din sistemul Linux. Încercați să executați comanda ''/​bin/​ls''​ :-) 
- 
-==Link-editarea mai multor fișiere obiect== 
- 
-Intrăm în directorul ''​~/​uso/​lab03/​simple-gcc''​ 
- 
-Separăm compilarea fișierului ''​help.c''​ de link-editare pentru a obține fișierului obiect ''​help.o''​. Pentru aceasta vom folosi comanda: 
- 
-<code bash> 
-student@midgard$:​ gcc -c help.c 
-student@midgard$:​ ls 
-errors.c ​ hello.c ​ help.c ​ help.o ​ Makefile ​ utils.c ​ utils.h ​ warnings.c simple_hello.c 
-</​code> ​ 
- 
-Observați crearea fișierului ''​help.o''​. Procedăm similar pentru ''​utils.c''​ și ''​hello.c'':​ 
- 
-<code bash> 
-student@midgard$:​ gcc -c utils.c 
-student@midgard$:​ gcc -c hello.c 
-student@midgard$:​ ls 
-errors.c ​ hello.c ​ hello.o ​ help.c ​ help.o ​ Makefile ​ simple_hello.c ​ utils.c ​ utils.h ​ utils.o ​ warnings.c 
-</​code> ​ 
- 
-Pentru a obține fișierul binar ''​hello'',​ care execută codul din corpul funcției ''​main''​ al fișierului sursă ''​hello.c''​ este nevoie să punem cap la cap toate cele 3 fișiere obiect, să le link-edităm: ​ 
- 
-<code bash> 
-student@midgard$:​ gcc utils.o help.o hello.o -o hello 
-student@midgard$:​ ls 
-errors.c ​ hello  hello.c ​ hello.o ​ help.c ​ help.o ​ Makefile ​ simple_hello.c ​ utils.c ​ utils.h ​ utils.o ​ warnings.c 
-student@midgard$:​ file hello 
-hello: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=54b686de038a29fed397f604403961f9d1086f76,​ not stripped 
-student@midgard$:​ ./hello 
-30 
-craaaaap 
-</​code>​ 
- 
-<​hidden>​ 
- 
-Grupelor mai avansate le puteți arăta despre optimizări: ​ 
- 
-=== Optimizări(extra) === 
- 
-''​GCC''​ pune la dispoziție câteva flaguri în spatele cărora se acund diferite grade de optimizări ale codului generat. Cele mai folosite sunt: 
-    * ''​-O0'',​ va determina compilatorul sã nu optimizeze codul generat; ​ 
-    * ''​-O3'',​ va determina compilatorul sã optimizeze la maxim codul generat; ​ 
-    * ''​-O2'',​ este pragul de unde compilatorul va începe sã insereze direct în cod functiile inline în loc sã le apeleze; ​ 
-    * ''​-Os'',​ va pune accentul pe optimizările pentru care duc la reducerea dimensiunii codului generat, si nu a vitezei la execuție. 
- 
-Descărcați fișierul de mai jos (îl găsiți și în repoul USO, în folderul gcc-optimizations,​ împreună cu un Makefile) și compilați-l folosind, pe rând, diferite grade de optimizare. Măsurați timpul de execuție de fiecare dată și arătați-le,​ în special, diferența uriașă de la O1 la O2. 
- 
-Vom folosi fișierul de mai jos pentru a evidenția diferite grade de optimizare. Pentru aceasta compilăm de 4 ori, cu flagurile ''​-O0'',​ ''​-O1'',​ ''​-O2''​ respectiv ''​-O3''​. Pentru fiecare variantă a programului măsurăm timpul de execuție pentru a putea compara performanțele. 
- 
-<columns 50% 50% -> 
- 
-<code c gcc-optimizations.c>​ 
-#include <​stdlib.h>​ 
-#include <​stdio.h>​ 
- 
-#define MAX_ITER 100000000 /* 100 million */ 
-#define N 4 
- 
-int main(void) 
-{ 
-    int i, j; 
-    long v[N] = {1, 2, 3, 4}; 
-    long w[N] = {4, 3, 2, 1}; 
- 
-    for (i = 0; i < MAX_ITER; ++i) 
-        for (j = 0; j < N; ++j) 
-            v[j] += w[j]; 
- 
-    return 0; 
-} 
-</​code>​ 
- 
-<​newcolumn>​ 
- 
-<code bash> 
-student@midgard$ gcc -Wall -O0 gcc-optimizations.c 
-student@midgard$ time ./a.out 
-./​a.out ​ 0.97s user 0.00s system 99% cpu 0.970 total 
- 
-student@midgard$ gcc -Wall -O1 gcc-optimizations.c 
-student@midgard$ time ./a.out 
-./​a.out ​ 0.34s user 0.00s system 99% cpu 0.341 total 
- 
-student@midgard$ gcc -Wall -O2 gcc-optimizations.c 
-student@midgard$ time ./a.out 
-./​a.out ​ 0.00s user 0.00s system 67% cpu 0.006 total 
- 
-student@midgard$ gcc -Wall -O3 gcc-optimizations.c 
-student@midgard$ time ./a.out 
-./​a.out ​ 0.00s user 0.00s system 65% cpu 0.006 total 
-</​code>​ 
- 
-</​columns>​ 
- 
-<note tip> 
-Utilitarul ''​time''​ poate fi folosit pentru a măsura timpul de execuție al unui proces. Observăm că el ne întoarce 3 măsurători,​ //user//, //system// și //total//. În general, ne interesează valoarea corespunzătoarele lui //total//, celealte reprezentând timpul consumat de către proces pe CPU în ''​user mode''​ respectiv ''​kernel mode''​. Mai multe detalii puteți găsi [[http://​en.wikipedia.org/​wiki/​User_space|aici]]. 
-</​note>​ 
- 
-</​hidden>​ 
- 
-<​hidden>​ 
- 
-Grupelor avansate le puteți arăta despre biblioteci 
- 
-=====Biblioteci====== 
- 
-O bibliotecă este o colecție de funcții precompilate. În momentul în care un program are nevoie de o funcție neinclusă în fișiere sursă proprii, linker-ul va apela respectiva funcție din bibliotecă. Numele fișierului reprezentând biblioteca trebuie să aibă prefixul **lib**: ​ 
- 
-<code bash> 
-student@midgard$ ls -l /​usr/​lib/​libm.* 
--rw-r--r-- 1 root root 496218 2010-01-03 15:19 /​usr/​lib/​libm.a 
-lrwxrwxrwx 1 root root     14 2010-01-14 12:17 /​usr/​lib/​libm.so -> /​lib/​libm.so.6 
-</​code>​ 
- 
-Biblioteca matematică este denumită ''​libm.a''​ sau ''​libm.so''​. În Linux bibliotecile sunt de două tipuri: 
- 
-Explicați pe scurt care e diferența, câteva avantaje și dezavantaje pentru fiecare. 
- 
-    * **statice** - au, de obicei, extensia ''​.a''​ sub Linux (''​.lib''​ în Windows) 
-    * **partajate** - au extensia ''​.so''​ sub Linux (''​.dll''​ în Windows) ​ 
- 
-Legarea se face folosind opțiunea ''​-l''​ transmisă comenzii ''​gcc''​. Astfel, dacă se dorește folosirea unor funcții din ''​math.h'',​ trebuie legată biblioteca matematică:​ 
-  
-Rulați în fața lor exemplul de mai jos. Mi se pare greu să înțeleagă din prima tot ce se întâmplă,​ dar tot cred că e mai bine decât să facă ei complet de capul lor. 
-<note warning> 
-Din câte am observat, pe sistemele din laborator comportamentul default este ca biblioteca matematică să fie deja încărcată,​ așa că e foarte posibil ca exemplul de mai jos să nu funcționeze. Dacă se întâmplă asta, mergeți în directorul ''​static-lib''​ din repo-ul USO și folosiți fișierul ''​simple_math.c''​ care are nevoie de biblioteca ''​libquadmath''​ (o legați cu -lquadmath). 
-</​note>​ 
- 
- 
-<columns 100% 50% -> 
-<code c cbrt.c> 
-#include <​stdio.h>​ 
-#include <​math.h>​ 
- 
-int main(void) 
-{ 
-   ​double x = 1000.0; 
-   ​printf("​Cubic root for %g is %g\n", x, cbrt(x)); 
-   ​return 0; 
-} 
-</​code>​ 
- 
-<​newcolumn>​ 
- 
-<code bash> 
- 
-student@midgard$ ls 
-cbrt.c 
-student@midgard$ gcc -Wall -o cbrt cbrt.c 
-/​tmp/​ccwvm1zq.o:​ In function `main':​ 
-cbrt.c:​(.text+0x1b):​ undefined reference to `cbrt' 
-collect2: ld returned 1 exit status 
-student@midgard$ gcc -Wall -o cbrt -lm cbrt.c 
-student@midgard$ ./​cbrt ​ 
-Cubic root for 1000 is 10 
-</​code>​ 
-</​columns>​ 
- 
-Se observă că, în primă fază, nu s-a rezolvat simbolul ''​cbrt''​. După legarea bibliotecii matematice, programul a fost compilat și rulat cu succes. 
- 
-</​hidden>​ 
- 
-=====Makefiles===== 
- 
-**Make** este un utilitar care permite automatizarea și eficientizarea sarcinilor. În mod particular este folosit pentru automatizarea compilării programelor. După cum s-a precizat, pentru obținerea unui executabil provenind din mai multe surse este ineficientă compilarea de fiecare dată a fiecărui fișier și apoi link-editarea. Se compilează fiecare fișier separat, iar la o modificare se va recompila doar fișierul modificat. 
- 
-=== Exemplu simplu de Makefile === 
- 
-<​hidden>​ 
-Cred că ar fi indicat ca Makefileul să fie scris //de mână// de către asistent pe proiector, pentru a lăsa mai mult timp studenților să observe ce se întâmplă de fapt. Ar putea fi puțin confuz, dacă le este efectiv //aruncat// în față un Makefile deja scris. 
- 
-După ce scrieți Makefileul, treceți prin toate etapele de mai jos, încercăm să le arătăm cât putem de mult de ce e bun, de ce 
-nu facem ''​Ctrl+R''​ -> ''​gcc''​ -> ''​Enter''​.  ​ 
-</​hidden>​ 
- 
-Utilitarul [[http://​linux.die.net/​man/​1/​make|make]] folosește un fișier de configurare denumit ''​Makefile''​. Un astfel de fișier conține reguli și comenzi de automatizare. ​ 
- 
-<columns 100% 50% 50% -> 
-<code make Makefile > 
-all: 
-       gcc -Wall hello.c -o hello 
-clean: 
-       rm -f hello 
-</​code>​ 
- 
-<​newcolumn>​ 
-  
-<code bash> 
- 
-student@midgard$ make 
-gcc -Wall hello.c -o hello 
-student@midgard$ ./hello 
-Hello, World! 
-</​code>​ 
- 
-<​newcolumn>​ 
- 
-<code bash> 
- 
-student@midgard$ make clean 
-rm -f hello 
-student@midgard$ make all 
-gcc -Wall hello.c -o hello 
-</​code>​ 
- 
-</​columns>​ 
- 
-<note warning> 
-Aveți grijă la separatorul folosit în cadrul unui fișier ''​Makefile''​. Liniile care conțin comenzi de compilare sunt indentate folosind ''​TAB'',​ nu ''​space''​. 
- 
-<code make Makefile>​ 
-main.o: main.c 
-<  TAB  >gcc -Wall -c main.c 
-</​code>​ 
-</​note>​ 
- 
-Exemplul prezentat mai sus conține două reguli: ''​all''​ și ''​clean''​. La rularea comenzii **''​make''​** se execută prima regulă din Makefile (în cazul de față ''​all'',​ nu contează în mod special denumirea). Comanda executată este ''​gcc -Wall hello.c -o hello''​. Se poate preciza explicit ce regulă să se execute prin transmiterea ca argument comenzii ''​make''​. (comanda **''​make clean''​** pentru a șterge executabilul ''​hello''​ și comanda **''​make all''​** pentru a obține din nou acel executabil). 
- 
- 
-=== Alt exemplu de Makefile === 
- 
-Intrați în directorul ''​~/​uso/​lab03/​simple-gcc''​. Amintiți-vă cele 4 comenzi gcc pe care le-am dat pentru a obține 3 fișiere obiect din sursele ''​utils.c'',​ ''​hello.c''​ și ''​help.c''​ și cea de a patra comanda pentru a link-edita cele 3 obiecte spre obținerea binarului. ​ 
- 
-Putem automatiza toți acești pași putem folosi fișierul ''​Makefile'':​ 
- 
-<code bash> 
-student@midgard$:​ make 
-gcc -c utils.c 
-gcc -c hello.c 
-gcc -c help.c 
-gcc utils.o help.o hello.o -o hello 
-student@midgard$:​ ls 
-errors.c ​ hello  hello.c ​ hello.o ​ help.c ​ help.o ​ Makefile ​ simple_hello.c ​ utils.c ​ utils.h ​ utils.o ​ warnings.c 
-student@midgard$:​ file hello 
-hello: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=54b686de038a29fed397f604403961f9d1086f76,​ not stripped 
-student@midgard$:​ ./hello 
-30 
-craaaaap 
-</​code>​ 
- 
-Urmăriți dependențele între reguli din fișierul ''​~/​uso/​lab03/​simple-gcc/​Makefile'':​ 
- 
-<code make Makefile>​ 
-build: utils.o hello.o help.o 
-        gcc utils.o help.o hello.o -o hello 
- 
-all: 
-        gcc simple_hello.c -o simple 
- 
-utils.o: utils.c 
-        gcc -c utils.c 
- 
-hello.o: hello.c 
-        gcc -c hello.c 
- 
-help.o: help.c 
-        gcc -c help.c 
- 
-clean: 
-        rm -f *.o hello 
-</​code>​ 
- 
-<​hidden>​ 
-Explicați cum fiecare regulă depinde de alte reguli care, în final, depind de fișiere și de modificările din acestea. ​ 
-</​hidden>​ 
- 
- 
- 
-<​hidden>​ 
-Grupelor mai avansate le puteți arăta de flagul ''​-f''​. 
- 
-În mod implicit, GNU Make caută, în ordine, fișierele GNUmakefile,​ Makefile, makefile și le analizează. Pentru a preciza ce fișier Makefile trebuie analizat, se folosește opțiunea **''​-f''​**. Astfel, în exemplul de mai jos, folosim fișierul Makefile.ex1:​ 
-  
-<code bash> 
-student@midgard$ mv Makefile Makefile.ex1 
-student@midgard$ make 
-make: *** No targets specified and no makefile found. ​ Stop. 
-student@midgard$ make -f Makefile.ex1 
-gcc -Wall hello.c -o hello 
-student@midgard$ make -f Makefile.ex1 clean 
-rm -f hello 
-</​code>​ 
-</​hidden>​ 
- 
- ​====== Exerciții ====== 
- 
-<​note>​ 
-Intrați în directorul ''/​home/​student''​. Dacă nu ați clonat deja la secțiunea demo [[https://​github.com/​systems-cs-pub-ro/​uso|repository-ului oficial uso]], atunci clonați-l acum folosind coamnda:<​code bash> 
-student@uso:​~$ git clone https://​github.com/​systems-cs-pub-ro/​uso ​ 
-</​code> ​ 
- 
-În directorul ''​~/​uso/​lab03''​ găsiți fișierele necesare pentru rezolvarea acestui laborator. 
-</​note>​ 
- 
-<note tip>​Recomandăm rezolvarea exercițiilor pe mașina virtuală USO pe care o veți avea și la teme și la testul practic. Informații pas cu pas despre importul și pornirea acesteia se află în secțiunea [[:​uso:​resurse:​mv|Mașina virtuală]]. 
- 
-Pentru acest laborator putem porni la lucru cu mașina cu interfață grafică, aceasta se află în ''/​mnt/​unfrozen''​. Drept urmare importăm fișierul ''/​mnt/​unfrozen/​uso_2016_2017_gnome.ova''​ 
- 
-</​note>​ 
-==== 0.0. Verificarea conturilor (0.5p) ==== 
- 
-<note important>​ 
-Raportați probleme cu conturi pe platforma [[https://​support.curs.pub.ro/​|https://​support.curs.pub.ro/​]] 
-</​note>​ 
- 
-Pe parcursul USO și al facultății avem nevoie să fim siguri că vă funcționează conturile în mai multe locuri. Avem următorul checklist 
- 
-  - Intrați pe platforma [[http://​studenti.pub.ro|http://​studenti.pub.ro]]. Parola initiala pentru anul 1 este student + ultimele 6 cifre din CNP sau pasaport. Schimbati parola dupa prima autentificare. ​ 
-  - Pentru a afla user-ul de acces la [[http://​cs.curs.pub.ro|http://​cs.curs.pub.ro]] accesati pagina "Acces site cursuri"​ de pe http://​studenti.pub.ro de la punctul 1 
-  - Au fost create e-mail-urile oficiale pentru studenti din partea UPB. E-mail-ul este de forma user_curs@stud.acs.upb.ro si poate fi accesat de la adresa http://​outlook.com/​upb.ro. Pentru a se activa, trebuie sa schimbati cel putin o data parola folosind platforma de cursuri (http://​cs.curs.pub.ro). Activarea se va realiza in aproximativ 3 ore. E-mail-ul se acceseaza cu aceeasi parola cu cea a site-ului de cursuri. 
- 
-==== 0.1. Conectarea la eduroarm (1 karma WoUSO) ==== 
- 
-Puteți accesa internetul Wireless din facultate prin platforma [[http://​eduroam.pub.ro/​wiki/​|eduroarm]] Conectarea în rețeaua eduroam se face pe baza aceluiași cont folosit și pe site-ul de cursuri. Pentru rețeaua eduroam datele de identificare vor fi de forma: 
- 
-<code bash> 
-utilizator eduroam: <​utilizator-cursuri>​@pub.ro 
-parola: <​parola-cursuri>​ 
-</​code>​ 
- 
-unde ''<​utilizator-cursuri>''​ și ''<​parola-cursuri>''​ vor fi înlocuite cu datele de autentificare pe site-ul de cursuri http://​cs.curs.pub.ro 
- 
-<note important>​Înainte de prima autentificare în rețeaua eduroam este nevoie ca date dvs. de conectare să fie sincronizate cu serverul de autentificare. Acest lucru se poate face printr-o schimbare a parolei în cadrul site-ului de cursuri. Puteți efectua două schimbări ale parolei, pentru a reveni la parola inițială. 
- 
-**Unii dintre voi ați făcut probabil acest pas la exercițiul 0.0. sau în laboratorul 1 pentru sincronizarea cu contul de email** 
- 
-Procedurile de conectare sub Linux, respectiv sub Android sunt descrise pe [[http://​eduroam.pub.ro/​wiki/​|wiki-ul eduroarm]] in linkurile de mai jos:  
- 
-  * [[http://​eduroam.pub.ro/​wiki/​tutoriale/​gnome|Eduroarm Linux Gnome tutorial]] 
-  * [[http://​eduroam.pub.ro/​wiki/​tutoriale/​lollipop|Eduroarm Android Lolliop tutorial]] 
- 
-</​note>​ 
-===== [1] Compilarea unui fișier sursă C (0.5p) ===== 
-Pentru a rezolva următoarea serie de exerciții mergeți în directorul ''/​home/​student/​uso/​lab03/​simple-gcc''​. Pentru aceasta 
-folosim următoarea comandă ''​cd ~/​uso/​lab03/​simple-gcc''​. În directorul ''​simple-gcc''​ găsiți fișierul sursă ''​simple_hello.c''​. Compilați-l,​ folosind ''​gcc'',​ într-un fișier executabil denumit ''​hello''​. Pentru aceasta folosim următoarea comandă: 
-<code bash> 
-student@midgard$ gcc simple_hello.c -o hello 
-</​code>​ 
- 
-Rulați executabilul proaspăt obținut. 
-<code bash> 
-student@midgard$ ./hello 
-Hello, World 
-</​code>​ 
- 
-Repetați procesul de mai sus, dar de data aceasta obțineți un executabil cu numele ''​salut''​. Acum îl rulăm și observăm că am obținut exact același lucru ca mai sus. Cele două fișiere par identice, dar ca să ne asigurăm folosim comanda ''​cmp''​. 
- 
-<​solution -hidden> 
-<code bash> 
-student@midgard:​~$ gcc simple_hello.c -o salut 
-student@midgard:​~$ ./salut 
-Hello, World 
-student@midgard:​~$ cmp salut hello 
-</​code>​ 
- </​solution>​ 
- 
-<note tip> 
-Folosiți cunoștințele din laboratorul precedent și căutați în pagina de manual a comenzii ''​cmp''​ folosind comanda: 
-<code bash> man cmp </​code>​ 
- 
-Dacă în urma rulării comenzii ''​cmp''​ cu parametrii corespunzător nu se va afișa nimic înseamnă că cele două fișiere sunt identice. 
-</​note> ​ 
- 
-Observăm că cele două fișiere sunt într-adevăr identice, acest lucru datorându-se faptului că procesul de compilare este unul determinist (o bucată de cod sursă C se va //traduce// mereu în exact aceleași instrucțiuni în limbaj de asamblare și apoi în cod mașină - dacă se păstrează același grad de optimizare). 
-===== [2] Detectarea și corectarea warning-urilor (1p) ===== 
-În același director ca mai sus, ''/​home/​student/​uso/​lab03/​simple-gcc'',​ găsim fișierul ''​warnings.c''​. Compilați-l folosind următoarea comandă: 
- 
-<code bash> 
-student@midgard$ gcc warnings.c -o warnings 
-student@midgard$ ./warnings 
-a + b = 5 
-</​code>​ 
- 
-Observăm că fișierul a fost compilat și rulat cu succes. Repetați comanda de mai sus, dar folosiți de această dată flagul ''​-Wall''​ pentru comanda ''​gcc'',​ ca mai jos: 
- 
-<code bash> 
-student@midgard$ gcc -Wall warnings.c -o warnings 
-warnings.c: In function ‘main’: 
-warnings.c:​8:​ warning: unused variable ‘c’ 
-</​code>​ 
- 
-Vedem totuși că de data aceasta a fost identificată o problemă cu fișierul ''​warnings.c''​ și anume că variabila ''​c''​ a fost declarată, inițializată,​ dar nefolosită. Acest fapt nu afectează comportamentul programului nostru, dar, în general, e bine să le evităm pe cât posibil. ​ 
- 
-Inspectați fișierul sursă ''​warnings.c''​ și corectați warningul. Rulați din nou comanda ''​gcc -Wall warnings.c -o warnings''​ până când nu mai primiți niciun warning la compilare. 
- 
-<​solution -hidden> 
-<code C warnings.c>​ 
-#include <​stdlib.h>​ 
-#include <​stdio.h>​ 
- 
-int main(void) 
-{ 
- int a = 2; 
- int b = 3; 
- 
- printf("​a + b = %d\n", a + b); 
- 
- return 0; 
-} 
-</​code>​ 
-<code bash> 
-student@midgard$ gcc -Wall warnings.c -o warnings 
-student@midgard$ ./warnings 
-a + b = 5 
-</​code>​ 
- 
-</​solution>​ 
- 
-===== [3] Detectarea și corectarea erorilor de compilare (1p) ===== 
-În același director ca mai sus, ''/​home/​student/​uso/​lab03/​simple-gcc'',​ găsim fișierul ''​errors.c''​. Compilați-l folosind următoarea comandă: 
-<code bash> 
-student@midgard$ gcc -Wall errors.c -o errors 
-errors.c: In function ‘main’: 
-errors.c:7: error: expected ‘;’ before ‘return’ 
-student@midgard$ ls errors 
-ls: cannot access errors: No such file or directory 
-</​code>​ 
- 
-Observăm că de această dată nu a mai fost obținut niciun fișier executabil, întrucât în fișierul ''​errors.c''​ au fost detectate **erori de sintaxă**. Cea identificată în cazul nostru este la linia 7 și anume că înaintea instrucțiunii ''​return''​ lipsește caracterul '';''​. Modificați fișierul ''​errors.c''​ astfel încât acesta să fie compilat și rulat cu succes. 
- 
-<​solution -hidden> 
-<code C errors.c>​ 
-#include <​stdlib.h>​ 
-#include <​stdio.h>​ 
- 
-int main(void) 
-{ 
- puts("​Hello World!"​);​ 
- 
- return 0; 
-} 
-</​code>​ 
-<code bash> 
-student@midgard:​~$ gcc -Wall errors.c -o errors 
-student@midgard:​~$ ./errors 
-Hello World! 
-</​code>​ 
-</​solution>​ 
- 
-===== [4] Detectarea și corectarea erorilor de linkare (1.5p) ===== 
- 
-Mergeți în directorul ''/​home/​student/​uso/​lab03/​tema-pc'',​ unde găsim 4 fișiere. Pentru acest exercițiu ignorați fișierul ''​Makefile'',​ ne interesează numai ''​tema.c'',​ ''​utils.c''​ și ''​utils.h''​. 
- 
-Inspectăm fișierul ''​tema.c''​ folosind un editor sau comanda ''​cat tema.c''​ și vedem că folosește două funcții (''​vect_gt''​ și ''​vect_lt''​) care nu apar definite nicăieri. Observăm totuși că este inclus fișierul ''​utils.h'',​ iar dacă ne uităm în acesta vom vedea că cele două funcții sunt declarate totuși acolo. 
- 
-Încercăm să compilăm fișierul ''​tema.c''​ așa cum am învățat până acum: 
-<code bash> 
-student@midgard$ gcc tema.c 
-/​tmp/​cc7oBohY.o:​ In function `main':​ 
-tema.c:​(.text+0xac):​ undefined reference to `vect_gt'​ 
-tema.c:​(.text+0xdb):​ undefined reference to `vect_lt'​ 
-collect2: ld returned 1 exit status 
-</​code>​ 
- 
-Din păcate, procesul de compilare eșuează în etapa de linking, chiar dacă noi avem cele două funcții declarate în fișierul ''​utils.h'',​ iar acesta este inclus în fișierul principal ''​tema.c''​. 
- 
-Compilați fișierul ''​tema.c''​ numai până la codul obiect (până la etapa de linkare), folosind flagul ''​-c''​. Comanda necesară pentru acest lucru este: 
-<code bash> 
-student@midgard$ gcc -Wall -c tema.c 
-</​code>​ 
- 
-Repetați același lucru pentru fișierul ''​utils.c''​ și obțineți fișierul obiect ''​utils.o''​. Putem obține acum fără probleme executabilul nostru, dacă //linkăm// cele două fișiere obiect. Facem asta cu comanda: 
-<code bash> 
-student@midgard$ gcc tema.o utils.o -o tema 
-student@midgard$ ./tema 
-Values: 10 -20 30 9 7 8 11 5 -2 100  
-Values greater than 5: 7 
-Values less than 3: 2 
-</​code>​ 
- 
-<note tip> 
-Puteam realiza același lucru de la început folosind direct comanda: 
-<code bash> 
-student@midgard$ gcc -Wall tema.c utils.c -o tema 
-</​code>​ 
-</​note>​ 
- 
-Deschideți în editorul preferat fișierul ''​tema.c''​ și realizați o modificare minoră, de exemplu modificați valoarea lui ''​N''​ din 9 în 5. Compilați din nou fișierul ''​tema.c''​ pentru a obține fișierul obiect ''​tema.o''​. La fel ca mai sus, //​linkați//​ fișierele obiect ''​tema.o''​ și ''​utils.o''​ pentru a obține executabilul ''​tema'',​ după care rulați-l. Observăm că nu a mai fost nevoie de recompilarea fișierului ''​utils.c'',​ am folosit fișierul obiect obținut anterior. 
- 
-<​solution -hidden> 
-<code C tema.c> 
-#include <​stdlib.h>​ 
-#include <​stdio.h>​ 
- 
-#include "​utils.h"​ 
- 
-/* UNUSEFUL CHANGE */ 
- 
-#define N 9 
- 
-int main(void) 
-{ 
- int i, v[] = {10, -20, 30, 9, 7, 8, 11, 5, -2, 100}; 
- 
- printf("​Values:​ "); 
- for (i = 0; i <= N; ++i) { 
- printf("​%d ", v[i]); 
- } 
- printf("​\n"​);​ 
- 
- printf("​Values greater than %d: %d\n", MIN_VAL, vect_gt(v, N, MIN_VAL)); 
- printf("​Values less than %d: %d\n", MAX_VAL, vect_lt(v, N, MAX_VAL)); 
- 
- return 0; 
-} 
-</​code>​ 
-<code bash> 
-student@midgard:​~$ gcc -c tema.c 
-student@midgard:​~$ gcc tema.o utils.o -o tema 
-student@midgard:​~$ ./tema 
-Values: 10 -20 30 9 7 8 11 5 -2 100  
-Values greater than 5: 7 
-Values less than 3: 2 
-</​code>​ 
-</​solution>​ 
- 
-<note tip>Un mare avantaj al opririi procesului de compilare înainte de **etapa de linkare** este faptul că putem //​refolosi//​ fișiele obiect. Dacă avem un proiect mare cu numeroase fișiere sursă și realizăm o modificare într-un singur fișier sursă, nu este nevoie sa compilăm de fiecare dată toate fișierele, ci numai cel modificat, fiind astfel suficient doar să le relinkăm la final. Cum putem exploata acest lucru vom observa în exercițiile următoare. 
-</​note>​ 
-===== [5] Compilarea temei folosind Makefile (2p) ===== 
- 
-Intrați în directorul ''/​home/​student/​uso/​lab03/​tema-pc''​. Dorim să compilăm tema la programare folosind fișierul ''​Makefile''​. Rulați comanda ''​make''​. 
- 
-Rulați încă o dată comanda ''​make''​. S-a mai executat vreo comandă? 
- 
-<​solution>​ 
-<code bash> 
-student@midgard:​~$ make 
-gcc -Wall -c tema.c 
-gcc -Wall -c utils.c 
-gcc -Wall tema.o utils.o -o tema 
-student@midgard:​~$ make 
-make: Nothing to be done for `all'. 
-</​code>​ 
- 
-</​solution>​ 
- 
-Schimbați valoarea macro-ului ''​MIN_VAL''​ în fișierul ''​utils.h''​. Rulați încă o dată comanda ''​make''​. De ce nu se actualizează fișierul executabil? Modificați fișierul ''​Makefile''​ pentru ca obținerea fișierelor obiect (cu extensia ''​.o''​) să țină cont și de fișierele header (cu extensia ''​.h''​) de care acestea depind. 
- 
- 
-<note tip> 
-Revedeți [[#​makefiles|secțiunea de Makefiles]] din suportul laboratorului. 
-</​note>​ 
- 
-<​solution>​ 
-<code C utils.h> 
-#define MIN_VAL 8 // in loc de 5 
-#define MAX_VAL 3 
- 
-int vect_gt(int*,​ int, int); 
-int vect_lt(int*,​ int, int); 
-</​code>​ 
- 
-<code bash> 
-student@midgard:​~$ make 
-make: Nothing to be done for `all'. 
-student@midgard:​~$ ./tema 
-Values: 10 -20 30 9 7 8 11 5 -2 100  
-Values greater than 5: 7 
-Values less than 3: 2 
-</​code>​ 
- 
-<code make Makefile>​ 
-all: tema 
- 
-tema: tema.o utils.o 
- gcc -Wall tema.o utils.o -o tema 
- 
-tema.o: tema.c utils.h 
- gcc -Wall -c tema.c 
- 
-utils.o: utils.c 
- gcc -Wall -c utils.c 
- 
-run: tema 
- ./tema 
- 
-clean: 
- rm -f *.o *~ tema 
-</​code>​ 
-<code bash> 
-student@midgard:​~$ make                                                  ​ 
-gcc -Wall -c tema.c 
-gcc -Wall tema.o utils.o -o tema 
-student@midgard:​~$ ./tema 
-Values: 10 -20 30 9 7 8 11 5 -2 100  
-Values greater than 8: 5 
-Values less than 3: 2 
-</​code>​ 
-</​solution>​ 
- 
- 
-===== [6] Makefile pentru un proiect (2p) ====== 
- 
-În directorul ''/​home/​student/​uso/​lab03/​large-project''​ găsiți o structură de fișiere și directoare care simulează un proiect software mai mare (mai multe fișiere sursă, împărțit pe funcționalități etc). Structura proiectului nostru este următoarea:​ 
- 
-<code bash> 
-student@midgard$:​ tree 
-. 
-├── Makefile 
-├── main.c 
-├── sum 
-│   ├── add 
-│   │   ├── add.c 
-│   │   └── add.h 
-│   ├── sum.c 
-│   └── sum.h 
-└── utils 
-    ├── utils.c 
-    └── utils.h 
- 
-3 directories,​ 8 files 
-</​code>​ 
- 
-Practic, modulul **main** depinde de modulele **sum** și **utils**, iar modulul **sum** depinde și el la rândul lui de modulul **add**. 
- 
-Completați fișierul ''​Makefile''​ din rădăcina proiectului astfel încât la rularea comenzii ''​make all''​ toate fișierele sursă ''​.c''​ vor fi compilate și va fi obținut executabilul ''​main''​. Înlocuiți liniile care conțin ''#​TODO''​ cu comenzile necesare pentru compilare. 
- 
-<​note>​ 
-Urmăriți ca model și fișierul ''​Makefile''​ de la [[#​compilarea_temei_folosind_makefile_2p|exercițiul 5]]. 
-</​note>​ 
- 
- 
-<​solution -hidden> 
-<code make Makefile>​ 
-all: main 
- 
-main: main.o sum/sum.o sum/​add/​add.o utils/​utils.o 
- gcc -Wall main.o sum/sum.o sum/​add/​add.o utils/​utils.o -o main 
- 
-main.o: main.c 
- gcc -c main.c 
- 
-sum/sum.o: sum/sum.c 
- gcc -c sum/sum.c -o sum/sum.o 
- 
-sum/​add/​add.o:​ sum/​add/​add.c 
- gcc -c sum/​add/​add.c -o sum/​add/​add.o 
- 
-utils/​utils.o:​ utils/​utils.c 
- gcc -c utils/​utils.c -o utils/​utils.o 
- 
-clean: 
- rm -f main main.o sum/sum.o sum/​add/​add.o utils/​utils.o *~ 
-</​code>​ 
-<code bash> 
-student@midgard:​$~ make 
-gcc -c main.c 
-gcc -c sum/sum.c -o sum/sum.o 
-gcc -c sum/​add/​add.c -o sum/​add/​add.o 
-gcc -c utils/​utils.c -o utils/​utils.o 
-gcc -Wall main.o sum/sum.o sum/​add/​add.o utils/​utils.o -o main 
-student@midgard:​$~ ./main 
-{vector: 
- { 
- integer: 1 
-... 
-</​code>​ 
-</​solution>​ 
- 
- 
-===== [7] Scrierea unui Makefile (1p) ===== 
-În directorul ''/​home/​student/​uso/​lab03/​project''​ se află două fișiere sursă, ''​project.c''​ și ''​functions.c''​. Fișierul project.c conține funcția ''​main''​ ce apelează o funcție denumită ''​f''​ și definită în fișierul ''​functions.c''​. Observăm că la rularea unei comenzi simple de compilare se obține un warning: 
- 
-<code bash> 
-student@uso:​~/​uso/​lab03/​project$ gcc -Wall functions.c project.c ​ 
-project.c: In function ‘main’: 
-project.c:​6:​5:​ warning: implicit declaration of function ‘f’ [-Wimplicit-function-declaration] 
-     f(); 
-     ^ 
-</​code>​ 
-Acest lucru se datorează faptului că funcția ''​f''​ este chemată fără a fi declarată. Pentru a evita această problemă trebuie să-i //​promitem//​ compilatorului că funcția ''​f''​ va exista la un moment ulterior definită (cu același nume, același tip de retur, același număr de parametri). 
- 
-Creați un fișier header ''​functions.h''​ în care să **declarați** funcția ''​f''​ după care includeți fișierul ''​functions.h''​ în ''​project.c''​. Observați că warningul de mai sus a dispărut. 
- 
-<code bash> 
-student@uso:​~/​uso/​lab03/​project$ gcc -Wall functions.c project.c 
-student@uso:​~/​uso/​lab03/​project$ 
-</​code>​ 
- 
- 
-În continuare, creați un fișier ''​Makefile''​ folosind editorul ''​vim'',​ în același folder, care să conțină, cel puțin, câte o regulă de compilare până la fișiere obiect pentru fiecare fișier ''​.c''​ și o regulă ''​clean''​ care șterge fișierele obiect și executabilul obținut în urma comenzii ''​make''​. De asemenea, scrieți ''​Makefileul''​ astfel încât la rularea mai multor comenzi ''​make''​ consecutive,​ proiectul să nu fie recompilat de fiecare dată. 
- 
-<​hidden>​ 
-Le puteți acorda punctajul complet dacă au făcut ''​Makefileul''​ ok, mai puțin partea de %%"​nerecompilare"​%%. Totuși, nu-i lăsați să scape așa ușor, măcar arătați-le voi cum trebuie făcut. 
-</​hidden>​ 
- 
-===== [BONUS #1] Variabile în Makefile (2 Karma WoUSO) ===== 
- 
-Un fișier ''​Makefile''​ permite folosirea de variabile. Astfel, un exemplu uzual de fișier ''​Makefile''​ este: 
-  
-<code make Makefile>​ 
-CC = gcc 
-CFLAGS = -Wall -g 
- 
-all: hello 
- 
-hello: hello.o 
-        $(CC) hello.o -o hello 
- 
-hello.o: hello.c 
-        $(CC) $(CFLAGS) -c hello.c 
- 
-clean: 
-        rm *.o hello 
-</​code>​ 
- 
-În exemplul de mai sus au fost definite variabilele ''​CC''​ și ''​CFLAGS''​. Variabila ''​CC''​ reprezintă compilatorul folosit, iar variabila ''​CFLAGS''​ reprezintă opțiunile (flag-urile) de compilare utilizate; în cazul de față sunt afișarea avertismentelor și compilarea cu suport de depanare. Referirea unei variabile se realizează prin intermediul construcției %%$%%(VAR_NAME). Astfel, ''​%%$%%(CC)''​ se înlocuiește cu ''​gcc'',​ iar ''​%%$%%(CFLAGS)''​ se înlocuiește cu ''​-Wall -g''​. 
- 
-Observăm că șirurile ''​hello'',​ ''​gcc'',​ precum și flagurile date la compilare apar în foarte multe locuri. Modificați fișierul ''​Makefile''​ astfel încât să avem de schimbat o singură linie în cazul în care dorim să schimbăm numele executabilului,​ compilatorului sau să mai adăugăm un alt flag. 
- 
-Modificați fișierul ''​Makefile''​ din directorul ''/​home/​student/​uso/​lab03/​tema-pc''​ astfel încât să folosiți în cadrul fiecărei reguli variabilele predefite: 
-  * ** %%$%%@ ** se expandează la numele target-ului. ​ 
-  * ** %%$%%^ ** se expandează la lista de cerințe. 
-  * ** %%$%%< ** se expandează la prima cerință. ​ 
- 
-<note tip> 
-Motivul utilizării acestora nu este pentru a reduce dimensiunea Makefile sau pentru a îl //​obfusca//,​ ci pentru a evita cât mai mult posibil repetițiile,​ minimizând în acest fel și potențialele erori ce pot apărea în viitor. Spre exemplu, dacă în cadrul unei reguli se adaugă ca dependență un fișier sursă ''​.c''​ nou, nu mai este nevoie să fie trecut și pe linia următoare corespunzătoare comenzii de compilare. El va fi automat expandat din variabila %%$%%^. 
-</​note>​ 
- 
-===== [BONUS #2] Investigarea bibliotecilor externe folosite (1 Karma WoUSO) ===== 
-În directorul ''/​home/​student/​uso/​lab03/​static-lib''​ aveți fișierele ''​simple_math.c''​ și ''​Makefile''​. Rulăm comanda ''​make''​ și observăm că primim o eroare **de linking** (în etapa de link-editare) 
- 
-<code bash> 
-student@midgard$:​ make 
-gcc -Wall simple_math.o -o simple_math ​ 
-simple_math.o:​ In function `main':​ 
-simple_math.c:​(.text+0x1e):​ undefined reference to `sqrtq'​ 
-simple_math.c:​(.text+0x3c):​ undefined reference to `quadmath_snprintf'​ 
-collect2: error: ld returned 1 exit status 
-make: *** [simple_math] Error 1 
-</​code>​ 
- 
-Eroarea provine de la faptul că două simboluri, și anume ''​sqrtq''​ și ''​quadmath_snprintf''​ au fost utilizate, declarate, dar nu au fost și definite. Pentru a rezolva problema avem nevoie să legăm biblioteca statică ''​libquadmath''​ la codul nostru. 
- 
-Modificați linia din ''​Makefile''​ care obține fișierul executabil ''​simple_math''​ astfel încât să legați biblioteca statică ''​libquadmath''​. 
- 
-<note tip> 
-Revedeți [[http://​ocw.cs.pub.ro/​courses/​uso/​laboratoare/​laborator-03#​biblioteci|secțiunea de biblioteci]] din cadrul demo-ului. Mai multe informații despre biblioteca ''​quadmath''​ puteți afla de [[https://​gcc.gnu.org/​onlinedocs/​libquadmath/​|aici]]. 
-</​note>​ 
- 
-===== [Bonus #3] Instalarea și compilarea din surse (2 Karma WoUSO) ===== 
- 
-Vrem să compilăm și să instalăm un program din cod sursă (adică nu dintr-un pachet). 
- 
-Descărcați Python 2.7.8 de [[http://​python.org/​download/​releases/​2.7.8/​|aici]]. Alegeți formatul corespunzător sistemului pe care lucrați. 
- 
-Următorii pași se aplică, în general, la compilarea din surse: 
-<code bash> 
-student@midgard ~ $ ./​configure ​ 
-student@midgard ~ $ make 
-student@midgard ~ $ make install 
-</​code>​ 
  
-Etapa de configurare dispune de un parametru special<​code bash+{{page>uso:​laboratoare:​laborator-03:​io_redirection&​nofooter&​noeditbutoon}} 
-./​configure ​--prefix=/​path/​to/​my/​custom/​folder +{{page>​uso:​laboratoare:​laborator-03:​archive&​nofooter&​noeditbutoon}} 
-</codeîn care putem specifica directorul de instalare. Folosiți această opţiune deoarece dorim să nu afectăm versiunea de Python a sistemului. Folosiți o cale absolută către un director din ''/​home/​student''​. ​+{{page>​uso:​laboratoare:​laborator-03:​file_system&​nofooter&​noeditbutoon}} 
 +{{page>uso:​laboratoare:​laborator-03:​cheatsheet&​nofooter&​noeditbutoon}}
  
-<note warning>​ +==== Cuprins ====
-Dacă doriți instalare ca utilizator neprivilegiat (fără a prefixa comanda cu ''​sudo'',​ vom învăța amănunte într-unul din laboratoarele viitoare), trebuie să folosiți opțiunea ''<​nowiki>​--</​nowiki>​prefix''​ a comenzii ''​./​configure''​ și să transmiteți un director la care utilizatorul are acces. În absența acestei opțiuni instalarea se face, în general, în directoare precum ''/​usr/​bin/''​ și ''/​usr/​lib/'',​ unde doar utilizatorul privilegiat (''​root''​) are acces. +
-</​note>​+
  
-===== [Bonus #4] Good code practices (1-5 Karma WoUSO) ===== +{{page>uso:laboratoare:​laborator-03:​nav&noheader&nofooter&​noeditbutton}}
-<hidden> +
-Punctați de la 1 la 5 în funcție de cât de multe probleme au rezolvat. Câteva exemple ar fi: +
-  * indentare corectă +
-  * eliminarea liniilor goale fără rost +
-  * spații la ''​int a = 1''​ +
-  * un singur ''​if''​ cu ''​&&''​-uri în loc de 3 +
-  * o buclă de la 0 la 7 în loc de a scrie de 8 ori același lucru +
-  * ''​return 0''​ la final +
-  * ''​int main(void)''​ sau ''​int main(int argc, char *argv[])''​ +
-  * split la 80 de caractere pe linia cu printf +
-  * etc etc +
-</​hidden>​+
  
-E bine ca atunci când scriem cod să fie cât mai organizat, aerisit, cât mai ușor de înțeles de către altcineva. În directorul ''/​home/​student/​uso/​lab03/​ugly''​ găsiți fișierul ''​ugly.c''​ care este scris intenționat într-un mod foarte confuz și alambicat. Citiți articolul de la acest [[http://​programmer.97things.oreilly.com/​wiki/​index.php/​Write_Code_for_Humans_not_Machines|link]] după care modificați fișierul ''​ugly.c''​ conform principiilor prezentate, păstrând însă exact aceeași funcționalitate. 
uso/laboratoare/laborator-03.1476603521.txt.gz · Last modified: 2016/10/16 10:38 by mbarbulescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0