You are on page 1of 22

2.

Osnove programiranja

Sadržaj
2.1 Prevodenje i povezivanje izvornog koda . . . . . . . 22
2.2 GCC - GNU projekt C i C++ prevodioc . . . . . . 23
2.2.1 Primjeri korištenja gcc prevodioca . . . . . . . . . . 25
2.3 GNU Make - automatiziranje prevodenja . . . . . . 29
2.3.1 Make varijable . . . . . . . . . . . . . . . . . . . . . 30
2.3.2 Make pravila . . . . . . . . . . . . . . . . . . . . . . 30
2.3.3 Primjer makefile datoteke . . . . . . . . . . . . . . . 31
2.4 Arhive objektnih datoteka - libovi . . . . . . . . . . 34
2.4.1 Korištenje libova . . . . . . . . . . . . . . . . . . . . 34
2.4.2 Drugi način korištenja libova . . . . . . . . . . . . . 35
2.4.3 Stvaranje arhiva objektnog koda . . . . . . . . . . . 35
2.4.4 GNU Ar - manipuliranje arhivama datoteka . . . . . 36
2.4.5 Primjer korištenja arhive . . . . . . . . . . . . . . . 37

U ovom poglavlju objasnit ćemo osnovne korake procesa stvaranja programske


podrške, koji započinje sa prvom napisanom linijom izvornog koda, a realizira
se u trenutku kada korisnik pokrene naše najnoviju aplikaciju. Navesti ćemo i
opisati tipove datoteka koje se u ovom postupku koriste, objasnit ćemo postu-
pak prevodenja i povezivanja te opisati korištenje alata kojima je ove postupke
moguće automatizirati. Iako se navedeni postupci i primjeri u prvom redu od-
nose na razvoj programske podrške za operativni sustav UNIX u programskom
jeziku C, opisani principi prevodenja i povezivanja izvornog koda u izvršni, sa
manjim razlikama, vrijede za većinu operativnih sistema i kompajlerskih1 pro-
gramskih jezika.
1
Pored kompajlerskih programskih jezika, kod kojih se izvorni kod postupkom prevodenja
i povezivanja pretvara u izvršnu datoteku, tj. strojni kod, postoje i interpreterski jezici. Kod
interpreterskih jezika naredbe izvornog koda analiziraju se i prevode u trenutku izvodenja.
Dobar primjer su shell skripte
22 Osnove programiranja

2.1 Prevodenje i povezivanje izvornog koda

IZVORNI KOD #include DATOTEKE ZAGLAVLJA


(source) (header files)
*.c *.h
prevodenje
(compiling)

OBJEKTNI KOD ARHIVE FUNKCIJA − LIBOVI


(object files) (static libraries)
*.o *.a

povezivanje
(linking)

IZVRSNI KOD MEMORIJA


(executable)

DINAMICKI LIBOVI
(dynamic libraries) CPU
*.so

Slika 2.1: Prevodenje i povezivanje

Postupak dobivanja izvršne datoteke, tj. programa koji možemo učitati u me-
moriju i pokrenuti, sastoji se od dva osnovna koraka i uključuje više različitih
tipova datoteka. Ovaj proces započinje pisanjem izvornog koda koji, u slučaju
programskog jezika C, uključuju datoteke izvornog koda (datoteke sa eksten-
zijom .c), i datoteke zaglavlja (ekstenzija .h). Osnovni koraci ovog procesa
prikazani su na slici 2.1:

• Prevodenje (Compiling)
Programski prevodioc analizira izvorni kod i prevodi ga u objektni.
Ovaj postupak započinje obradom predprocesorom koji kod priprema
za prevodenje, dio čega je i uključivanje datoteka zaglavlja (.h) u izvorni
kod. Svaka datoteka izvornog koda prevodi se u datoteku objektnog
koda (ekstenzija .o).
• Povezivanje (Linking)
Datoteke objektnog koda povezuju se u izvršnu datoteku. Pored objek-
tnih datoteka, u postupku povezivanja kao ulazne datoteke koriste se i
2.2 GCC - GNU projekt C i C++ prevodioc 23

arhive funkcija ili statički libovi. Libovi su kolekcije objektnih datoteka


pohranjenih na način da je iz njih moguće izdvojiti objektne datoteke
u izvornom obliku. Da bi u postupku povezivanja iz datoteka objekt-
nog koda mogla biti generirana izvršna datoteka, u točno jednoj objekt-
noj datoteci mora biti definirana funkcija main, koja predstavlja ulaznu
točku programa.

Moderna integrirana razvojna okruženja (Integrated Developement Envi-


ronment - IDE) programeru olakšavaju postupak prevodenja izvornog koda
u izvršnu datoteku. Ovi programi automatski generiraju datoteku sa pra-
vilima za prevodenje i povezivanje, a korisnik proces stvaranja izvršne da-
toteke pokreće jednostavnim odabirom opcije build. Pored automatiziranog
prevodenja i povezivanja, integrirana razvojna okruženja obično uključuju
editor, program za pronalaženje pogrešaka (debuger), alate za automatsko
generiranje koda (wizards), alate za kreiranje korisničkog sučelja (Graphical
User Interface - GUI) i druge dodatke koji značajno olakšavaju i ubrzavaju
proces razvoja programske podrške.
Kod ovih je sustava dobar dio postupaka i koraka u stvaranju programa
skriven od programera, pa mnogi, čak i iskusniji programeri slabo poznaju
procese koji su potrebni da bi od izvornog koda nastala njihova najnovija
aplikacija. Iako je ovim život programera značajno olakšan, svaki progra-
mer koji drži do sebe trebao bi ovladati osnovnim principima i koracima u
prevodenju i povezivanju izvornog koda, kao i shvatiti odnose medu tipovima
datoteka koje u tom procesu sudjeluju, čime stvara temelj za kvalitetniji ra-
zvoj programerske vještine.
Kod razvoja programske podrške za unix, programeru je na raspolaganju više
integriranih razvojnih okruženja. Kvalitetno rješenje predstavlja Kdevelop,
standardni dio KDE grafičkog sučelja.

2.2 GCC - GNU projekt C i C++ prevodioc

GCC, besplatan prevodioc otvorenog koda, dio je GNU2 paketa prevodioca


koji uključuje prevodioce za C, C++, Fortran, Java i druge programske
jezike, kao i libove potrebne za povezivanje programa. Dostupan je pod GPL3
2
GNU - ”GNU’s Not UNIX”, Projekt pokrenut 1984. kako bi se razvio kompletan Unixu
sličan operativni sustav koji je slobodan softver.
3
GPL - ”General Public Licence”, GNU Opća javna licenca jamči slobodu dijeljenja i
mijenjanja slobodnih programa, kako bi program bio slobodan za sve svoje korisnike.
24 Osnove programiranja

licencom za brojne platforme sa ciljem omogućavanja razvoja prenosivog koda


za različite arhitekture i okruženja.
GCC prevodioc se koristi za prevodenje i povezivanje (compiling & linking)
C i C++ izvornog koda.

Sintaksa

gcc [opcije] ulazne datoteke


U daljnjem tekstu navedene su osnovne opcije i tipovi datoteka koje gcc ko-
risti. Detaljnu uputu za korištenje gcc prevodioca moguće je dobiti sa:
man gcc

Osnovne opcije

-c samo prevodenje, bez povezivanja (rezultat je objektna datoteka)


-Orazina razina optimizacije (0-3)
-g generira informaciju za debugger (program za pronalaženje grešaka)
-Idir uključi dir u listu direktorija sa datotekama zaglavlja
-Ldir uključi dir u listu direktorija sa arhivama objektnog koda
-Wall prikaži sva upozorenja (Warning all)
-o datoteka naziv izlazne datoteke

Ukoliko ime izlazne izvršne datoteke nije eksplicitno navedeno opcijom -o,
uobičajeno ime izvršne datoteke je a.out.
Ukoliko se koristi opcija -c, izlazna datoteka je datoteka objektnog koda. Ime
objektne datoteke stvorene iz datoteke izvornog koda imena ime.sufiks (na
primjer ime.c) je ime.o.

Ulazni tipovi datoteka

Nakon pokretanja, gcc obavlja predprocesiranje, prevodenje i povezivanje.


Tipovi datoteka koji se mogu pojaviti kao ulazne datoteke zagcc uključuju:

• datoteka.c
C izvorni kod koji je potrebno predprocesirati
2.2 GCC - GNU projekt C i C++ prevodioc 25

• datoteka.i
C izvorni kod koji se ne predprocesira

• datoteka.h
C ili C++ datoteka zaglavlja, obraduje se u fazi predprocesiranja

• datoteka.cc
datoteka.cp
datoteka.cpp
datoteka.CPP
datoteka.cxx
datoteka.c++
datoteka.C
C++ izvorni kod koji je potrebno predprocesirati

• datoteka.ii
C++ izvorni kod koji se ne predprocesira

• datoteka.hh
datoteka.H
C++ datoteka zaglavlja, obraduje se u fazi predprocesiranja

• datoteka.o
datoteka.a
objektni kod, koristi se u fazi povezivanja. Pored datoteka sa ekstenzijom
.o (objektne datoteke) i .a (arhive objektnog koda), gcc sve datoteke
koje ne prepoznaje kao jedan od uobičajenih ulaznih tipova (pored ovdje
navedenih postoje i drugi) tretira kao datoteke objektnog koda.

2.2.1 Primjeri korištenja gcc prevodioca

Prevodenje izvornog koda u jednoj datoteci

U datoteci pozdrav.c nalazi se izvorni kod jednostavnog programa koji is-


pisuje pozdravnu poruku. Prikazano je nekoliko načina prevodenja izvornog
koda u izvršnu datoteku.

/> gcc -Wall pozdrav.c


/> gcc -Wall pozdrav.c -o pozdrav1
/> ls -al
26 Osnove programiranja

total 20
drwxr-xr-x 2 dkrst users 120 2006-03-15 03:31 .
drwxr-xr-x 4 dkrst users 112 2006-03-15 03:14 ..
-rwxr-xr-x 1 dkrst users 7025 2006-03-15 03:30 a.out
-rwxr-xr-x 1 dkrst users 7025 2006-03-15 03:31 pozdrav1
-rw-r--r-- 1 dkrst users 79 2006-03-15 03:15 pozdrav.c

U prvom slučaju nije navedeno ime izlazne datoteke pa izlazna datoteka do-
biva uobičajeno ime a.out. U drugom slučaju korištenjem opcije -o zadano
je ime izvršne datoteke pozdrav1. Datoteke pozdrav1 i a.out su identične.
U oba primjera koristi se opcija -Wall, koja prevodiocu nalaže da ispiše sve
poruke o upozorenjima.
Kod stvaranja izvršne datoteke (executable), automatski se postavljaju prava
pristupa koja omogućavaju pokretanje datoteke.

Ukoliko nije eksplicitno navedeno korištenjem opcije -c, prevodioc stvara (uko-
liko se ne pojavi greška) izvršnu datoteku, tj. provodi prevodenje i povezivanje
programa. Postupke prevodenja i povezivanja moguće je izvršiti odvojeno sli-
jedećim nizom naredbi:

/> gcc -Wall -c pozdrav.c


/> gcc -Wall pozdrav.o -o pozdrav2
/> ls -al
total 32
drwxr-xr-x 2 dkrst users 168 2006-03-15 03:44 .
drwxr-xr-x 4 dkrst users 112 2006-03-15 03:14 ..
-rwxr-xr-x 1 dkrst users 7025 2006-03-15 03:30 a.out
-rwxr-xr-x 1 dkrst users 7025 2006-03-15 03:31 pozdrav1
-rwxr-xr-x 1 dkrst users 7025 2006-03-15 03:44 pozdrav2
-rw-r--r-- 1 dkrst users 79 2006-03-15 03:15 pozdrav.c
-rw-r--r-- 1 dkrst users 892 2006-03-15 03:42 pozdrav.o

Prva naredba datoteku pozdrav.c prevodi u objektnu datoteku. Ukoliko ime


izlazne datoteke nije eksplicitno navedeno, ime objektne datoteke jednako je
imenu datoteke izvornog koda čija se ekstenzija mjenja u .o
U drugom koraku objektna datoteka se koristi kao ulaz. Postupak prevodenja
se preskače (objektni kod je već preveden) i obavlja se samo povezivanje. Re-
zultat je izvršna datoteka pozdrav2.
Datoteke a.out, pozdrav1 i pozdrav2 su identične.
Kod pregleda sadržaja direktorija, pored datoteke pozdrav.c i izvršnih dato-
teka a.out, pozdrav1 i pozdrav2 uočavamo i objektnu datoteku pozdrav.o
2.2 GCC - GNU projekt C i C++ prevodioc 27

Prevodenje izvornog koda koji se nalazi u više datoteka

Prethodni primjer preraden je na način da je dio koda odgovoran za ispis poz-


dravne poruke korisniku izdvojen u funkciju koja se nalazi u zasebnoj datoteci.
U ovom slučaju, za stvaranje izvršne datoteke potrebno je prevesti dvije da-
toteke izvornog koda u objektni kod ta objektne datoteke povezati u izvršnu.
Izvorni kod nalazi se u datotekama pozdrav fn.c i funkcije1.c, a funkcijski
prototipovi u datoteci zaglavlja funkcije.h.

1 #include <stdio.h>

3 void dobar_jutar() {
printf("Dobar jutar!\n");
}

Datoteka funkcije1.c

6 #ifndef _PRIMJER2_
#define _PRIMJER2_

9 void dobar_jutar();

void slucajni_niz(int *niz, int broj_elemenata);


12 int najveci_element(int *niz, int broj_elemenata);
int najmanji_element(int *niz, int broj_elemenata);

15 #endif

Datoteka funkcije.h: dani su prototipovi 4 funkcije

#include "funkcije.h"

18 int main() {
dobar_jutar();

21 return(0);
}

Datoteka pozdrav fn.c - poziva se funkcija dobar jutar()


28 Osnove programiranja

Postupak prevodenja i povezivanja možemo pokrenuti na više načina.

/> gcc -Wall pozdrav_fn.c funkcije1.c -o pozdrav_fn1


/> ls -al
total 20
drwxr-xr-x 3 dkrst users 200 2006-03-14 05:22 .
drwxr-xr-x 4 dkrst users 112 2006-03-15 03:14 ..
-rw-r--r-- 1 dkrst users 71 2006-03-14 04:52 funkcije1.c
-rw-r--r-- 1 dkrst users 67 2006-03-14 05:21 funkcije.h
-rwxr-xr-x 1 dkrst users 7156 2006-03-14 05:22 pozdrav_fn1
-rw-r--r-- 1 dkrst users 69 2006-03-14 05:21 pozdrav_fn.c

Postupak prevodenja i povezivanja pokrećemo jednom naredbom. Kao ulaz


u gcc koriste se datoteke izvornog koda, koje se prevode u objektni i zatim
povezuju u izvršnu. Objektne datoteke, koje su medukorak izmedu izvornog
i izvršnog koda nisu sačuvane. U slučaju promjene izvornog koda, cijeli se
postupak ponavlja, tj. svaka od datoteka se ponovo prevodi u objektni kod i
povezuje u izvršnu datoteku.
Kao i u prethodnom primjeru, postupak prevodenja i povezivanja možemo
razdvojiti.

/> gcc -Wall -c funkcije1.c pozdrav_fn.c


/> gcc -Wall funkcije1.o pozdrav_fn.o -o pozdrav_fn2
/> ls -al
total 36
drwxr-xr-x 3 dkrst users 296 2006-03-14 05:43 .
drwxr-xr-x 4 dkrst users 112 2006-03-15 03:14 ..
-rw-r--r-- 1 dkrst users 71 2006-03-14 04:52 funkcije1.c
-rw-r--r-- 1 dkrst users 872 2006-03-14 05:43 funkcije1.o
-rw-r--r-- 1 dkrst users 67 2006-03-14 05:21 funkcije.h
-rwxr-xr-x 1 dkrst users 7156 2006-03-14 05:22 pozdrav_fn1
-rwxr-xr-x 1 dkrst users 7156 2006-03-14 05:43 pozdrav_fn2
-rw-r--r-- 1 dkrst users 69 2006-03-14 05:21 pozdrav_fn.c
-rw-r--r-- 1 dkrst users 804 2006-03-14 05:43 pozdrav_fn.o

Provm naredbom datoteke izvornog koda se prevode u objektni kod, koji


se u izvršnu datoteku povezuje drugom naredbom. Pored izvršne datoteke,
sačuvane su i datoteke objektnog koda. Ukoliko sada u izvorni kod unesemo
neku izmjenu, prevesti je potrebno samo onu datoteku u kojoj su izmjene na-
pravljene, i ponoviti postupak povezivanja. U slučaju složenijih programa,
sa većim brojem datoteka izvornog koda, postupak prevodenja i povezivanja
2.3 GNU Make - automatiziranje prevodenja 29

može se znatno skratiti ukoliko nakon svake promjene nije potrebno ponovo
prevoditi cjelokupan kod. Ovo posebno dolazi do izražaja tijekom razvoja
programa, kada često unosimo manje izmjene i testiramo razne varijante pro-
grama.

2.3 GNU Make - automatiziranje prevodenja

U procesu razvoja programske podrške često se ponavlja isti ili sličan slijed
naredbi, i to nakon svake izmjene u izvornom kodu programa. Alat GNU
Make nam omogućava automatiziranje ovog postupka. Make analizira sve
datoteke u kojima se nalazi izvorni kod našeg projekta i ponovo prevodi samo
one koje su mijenjane od posljednjeg prevodenja. Da bi ovo bilo moguće, po-
trebno je definirati datoteku sa pravilima za prevodenje i povezivanje u kojoj
su navedene ulazne datoteke projekta, odnosi medu njima i slijed naredbi i
postupaka koji se izvode kod prevodenja.
Kod integriranih razvojnih okruženja, postupak kreiranja i održavanja ove
datoteke obavlja razvojno okruženje. U ovom slučaju opcije za prevodenje i
povezivanje možemo mijenjati kroz sustav menija, a razvojno okruženje auto-
matski unosi zadane promjene u datoteku sa pravilima.

Sintaksa

make [opcije]
Detaljnu uputu za korištenje programa make moguće je dobiti sa:
man make

Osnovne opcije

-f ime datoteke Ime datoteke sa pravilima, koju nazivamo make-


file. Ukoliko ova opcija nije navedena, make u
radnom direktoriju traži datoteku naziva GNU-
makefile, makefile, ili Makefile, redosljedom
kojim su navedene i, ukoliko neku od navedenih
datoteka pronade, iz nje čita pravila. Ukoliko ne
postoji makefile datoteka, make javlja grešku.
pravilo Izbor pravila (u jednoj makefile datoteci može
biti navedeno više pravila).
30 Osnove programiranja

Nakon pokretanja, rutina make učitava datoteku sa pravilima u kojoj su


navedeni točni postupci koje je potrebno izvršiti za prevodenje izvornog koda u
izvršnu datoteku. U jednoj makefile datoteci moguće je definirati više pravila,
a ime pravila koje želimo pokrenuti zadajemo kao argument naredbenog retka.
Pored pravila za prevodenje i povezivanje, makefile datoteka može sadržavati
i pravila druge namjene. Uobičajeno se u ovoj datoteci deiniraju i pravila za
brisanje nepotrebnih i privremenih datoteka, ali i složena pravila za instalaciju
programske podrške.

2.3.1 Make varijable

Varijabla je ime definirano unutar makefile datoteke, a vrijednost varijable je


tekstualni niz (string). Varijable mogu predstavljati imena datoteka, putanju
do izvršnih programa (npr. prevodioca), opcije za prevodenje i povezivanje,
putanju do direktorija u kojima se nalaze datoteke izvornog koda, direktorija
za pohranu izvršnih datoteka, ili imati bilo koju drugu namjenu. Koriste u
drugim djelovima makefile datoteke, uključujući definiciju drugih varijabli.
Vrijednost varijable dohvaćamo korištenjem znaka $ i imena varijable u zagra-
dama. Varijabla se zamjenjuje stringom koji joj je pridružen.

2.3.2 Make pravila

Pravila za prevodenje i povezivanje dana su u formi:

naziv pravila : ovisnosti


naredbe
...

• Kao naziv pravila najčešće se koristi ime datoteke koja nastaje kao pro-
dukt izvodenja pravila. Naziv pravila može odgovarati i akciji koju pra-
vilo obavlja, ali može biti i proizvoljno odabrano od strane programera.
pravila.

• Ovisnosti (dependencies) predstavljaju datoteka koje su potrebne za


izvršavanje pravila. Make rutina provjerava postoje li datoteke nave-
dene u ovisnostima i vrijeme kada su zadnji puta mijenjane, te na osnovu
toga odlučuje koje dijelove koda treba ponovo prevesti. Ukoliko dato-
teke navedene u ovisnostima ne postoje, make traži implicitna pravila
za dobivanje istih. Datoteke o kojima ovisi izvodenje pravila ne moraju
2.3 GNU Make - automatiziranje prevodenja 31

nužno biti navedene. U ovom slučaju, pravilo se izvršava svaki put kada
je pozvano.
• Naredbe su skup postupaka koji se izvršavaju kada je pozvano odredeno
pravilo. Iako se najčešće radi o naredbama potrebnim za stvaranje
izvršne datoteke, pravila u makefile datoteci se mogu koristiti i za druge
operacije, kao na primjer za brisanje odredenih datoteka, ali i za opisi-
vanje složenih postupaka, kao što je instalacija programske podrške.
Važno je naglasiti da je redak (ili više njih) u kojem su naredbe
definirane mora biti uvučen korištenjem tipke TAB. Ukoliko se
umjesto ovoga koristi običan razmak, make će prijaviti grešku.
• Implicitna pravila se koriste za opisivanje nekih postupaka koji se izvode
vrlo često. Ovaj tip pravila se najčešće koristi za dobivanja objektnih
datoteka iz izvornog koda. Odabir implicitnog pravila koje će se izvršiti
temelji se na imenu datoteke. Na primjer, oznaka .c.o definira impli-
citno pravilo koje se koristi za dobivanje objektne datoteke (ekstenzija
.o) iz datoteke C izvornog koda.

2.3.3 Primjer makefile datoteke

U slijedećem primjeru dana je datoteka sa pravilima za prevodenje i poveziva-


nje primjera pozdrav i pozdrav fn koji su do sada korišteni u ovom poglavlju.
Programi su prevedeni na dva načina, kako je bilo prezentirano u ranijem tek-
stu. Izvršne datoteke pozdrav i pozdrav fn dobivene su na način da su se kao
ulazne datoteke gcc prevodioca koristile datoteke objektnog koda, pri čemu
su datoteke objektnog koda generirane korištenjem implicitnog pravila defini-
ranog u 24. i 25. retku Makefile datoteke.
Izvršne datoteke pozdrav2 i pozdrav fn2 dobivene su na način da su kao
ulazne datoteke gcc prevodioca korištene datoteke izvornog koda.

1 CC = /usr/bin/gcc
CFLAGS = -Wall
3 TARGETS = pozdrav pozdrav2 pozdrav_fn pozdrav_fn2

default: pozdrav_fn
6 all: $(TARGETS)

pozdrav: pozdrav.o
9 $(CC) $(CFLAGS) pozdrav.o -o pozdrav
32 Osnove programiranja

pozdrav2: pozdrav.c
12 $(CC) $(CFLAGS) pozdrav.c -o pozdrav2

pozdrav_fn: pozdrav_fn.o funkcije1.o


15 $(CC) $(CFLAGS) pozdrav_fn.o funkcije1.o -o pozdrav_fn

pozdrav_fn2: pozdrav_fn.c funkcije1.c


18 $(CC) $(CFLAGS) pozdrav_fn.c funkcije1.c \
-o $(BIN)/pozdrav_fn2

21 clean:
rm -f *.o *~ a.out $(TARGETS)

24 .c.o:
$(CC) $(CFLAGS) -c $<

Makefile datoteka sa pravilima za prevodenje i povezivanje

Varijable:

CC Putanja do gcc prevodioca. Promjenom sadržaja ove vari-


jable moguće je promijeniti prevodioc u svim pravilima koja
su u datoteci definirana.
CFLAGS Opcije za prevodioc
TARGETS Imena izvršnih datoteke, koristi se u pravilima all i clean.
2.3 GNU Make - automatiziranje prevodenja 33

Pravila:

default Ovo pravilo se izvodi ukoliko je make rutina pozvana bez


imena pravila, u kojem se slučaju poziva prvo pravilo koje je
navedeno. Važno je uočiti da se pravilo default ne poziva
zbog svog simboličkog imena već zbog činjenice da je prvo
navedeno praivlo u pozvanoj Makefile datoteci.
all Uključuje sva pravila. Pravila se izvode redom kojim su
navedena u pravilu all.
pozdrav Kao ovisnost se javlja objektna datoteka datoteka
pozdrav.o. Ukoliko ova datoteka ne postoji, make traži
odgovarajuće implicitno pravilo. Implicitno pravilo se po-
ziva i ukoliko datoteka pozdrav.o postoji, ali je starija od
datoteke primjer.c.
pozdrav2 Prevodenje i povezivanje datoteke izvornog koda pozdrav.c,
koja je navedena kao ovisnost. Za definiranje naredbi koriste
se varijable
pozdrav fn Kao ulazne datoteke se koriste datoteke objektnog koda.
U slučaju promjene u nekoj od datoteka izvornog koda,
poziva se implicitno pravilo i ponovo se prevodi samo iz-
mjenjena datoteka, nakon čega se ponavlja postupak po-
vezivanja. Kod složenijih programa čiji se kod može nala-
ziti u većem broju datoteka, prevodenje samo onih dijelova
koda koji su izmjenjeni nakon zadnjeg prevodenja rezultira
značajnim skraćenjem trajanja postupka. Ovo posebno do-
lazi do izražaja u fazi razvoja programske podrške, kada se
često unose male promjene, nakon čega se program prevodi
i testira.
pozdrav fn2 Prevodenje programa koji se nalazi u dvije datoteke izvornog
koda jednom naredbom. U slučaju bilo kakve promjene u
nekoj od datoteka cijeli postupak prevodenja i povezivanja
se ponavlja.
clean Brisanje privremenih, objektnih i izvršnih datoteka.
.c.o Implicitno pravilo za prevodenje datoteka C izvornog koda u
objektne datoteke. Poziva se svaki put kada se u ovisnostima
pojavi datoteka imena ime.o, ukoliko takva datoteka ne pos-
toji, ili je po vremenu promjene starija od vremena promjene
odgovarajuće datoteke ime.c. U ovom slučaju izvršava se
naredba (definirana u 25. retku Makefile datoteke): gcc
-Wall -c ime.c
34 Osnove programiranja

2.4 Arhive objektnih datoteka - libovi

Arhiva objektnih funkcija (library) je jedna datoteka koja u sebi sadrži više
datoteka objektnog koda pohranjenih na način da je svaku od njih moguće iz-
dvojiti u njezinom izvornom obliku. Ovako organizirane arhive objektnog koda
mogu se koristiti kao ulaz u programski prevodioc (u našem slučaju gcc).
Neke arhive distribuiraju se kao dio paketa programskog prevodioca i sadrže te-
meljne funkcije nužne za razvoj programske podrške. Primjer je arhiva libc.a,
koja sadrži osnovne C funkcije kao što su printf, getc, putc, malloc i ostale
funkcije bez kojih je teško moguć razvoj i najjednostavnijih programa. Os-
tale arhive u pravilu sadrže skup funkcija orjentiranih na rješavanje odredene
problematike (na primjer funkcije za mrežnu komunikaciju ili obradu slika), a
mogu biti distribuirane u paketu sa prevodiocem, ili odvojeno. Korištenjem
već pripremljenih funkcija programera oslobada potrebe da svoj program ra-
zvija ”od nule” pa je prije upuštanja u kodiranje uvijek korisno provjeriti
potoji li lib koji nam može olakšati život i uštedjeti vrijeme i trud.

2.4.1 Korištenje libova

Lib kao ulaz u prevodioc koristimo na isti način kao i objektnu datoteku. Na
primjer, naredba:

gcc program.c nekilib.a -o program

kao ulaz u prevodioc koristi datoteku izvornog koda program.c i lib


nekilib.a. Datoteka program.c se prevodi u objektni kod (funkcije u libu
već jesu objektni kod), nakon čega se povezuje sa objektnim datotekama koje
su dio navedene arhive, a koje su potrebne za stvaranje izvršne datoteke
program. Pri pozivanju prevodioca nije potrebno eksplicitno navesti ranije
spomenutu arhivu libc.a koja je gotovo uvijek potrebna pa se automatski
koristi u povezivanju.

Kada je kao ulaz u prevodioc naveden lib, on se traži u radnom direkto-


riju i listi direktorija sa arhivama objektnog koda. Ova lista na unix sis-
temu obično uključuje direktorij /usr/lib, a može se proširiti opcijom
-Lime direktorija (vidi poglavlje 2.2).
Kod korištenja arhiva objektnog koda važan je i redosljed kojem su ulazne
datoteke navedene u naredbi koja poziva gcc. Naime, u svakoj arhivi može
biti više objektnih datoteka, a prevodioc izdvaja samo one koje sadrže funk-
2.4 Arhive objektnih datoteka - libovi 35

cije potrebne za generiranje izvršne datoteke. Kada pokrenemo gcc, datoteke


se analiziraju onim redosljedom kojim su navedene u naredbenom retku pri
čemu se stvara lista potrebnih funkcija. Funkcije koje nedostaju traže se u li-
bovima koje slijede u naredbenom retku, iz kojih se izdvajaju samo oni djelovi
objektnog koda koji sadrže potrebne funkcije. Ukoliko je neka arhiva navedena
ranije od funkcijskog poziva koji koristi dio objektnog koda arhive, ovaj dio
koda neće biti izdvojen iz liba i gcc će prijaviti grešku u procesu povezivanja.
Dobra je praksa arhive objektnog koda staviti na kraju liste datoteka koje su
ulaz u gcc prevodioc, a posebno je potrebno voditi računa o redosljedu ako
koristimo više od jednog liba pri čemu postoji mogućnost da neka od funkcija
iz jedne arhive koristi funkcije iz neke druge. U ovom slučaju uvijek moramo
lib ”više razine”, tj. onaj koji koristi funkcije iz neke druge arhive, staviti
ranije u listi datoteka.

2.4.2 Drugi način korištenja libova

Kada je ime liba dano u obliku libime.a, a nalazi se u nekom od direktorija


navedenim u listi direktorija sa arhivama objektnog koda, umjesto navodenja
putanje do željenog liba može se koristiti opcija gcc prevodioca -lime. Uko-
liko, na primjer, u proces povezivanja želimo uključiti arhivu libjpeg.a u
kojoj se nalazi objektni kod funkcija za manipuliranje slikama u jpeg formatu,
možemo koristiti slijedeću sintaksu:

gcc -Wall prog.o -ljpeg -o izvrsna

Ukoliko direktorij sa datotekom libjpeg.a nije u listi direktorija sa arhivama


objektnog koda, sintaksa naredbe bi izgledala ovako:

gcc -Wall -L/putanja/na/direktorij prog.o -ljpeg -o izvrsna

2.4.3 Stvaranje arhiva objektnog koda

Pored korištenja arhiva objektnog koda koje su pripremili drugi programeri,


jednostavno je i stvaranje novih libova u kojima možemo pohraniti svoje funk-
cije. Ovo je dobra praksa ukoliko često koristimo neke djelove koda. Arhivi-
ranjem funkcija u lib sistematiziramo kod koji smo ranije razvili na način da
umjesto velikog broja objektnih datoteka koristimo jednu ili više tematskih
36 Osnove programiranja

arhiva. Vjerovatno najlošija praksa je kopiranje izvornog koda u svaki novi


projekt, pri čemu se vrlo lako izgubiti u šumi izmjena koje unosimo u različitim
verzijama.
Osim za osobne primjene, arhive možemo ponuditi na korištenje i drugim pro-
gramerima, bilo kao dio slobodnog softwarea, ili kao komercijalni proizvod. Na
ovaj način omogućavamo distribuciju i korištenjene svojih funkcija bez potrebe
da, ukoliko to ne želimo, otkrivamo izvorni kod. Naravno, funkcije je moguće
distribuirati i u objektnom obliku (što je praktički isto), ali tada umjesto sa
jednom manipuliramo sa većim brojem datoteka.

2.4.4 GNU Ar - manipuliranje arhivama datoteka

Program ar koristimo za stvaranje i manipuliranje arhivama datoteka. U


arhivi datoteke sačuvan je sadržaj, vlasništvo, prava i vremena pristupa svake
pojedine datoteke koja na zahtjev može biti izdvojena iz arhive. Iako se može
koristiti za razne namjene, ar se najčešće koristi za manipuliranje arhivama
objektnog koda.

Sintaksa

ar [-opcije] arhiva [ulazne datoteke]


Detaljnu uputu za korištenje ar rutine moguće je dobiti sa:
man ar

Osnovne opcije

r Dodavanje nove ili zamjena postojeće datoteke u arhivi.


Ukoliko u arhivi postoji član sa istim imenom, prije dodava-
nja novog, postojeći član se briše iz arhive.
d Brisanje datoteke člana iz arhive.
x Izdvajanje datoteke člana iz arhive.
t Ispis liste datoteka članova arhive.
v Mod rada sa ispisom dodatnih informacija (verbose).
2.4 Arhive objektnih datoteka - libovi 37

2.4.5 Primjer korištenja arhive

U datoteci funkcije2.c dan je izvorni kod funcije za generiranje niza slučajnih


brojeva, te dvije funkcije za pronalaženje najvećeg i najmanjeg elementa niza:

1 #include <stdlib.h>

3 /*
*
* Generira slucajni niz duzine broj_elemenata
6 *
*/
void slucajni_niz(int *niz, int broj_elemenata) {
9 int i;
for (i=0; i<broj_elemenata; i++)
niz[i] = rand();
12 }

/*
15 *
* Pronalazi najveci element u nizu
*
18 */
int najveci_element(int *niz, int broj_elemenata) {
int i, maxel = niz[0];
21
for (i=1; i<broj_elemenata; i++) {
if (maxel < niz[i])
24 maxel = niz[i];
}

27 return(maxel);
}

30 /*
*
* Pronalazi najmanji element u nizu
33 *
*/
int najmanji_element(int *niz, int broj_elemenata) {
36 int i, minel = niz[0];
38 Osnove programiranja

for (i=1; i<broj_elemenata; i++) {


39 if (minel > niz[i])
minel = niz[i];
}
42
return(minel);
}

Datoteka funkcije2.c

Funkcijski prototipovi navedenih funkcija navedeni su u već prikazanoj da-


toteci funkcije.h. Izvorni kod programa koji koristi ove funkcije dan je u
datoteci niz.c:

1 #include <stdio.h>
#include "funkcije.h"
3 #define N_EL 10

int main() {
6 int i, mx, mi;
int niz[N_EL];

9 slucajni_niz(niz, N_EL);
printf("Elementi niza:\n");
printf("----------------\n");
12
for (i=0; i<N_EL; i++)
printf("%3d.element: %12d\n", i+1, niz[i]);
15
mx = najveci_element(niz, N_EL);
mi = najmanji_element(niz, N_EL);
18 printf("\n\nMax: %d; Min:%d\n",mx, mi);

return(0);
21 }

Datoteka niz.c

Izvršnu datoteku programa možemo dobiti sa:


2.4 Arhive objektnih datoteka - libovi 39

/> gcc -Wall niz.c funkcije2.c -o niz

Prevodenje programa možemo riješiti i dodavanjem slijedećeg pravila u ranije


stvorenu Makefile datoteku:

niz1: niz.o funkcije2.o


$(CC) $(CFLAGS) niz.o funkcije2.o -o $(BIN)/niz1

Stvaranje arhive funkcija

Pokušajmo sada kreirati lib sa funkcijama danim u datotekama funkcije1.c


i funkcije2.c. U ovoj bi arhivi trebale biti pohranjene ukupno četiri funkcije
u dvije objektne datoteke (funkcije1.o i funkcije2.o). Prvi korak je
prevodenje datoteka izvornog koda u objektni kod (gcc opcija -c):

/> gcc -Wall -c funkcije1.c funkcije2.c

Iz objektnih funkcija stvaramo lib korištenjem rutine ar sa opcijom -r (doda-


vanje ili zamjena objektnih datoteka u arhivi). Ukoliko arhiva ne postoji, ar
stvara novu arhivu:

/> ar -r mojlib.a funkcije1.o funkcije2.o


ar: creating mojlib.a

Izvršnu datoteku sada možemo generirati na slijedeći način:

/> gcc -Wall niz.c mojlib.a -o niz2

Kada prevodioc pokrenemo na ovaj način, iz arhive mojlib.a se rekons-


tuira objektna datoteka funkcije2.o u kojoj su definirane funkcije potrebne
za povezivanje u izvršnu datoteku programa. Ova naredba u osnovi je jednaka
naredbi:

/> gcc -Wall niz.c funkcije2.o -o niz2


40 Osnove programiranja

Make pravila

Postupak stvaranja arhive objektnog koda možemo automatizirati dodavanjem


pravila u postojeću Makefile datoteku. Takoder, možemo definirati i pravila
za prevodenje i povezivanje primjera opisanih u ovom poglavlju na način da
umjesto datoteka objektnog koda koriste lib. Konačni izgled Makefile dato-
teke dan je u slijedećem listingu:

1 CC = /usr/bin/gcc
AR = /usr/bin/ar
3 CFLAGS = -Wall
LIBDIR = .

6 TARGETS = pozdrav pozdrav2 pozdrav_fn pozdrav_fn2 \


pozdrav_fn3 niz niz2

9 default: niz
all: $(TARGETS) mojlib

12 pozdrav: pozdrav.o
$(CC) $(CFLAGS) pozdrav.o -o pozdrav

15 pozdrav2: pozdrav.c
$(CC) $(CFLAGS) pozdrav.c -o pozdrav2

18 pozdrav_fn: pozdrav_fn.o funkcije1.o


$(CC) $(CFLAGS) pozdrav_fn.o funkcije1.o -o pozdrav_fn

21 pozdrav_fn2: pozdrav_fn.c funkcije1.c


$(CC) $(CFLAGS) pozdrav_fn.c funkcije1.c -o pozdrav_fn2

24 pozdrav_fn3: pozdrav_fn.o
$(CC) $(CFLAGS) pozdrav_fn.o $(LIBDIR)/mojlib.a -o pozdrav_fn3

27 niz: niz.o funkcije2.o


$(CC) $(CFLAGS) niz.o funkcije2.o -o niz

30 niz2: niz.o
$(CC) $(CFLAGS) niz.o $(LIBDIR)/mojlib.a -o niz2

33 mojlib: funkcije1.o funkcije2.o


2.4 Arhive objektnih datoteka - libovi 41

$(AR) -r $(LIBDIR)/mojlib.a funkcije1.o funkcije2.o

36 clean:
rm -f *.o *~ a.out $(TARGETS)

39 cleanall:
rm -f *.o *~ a.out $(TARGETS) $(LIBDIR)/mojlib.a

42 .c.o:
$(CC) $(CFLAGS) -c $<

Konačni oblik Makefile datoteke

U Makefile datoteku dodana su slijedeća pravila:

pozdrav fn3 Pravilo za prevodenje primjera pozdrav fn u kojem se


umjesto objektne datoteke funkcije1.o koristi arhiva
objektnog koda mojlib.a
niz Prevodenje primjera niz. Funkcije za manipuliranje nizom
nalaze se u datoteci funkcije2.o
niz2 Datoteka objektnog koda funkcije2.o sa funkcijama za
manipuliranje nizom uzima se iz arhive mojlib.a
mojlib Pravilo za stvaranje arhive mojlib.a. U ovisnostima
su navedene datoteke objektnog koda funkcije1.o i
funkcije2.o. Make provjerava postoje li navedene dato-
teke i njihova vremena kreiranja, te po potrebi poziva impli-
citno pravilo za prevodenje izvornog u objektni kod. Nakon
stvaranja objektnih datoteka, izvršava se naredba:
ar -r ./mojlib.a funkcije1.o funkcije2.o
Naredba se formira korištenjem dviju novih varijabli: Vari-
jabla AR (drugi redak makefile datoteke) definira putanju do
ar rutine. Varijabla LIBDIR (šesti redak) odreduje direk-
torij u koji se pohranjuje arhiva. Ista varijabla koristi se i
kod povezivanja programa koji funkcije uzimaju iz arhive.
cleanall Pored izvršnih, objektnih i privremenih datoteka, briše i ar-
hivu mojlib.a
42 Osnove programiranja

You might also like