Opis
U ovom tutorijalu ćemo napisati minimalni C program i kompajlirati ga: prvo ručno, a zatim i pomoću Makefile datoteke.
Video
C program
Ovo je listing programa koji je korišćen:
- Kod: Obeleži sve
#include <stdio.h>
int main(int argc, char **argv)
{
puts("Zdravo Slakver svete!");
return 0;
}
Pokušaću da ukratko objasnim (bez namere da dublje ulazim u opisivanje C programskog jezika).
C ima ograničeni skup naredbi. Sve ostalo je potrebno dodatno uključiti u program. U ovom slučaju uključujemo stdio.h koji sadrži funkcije za standardne ulazno-izlazne operacije. U ovoj datoteci je definisana naredba puts (napiši string).
- Kod: Obeleži sve
#include <stdio.h>
C programi sadrže jednu glavnu funkciju koja se zove main. Main funkcija je standardizovana i postoji nekoliko predefinisanih načina na koje može da se napiše. Parametri argc i argv se odnose na unos sa komandne linije. Pošto ovaj program ne prima unos, main je mogla da se napiše i kao: int main(void). Primetićete da je telo funkcije zaokruženo između dve uglaste zagrade ("{" i "}").
- Kod: Obeleži sve
int main(int argc, char **argv)
Naredba puts prikazuje tekst na standardnom izlazu. Ovde prikazujemo string "Zdravo Slakver svete!".
- Kod: Obeleži sve
puts("Zdravo Slakver svete!");
Pošto main funkcija vraća vrednost, koristimo naredbu return. Parametar "0" (nula) označava da je program uspešno izvršen. Ovaj parametar može da poprimi bilo koju celobrojnu vrednost u okviru granica "int" tipa podataka.
- Kod: Obeleži sve
return 0;
Kompajliranje
Da bi od ove tekstualne datoteke dobili program, potrebno ga je prethodno kompajlirati. Kompajliranje podrazumeva prevođenje u binarni oblik. Obično se izvorni kod kompajlira u privremeni objektni format, a zatim se objektne datoteke povezuju, tj. linkuju u izvršni program.
Tako pozivanje gcc kompajlera sa opcijom "-c" kreira objektnu datoteku proba.o:
- Kod: Obeleži sve
gcc -c proba.c
To možemo i proveriti tako što izlistamo sadržaj trenutnog direktorijuma.
- Kod: Obeleži sve
ls
proba.c proba.o
Ovaj program se zatim linkuje. Postoji zaseban program za ovu namenu koji se zove linker (ld na *niks sistemima), ali se on retko koristi direktno. Umesto toga pozvaćemo kompajler sa odgovarajućim opcijama, a kompajler će automatski pozvati linker sa odgovarajućim opcijama. Da u ovom programu koristimo spoljne biblioteke, parametre bi prosledili linkeru kroz opcije kompajlera (najčešće korišćene "-l", "-L" i "-s" opcije).
Elem, u ovom slučaju, dovoljno je otkucati samo:
- Kod: Obeleži sve
gcc -o proba proba.o
Kreiran je izvršni program proba.
- Kod: Obeleži sve
ls
proba proba.c proba.o
Sada možemo i testirati program
- Kod: Obeleži sve
./proba
S obzirom da se ovaj program sastoji samo od jedne datoteke, generisanje objektne datoteke možemo i preskočiti. Tako GCC kompajler možemo pokreniti i na ovaj način:
- Kod: Obeleži sve
gcc -o proba proba.c
Da bismo obrisali izvršni program i objektne datoteke, koristimo standarni *niks program za brisanje datoteka "rm":
- Kod: Obeleži sve
rm proba proba.o
Makefile
Ovaj proces možemo automatizovanje korišećenjem alatke make. Make čita posebnu tekstualnu datoteku koja se zove Makefile i na osnovu pravila u njoj izgrađuje program. Pored izgradnje, make se može koristiti i za prateće operacije, kao što je brisanje privremenih datoteka ili izvršnog programa.
Ovo je vrlo jednostavan Makefile primer
- Kod: Obeleži sve
CFLAGS=-O2 -Wall
proba: proba.c
$(CC) $(CFLAGS) -o $@ $<
clean:
$(RM) proba
.PHONEY: clean
CFLAGS je promenljiva koja sadrži parametre kompajlera. U ovom slučaju opcija sa optimizaciju "-O2" i prikazivanje upozorenja "-Wall".
Sledeće dve linije sadrže pravilo za izgradnju izvršne datoteke:
- Kod: Obeleži sve
proba: proba.c
$(CC) $(CFLAGS) -o $@ $<
Prva linija ima sledeći oblik:
- Kod: Obeleži sve
cilj: zavisnosti
Nakon nje sledi linija sa pravilima kako izgraditi "cilj". Makefile datoteka takođe ima promenljive. One su označene sa $ i nemaju tip. Recimo $(CFLAGS) će pri izvršavanju pravila biti zamenjenom sa "-O2 -Wall". CC je promenljiva koja definiše kompajler. Može se postaviti ručno, ili kao u ovom primeru koristiti predefinisanu vrednost. $@ je promenljiva koja će biti zamenjena sa vrednošću koju ima "cilj". $< je promenjljiva koja će biti zamenjena sa vrednošću koje ima prva "zavisnost" u listi.
Tj konkretno, ova linija:
- Kod: Obeleži sve
$(CC) $(CFLAGS) -o $@ $<
će biti zamenjena pri izvršavanju sa:
- Kod: Obeleži sve
cc -O2 -Wall -o proba proba.c
Primetili ste da druga linija počinje sa razmakom? On je neophodan. Sva pravila za izgradnju cilja "cilj" moraju biti odvojena razmakom.
Sledeće linija takođe sadrži cilj, ali ne i zavisnosti.
- Kod: Obeleži sve
clean:
$(RM) proba
Ovo je pravilo za brisanje izvršne datoteke. RM je promenljiva koja je već predefinisana. Njena vrednost je "rm -f"
S obzirom da pravilo za "clean", ne sadrži zavisnosti, moramo ga tako i obeležiti. Tome služi poslednja linija:
- Kod: Obeleži sve
.PHONY: clean
Napomene
BSD sistemi koriste make alatku koja ima nešto drugačiju sintaksu nego tradicionalna make alatka. Ako koristite *BSD sistem, moraćete instalirati/pokrenuti neku od make alatki koja podržavaju tradicionalni make format: GNU make ili smake. Za korisnike GNU/Linuksa: ako naiđete na BSD-oliki Makefile, postoji port BSD make za Linuks. Zove se pmake i dolazi podrazumevano uz Slackware. Drugi, alternativni (i možda ažurniji) port je dostupan i sa SlackBuilds.org.