Politechnika Krakowska im. T. Kościuszki

Jest to skrótowa składnia, tylko dla naszej wygody. W rzeczywistości są to 2 oddzielne procesy: kompilacja i linkowanie. Np. polecenie gcc –c licz0.c daje plik binarny: licz0.o, zawierający tylko nasz kod, skompilowany do języka maszyny.

INSTYTUT INFORMATYKI STOSOWANEJ

Polecenie gcc –o licz0.exe licz0.o linkuję (łączy) wszystkie funkcje znajdujące się w pliku ‘licz.o’, z Środowisko LINUX – Kompilacja programów języka C w systemie Linux funkcjami biblioteki standardowej i tworzy plik wykonywalny: licz.exe.

W wyniku otrzymuje się plik wykonywalny, który wykonujemy po wpisaniu w linii poleceń: ./licz0.exe Systemy

LABORATORIUM

2 x 45min

5. Kompilacja i scalanie programu C w linii poleceń

Operacyjne

licz1.c:

#include<stdio.h>

1. Cel

double kwadrat(double x);

double szescian(double x);

int dodaj(int a, int b);

Celem niniejszego ćwiczenia jest zapoznanie się z podstawami kompilacji programów, void powitaj(char* dopisek);

których kod źródłowy jest napisany w języku C.

int main(int argc, char* argv[])

{

2. Wstęp

double liczba, kw_liczby;

powitaj("matematyki");

Nazwa kompilacja, na co dzień jest używana w kontekście tłumaczenia z języka wyższego printf("Podaj liczbę: ");

poziomu na język niższego poziomu. W Linuksie kompilację kodu można przeprowadzić za scanf("%lf", &liczba);

pomocą kompilatora gcc wywoływanego z linii poleceń lub też za pomocą polecenia make.

kw_liczby=kwadrat(liczba);

Narzędzie make służy do zarządzania kompilacją projektów składających się z wielu plików printf("Jej kwadrat to %lf\n", kw_liczby);

return 0;

źródłowych. Aby używać make należy napisać skrypt o nazwie Makefile lub makefile, w

}

którym opisane są: zależności pomiędzy plikami źródłowymi i plikami wynikowymi, sposób tworzenia plików wynikowych z plików źródłowych. Następnie przy pomocy polecenia make funkcje.c:

kompilujemy projekt. Make usprawnia kompilację, gdyż samodzielnie decyduje, które z double kwadrat(double x)

plików źródłowych mają być przekompilowane (sprawdzając daty ostatniej modyfikacji).

{

return (x)*(x);

3. Przygotowanie systemu CentOS 5.0

}

Zanim przystąpimy do wpisywania kodu źródłowego programu i jego kompilacji należy powitanie.c:

pobrać pakiet kompilatora gcc

#include<stdio.h>

Dokonujemy tego poleceniem:

void powitaj(char* dopisek)

{

yum install gcc

printf("Witaj w swiecie %s\n", dopisek);

}

4. Kompilacja programu C w linii poleceń

Pliki licz1.c, funkcje.c i powitanie.c należy teraz skompilować (przetłumaczyć), tak jak Edycji kodu źródłowego należy dokonać przy użyciu edytora vim. Poniżej zamieszczony jest zrobiono to w punkcie 5, a następnie zlinkować (scalić).

kod źródłowy programu licz0.c:

Scalanie plików obiektów w program wykonywalny wymaga użycia opcji „-o”

#include<stdio.h>

double kwadrat(double x)

gcc –o <nazwa_celu>.exe <nazwa_pliku1>.o <nazwa_pliku2>.o …

{

return (x)*(x);

<nazwa_celu> oznacza nazwę pliku wykonywalnego, która może, ale nie musi mieć żadnego

}

konkretnego rozszerzenia (takiego jak np. „exe” w systemie Windows).

int main(int argc, char* argv[])

W wielu systemach uniksowych można połączyć kompilację i scalanie plików w jednym poleceniu:

{

double liczba, kw_liczby;

gcc –o <nazwa_celu>.exe <nazwa_pliku1>.c <nazwa_pliku2>.c …

printf("Podaj liczbe: ");

scanf("%lf", &liczba);

kw_liczby=kwadrat(liczba);

Jeśli plik nagłówka (.h) nie znajduje się w bieżącym katalogu ani w żadnym z katalogów zawierających printf("Jej kwadrat to: %lf\n", kw_liczby);

nagłówki standardowych bibliotek to przy kompilacji stosowana jest opcja –I <katalog_naglowka> .

return 0;

(duże 'i')

}

gcc –c –I <katalog_naglowka> <nazwa_pliku>.c

Kompilowanie plików źródłowych C do postaci plików wykonywalnych wymaga użycia opcji „-o”.

gcc -o <nazwa_programu>.exe <nazwa_pliku>.c

1

2

6. Kompilacja i scalanie programów C przez „make”

7. Kompilacja jądra Linux

Polecenie „make” szuka w bieżącym katalogu pliku tekstowego o nazwie „makefile” lub „Makefile” w W wersjach stabilnych źródeł jądra Linux środkowa liczba jest liczbą parzystą (np. 2.2.14), a w podanej kolejności. Plik ten zawiera reguły opisujące dla „make”, co budować (wykonywać) i w jaki wersjach rozwojowych jest to liczba nieparzysta.

sposób. Reguły pliku make mają następującą formę ogólną:

Standardowo każda, świeżo zainstalowana dystrybucja systemu Linux posiada już rozpakowane źródła w katalogu /usr/src/linux. Wersję najnowszą (zarówno stabilną jak i rozwojową)

<zmienna>:=<polecenie lub wartość >

najprościej można pobrać z Internetu. Pod adresem http://www.kernel.org/ znajduje się strona,

[…]

gdzie dostępne są wszystkie wersje jądra systemowego. Gdy źródła wybranej wersji jądra zostaną już

<nazwa_celu>: <zależ ność > [<zależ ność >] […]

w całości pobrane na lokalny dysk twardy, należy zalogować się jako administrator ( root) i je

<tabulator> <polecenie>

rozpakować. Następnie wystarczy przekopiować plik ze źródłami do katalogu /usr/src. Jeżeli są to

[<tabulator> <polecenie>]

źródła, których rozszerzeniem jest *.tar.gz, wydać z konsoli polecenie:

[…]

tar –zxvf linux-pobrana.wersja.jądra.tar.gz

Cel jest plikiem binarnym(wykonywalnym) lub obiektowym (.o), który chcemy utworzyć. Polecenia są Po rozpakowaniu źródeł, w katalogu /usr/src powinien pojawić się nowy katalog: krokami takimi jak wywołania kompilatora lub poleceń powłoki koniecznymi dla utworzenia celu. Jeśli linux-pobrana.wersja.jądra.

cel nie istnieje „make” go buduje zgodnie z poleceniem. W przeciwnym razie porównuje daty Kolejnym krokiem jest utworzenie dowiązania symbolicznego dla katalogu ze źródłami nowej wersji tworzenia celu z datami jego zależności. Jeśli są one późniejsze niż cel (przynajmniej jedna) cel jądra. W tym celu należy wejść do katalogu /usr/src i wydać polecenie: podlega przebudowaniu, bo zmienił się jakiś kod.

ln –s linux-pobrana.wersja.jadra linux

# przykaldowy plik Makefile

Jego utworzenie jest potrzebne dla kompilatora gcc, gdyż podczas kompilacji jądra, gcc odwołuje się CC = gcc

do katalogu /usr/src/linux, gdzie standardowo powinny znajdować się nagłówki jądra.

CFLAGS = -O1

Licz1.exe : licz1.o funkcje.o powitanie.o

Aby dokonać konfiguracji wpisujemy polecenie:

$(CC) $(CFLAGS) -o $@ $?

liczh.o : licz1.c

make menuconfig (alternatywa: make xconfig, make config)

$(CC) $(CFLAGS) -c $?

funkcje.o : funkcje.c

Konfiguracja odbywa się poprzez zaznaczenie potrzebnych opcji dzięki trzem reprezentacjom $(CC) $(CFLAGS) -c $?

graficznym:

powitanie.o : powitanie.c

<*> - podana opcja zostanie wdrążona do jądra na stałe, $(CC) $(CFLAGS) -c $?

< > - podana opcja nie zostanie wdrążona do jądra, clean:

<M> - podana opcja zostanie wdrążona do systemu jako moduł.

rm

*.o

Wszystkie wybrane opcje są zapisywane w pliku konfiguracyjnym „.config” znajdującym się w

katalogu ze źródłami jądra systemowego.

Wybrane zmiene automatyczne stosowane w plikach “make”:

$@ -symboliczna nazwa pliku celu w regule

Po zakończeniu konfiguracji potrzebnych opcji dla jądra systemowego należy je skompilować.

$* -rdzeń nazwy pliku (bez rozszerzenia po kropce)

Umożliwiają to następujące komendy:

$< -nazwa pliku pierwszej zależności od reguły

$^ -lista wszystkich zależności w regule

make dep - sprawdzenie zależności,

$? - lista zależności nowszych niż cel

make clean - usunięcie pozostałości po starej kompilacji jądra, Zmienne lokalne w plikach „make” są przypisywane różnym poleceniom na początku skryptu.

make bzImage - kompilacja jądra wraz z zapisaniem go w katalogu /usr/src/linux/arch/i386/boot, make modules - kompilacja modułów,

Aby wytworzyć kod produkcyjny korzystamy z ustawienia 3 poziomów optymalizacji poprzez opcję „-

make modules_install - instalacja modułów i przekopiowanie ich do katalogu Ox” (x=0,1,2.3). Poziom „-O2” jest odpowiedni dla większości programów.

/lib/modules/pobrana.wersja.jądra

W jednym pliku „Makefile” można definiować wiele różnych celów – kompilować i scalać wiele

programów. Wywołanie „make” odbywa się z odpowiednim parametrem stanowiącym nazwę celu i Jądro znajduje się w katalogu usr/src/linux/arch/i386/boot/bzImage i należy je zainstalować.

może zawierać opcje:

Aby je zainstalować należy przekopiować plik bzImage do katalogu /boot za pomocą polecenia: make [-<opcje>] <nazwa_celu lub plik_wykonywalny> cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-<wersja.jądra>

Kolejnym krokiem jest przekopiowanie do katalogu /boot pliku System.map: Wybrane opcje polecenia “make”(nie muszą występować):

-n : polecenia są składane i wyświetlane, ale nie wykonywane (dobre do testów) cp /usr/src/linux/System.map /boot/System.map-<wersja.jądra>

-I <katalog> : katalog do poszukiwania plików make poza katalogiem bieżącym (duże 'i') Należy również przekopiować do katalogu /boot plik initrd-<wersja.jądra>.img

-s : (silent) make nie wypisuje poleceń na ekranie

-f <plik> : nazwa pliku make inna niż „makefile” lub „Makefile”

Aby uruchomić system GNU/Linux z nowym jądrem należy dodać wpis do pliku konfiguracyjnego

-k : nie przerywa działania jeśli nie uda się zbudować jednego z celów programu grub, który znajduje się w katalogu /boot/grub.conf.

-d : (debug) wyświetlane są informacje debugowania

title <nazwa> (wersja_jądra)

-W<plik> : wykonuje się tak jakby wymieniony plik był zmodyfikowany (do testowania) root

(hd0,0)

kernel

/vmlinuz-<wersja.jądra> ro root=<partycja_systemowa> initrd

/initrd-<wersja.jądra>.img

3

4