Prevođenje C, C++ i Fortran programa u izvršni kod
GNU Compiler Collection (GCC) je najkorišteniji otvoreni skup program-prevoditelja.
- inicijalno je podržavao samo C, pa je GCC bila kratica za GNU C Compiler
- podržava jezike: C (
gcc
), C++ (g++
), Objective-C (gobjc
), Objective-C++ (gobjc++
), Fortran (gfortran
), Java (gcj
), Ada (gnat
) i Go (gccgo
)
Clang i LLVM čine alternativu GCC-u.
- razvoj je započeo na University of Illinois at Urbana-Champaign, danas ga dobrim dijelom sponzorira Apple
- Clang podržava C, Objective-C (
clang
), C++ i Objective-C++ (clang++
), a LLVM ima dodatke koji podržavaju i druge programske jezike
Zadatak
- Napišite u
emacs
-u "hello world" C++ program s pozdravom po vašem izboru i spremite ga kaoprog.cpp
. - Iskoristite
g++
iliclang++
za prevođenje u izvršni kod. Pokrenite rezultirajući program. - Razmotrite rezultat s
hexdump
-om. Pronađite način da ga ispišete u kanonskom obliku.
Dodatni zadatak
- Prema uputama Wikibooksove knjige o Fortranu složite program s istim pozdravom kao u prethodnom zadatku i spremite ga kao
prog.f
. Pripazite da imate uvlaku od 6 znakova u svakom retku. - Iskoristite
gfortran
za prevođenje u izvršni kod. Pokrenite rezultirajući program. - Razmotrite rezultat s
hexdump
-om i usporedite ga s programom iz prethodnog zadatka.
Izrada biblioteka i povezivanje
Biblioteka (engl. library) je kolekcija resursa (funkcija, klasa, konstanti, ...) koju programi mogu koristiti. Biblioteke omogućuju višestruko iskorištenje koda.
Biblioteke se razlikuju od uobičajenih programa po tome što nemaju funkciju main()
. Primjerice, od dvije datoteke bibl1.cpp
sadržaja
void set_value1 (int *num)
{
*num = 10;
}
i bibl2.cpp
sadržaja
void set_value2 (int *num)
{
*num = 20;
}
datoteka zaglavlja bibl.h
je oblika
void set_value1 (int *num);
void set_value2 (int *num);
dok datoteka programa mainprog.cpp
koji koristi te dvije funkcije može biti oblika
#include <iostream>
#include "bibl.h"
int main ()
{
int a, b;
set_value1 (&a);
set_value2 (&b);
std::cout << "a=" << a << " b=" << b << std::endl;
return 0;
}
Povezivanje (engl. linking) podrazumijeva povezivanje s bibliotečnim datotekam.
- statičko povezivanje (engl. static linking) u izvršnu datoteku uključuje sve potrebne dijelove bibliotečnih datoteka
- dinamičko povezivanje (engl. dynamic linking) u izvršnu datoteku stavlja samo poveznice na bibliotečne datoteke
Statičko povezivanje u gornjem primjeru izveli bismo na način:
$ g++ -c bibl1.cpp bibl2.cpp
$ ar rcs libbibl.a bibl1.o bibl2.o
$ g++ -static -o mainprog mainprog.cpp -L. -lbibl
$ ./mainprog
Program ar
je arhiver, donekle sličan tar
-u koji već poznajemo. On ovdje služi za stvaranje statičke biblioteke, datoteke s ekstenzijom .a
.
Parametar -L
kod g++
-a navodi dodatnu putanju u kojoj treba tražiti biblioteke (pored predefiniranih na sustavu), a parametar -l
navodi se jednom ili više puta zajedno s imenom biblioteke na koju je potrebno povezati program. Poredak parametara je značajan; više detalja ima u komentaru Paula Pluzhnikova na temu linking problems and order (Google grupa gnu.gcc.help).
Zadatak
Modificirajte gornji primjer tako da biblioteka uključuje i datoteku bibl3.cpp
sa dvjema funkcijama po vašem izboru čije se deklaracije navode u datoteci zaglavlja i koje se pozivaju u mainprog.cpp
. Izvedite prevođenje programa sa statičkim povezivanjem.
Dinamičko povezivanje u datotekama primjera izveli bismo na način:
$ g++ -fPIC -c bibl1.cpp bibl2.cpp
$ g++ -shared -Wl,-soname,libbibl.so.1 -o libbibl.so.1.0 bibl1.o bibl2.o
$ ln -sf libbibl.so.1.0 libbibl.so
$ ln -sf libbibl.so.1.0 libbibl.so.1
$ g++ -o mainprog -L. mainprog.cpp -lbibl
$ export LD_LIBRARY_PATH=.
$ ./mainprog
Parametar -fPIC
osigurava da je strojni kod koji GCC stvara prevođenjem neovisan o o položaju u memoriji, što omogućava dijeljenje istog od većeg broja programa.
Biblioteka u primjeru ima verziju 1.0
, što se vidi iz njezinog imena. Simboličke poveznice se stvaraju kako bismo joj mogli pristupiti i programi koji traže istoimenu biblioteku navođenjem samo verzije 1
, te programi koji traže istoimenu biblioteku bez da navode verziju.
Varijabla okoline LD_LIBRARY_PATH
navodi dodatne putanje (pored onih predefiniranih na sustavu) u kojima je potrebno tražiti biblioteke.
Zadatak
Modificirajte gornji slučaj da biblioteka uključuje i datoteku bibl3.cpp
sa dvjema funkcijama po vašem izboru čije se deklaracije navode u datoteci zaglavlja i koje se pozivaju u mainprog.cpp
. Izvedite prevođenje programa s dinamičkim povezivanjem.
Todo
Ovdje treba opisati parametre za GCC koji se odnose na linkanje, alate ldd
i readelf
, a primjer može biti s Boost bibliotekama filesystem
i datetime
.
Zadatak
Usporedite međusobno dva programa i dvije biblioteke stvorene u prethodna dva zadatka.
- Razmotrite veličinu datoteke i objasnite uzrok razlikama koje vidite.
- Usporedite izlaz naredbe
file
.
Alat make
Alat make
"automatski" izgrađuje izvršne programe i bibliotečne datoteke iz izvornog koda.
- može raditi pomoću instrukcija zadanih u datoteci Makefile
- može raditi na temelju predefiniranih ciljeva na temelju imena datoteka, u slučaju da se Makefile ne koristi
- postoje dvije inačice koje nisu 100% kompatibilne: BSD Make i GNU Make
Zadatak
- Prevedite prethodno napisani program uz pomoć
make
-a. Koju naredbumake
pokreće? Koji parametar čini da je ime izvršne datoteke isto kao ime datoteke izvornog koda bez ekstenzije? - Objasnite što se dogodi kada ponovno pokušate napraviti prevođenje. Koji je razlog tome?
- Što bi se dogodilo da preimenujete datoteku koja sadrži program u datoteku s ekstenzijom
.c
?
make
cilj (engl. target) je imenovani niz naredbi koje su potrebne za izgradnju određene ciljne datoteke (najčešće neke vrste izvršne datoteke)
- navedeni u Makefile datoteci, naziv
Makefile
iliGNUmakefile
- brojni primjeri Makefile datoteka mogu se pronaći na Wikipedijinoj stranici i drugdje
Makefile se sastoji od jednog ili više ciljeva, koji mogu imati druge ciljeve kao svoje komponente.
target [target ...]: [component ...]
[command 1]
.
.
.
[command n]
Zadatak
Napišite jednostavan Makefile
za prethodno napisani hello world program, koji sadrži:
- cilj
doc
koji u datoteku README sprema tekstOvo je dokumentacija mojeg hello world programa
, - cilj
compile
koji prevodi program u izvršni kod, - cilj
static-compile
koji prevodi program u izvršni kod i pritom koristi statičko povezivanje, - cilj
pack
koji radi arhivu koja sadrži izvršni kod i README datoteku. Obavezno iskoristite komponente.
Makefile
varijable slične su varijablama ljuske; primjer:
- zadavanje
NAME = mojprogram
, pozivanje sa$(NAME)
- zadavanje
VERSION = 3.2
, pozivanje sa$(VERSION)
- nazivaju se i makroi, zbog mogućnosti ekspanzije:
WHATSNEW_FILE_NAME = NEWS-$(VERSION)
Zadatak
Modificirajte prethodno napisani Makefile
, tako da se
- izvršna datoteka programa generira s imenom oblika
ime-verzija
, - arhiva generira s imenom oblika
ime-verzija.tar.bz2
.
Author: Vedran Miletić