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