CS107 Kompilacja programów C za pomocą GCC
Pisane przez Chrisa Gregga, z modyfikacjami Nicka Troccoli
Kliknij tutaj, aby obejrzeć film instruktażowy.
Kompilator, którego użyjemy w CS107 nazywa się „GNU Compiler Collection” (gcc). Jest to jeden z najczęściej używanych kompilatorów i jest dostępny na wielu różnych platformach komputerowych.
gcc
Wykonuje krok kompilacji, aby zbudować program, a następnie wywołuje inne programy, aby złożyć program i połączyć jego części składowe w program wykonywalny, który można uruchomić. Dowiemy się trochę o każdym z tych kroków w CS107, ale miłą rzeczą jest to, że gcc
może wyprodukować cały wykonywalny program za pomocą jednego polecenia.
W CS107, będziemy głównie używać plików Makefile do kompilacji, składania i łączenia naszego kodu, ale plik Makefile uruchamia gcc
aby wykonać pracę. This is just a quick overview on how to compile and run your own programs should you decide to do so without a Makefile.
The simplest way to run gcc
is to provide gcc
a list of .c
files:
$ gcc hello.c$
Note that you do not put header files (.h
) into the gcc
command: it reads in the header files as it compiles, based on the #include
statements inside .c
files.
If the program compiled without errors or warnings, you don’t get any output from gcc
, and you will have a new file in your directory, called a.out
. To run this file, you need to tell the shell to run the file in the current directory, by using ./
before the name:
$ ./a.outHello, World!$
Na ogół nie chcemy, aby nasze programy nazywały się a.out
, więc można dać gcc
opcję, -o programName
, aby powiedzieć jej, jak ma nazywać uruchamiany plik:
$ gcc hello.c -o hello$ ./helloHello, World!$
Uwaga: uważaj, aby przypadkowo nie wprowadzić nazwy pliku uruchomieniowego, która jest taka sama jak twój plik wejściowy – coś w stylu:
$ gcc hello.c -o hello.c
Na myth
, twój profil został ustawiony tak, aby złapać błąd i nie kompilować go, pozostawiając twój plik źródłowy w takt. Nie jest tak w przypadku wielu innych systemów Linux, więc bądź ostrożny! Na innych systemach, GCC nadpisałby twój plik źródłowy nowym plikiem wykonywalnym.
gcc
przyjmuje wiele różnych opcji wiersza poleceń (flag), które zmieniają jego zachowanie. Jedną z najczęstszych flag jest flaga „poziomu optymalizacji”, -O
(duża litera 'o’). gcc
ma możliwość zoptymalizowania twojego kodu dla różnych sytuacji.
- -O lub -O1: Optymalizuj. Optymalizacja kompilacji zajmuje nieco więcej czasu, i dużo więcej pamięci dla dużych funkcji. Z
-O
, kompilator stara się zmniejszyć rozmiar kodu i czas wykonania, bez wykonywania żadnych optymalizacji, które zajmują dużo czasu kompilacji. - -O2: Optymalizuj jeszcze bardziej. GCC wykonuje prawie wszystkie wspierane optymalizacje, które nie wymagają kompromisu pomiędzy przestrzenią a szybkością. W porównaniu do
-O
, ta opcja zwiększa zarówno czas kompilacji jak i wydajność generowanego kodu. - -O3: Zoptymalizuj jeszcze bardziej.
-O3
włącza wszystkie optymalizacje określone przez-O2
a także włącza inne optymalizacje. Jest to często najlepsza opcja do użycia. - -O0: Zmniejsza czas kompilacji i sprawia, że debugowanie daje oczekiwane rezultaty. Jest to opcja domyślna.
- -Os: Zoptymalizuj pod kątem rozmiaru.
-Os
Włącza wszystkie-O2
optymalizacje, które zazwyczaj nie zwiększają rozmiaru kodu. Wykonuje również dalsze optymalizacje zaprojektowane w celu zmniejszenia rozmiaru kodu. - -Ofast: Lekceważenie ścisłej zgodności ze standardami.
-Ofast
Włącza wszystkie-O3
optymalizacje. Włącza również optymalizacje, które nie są ważne dla wszystkich programów zgodnych ze standardami. - -Og: Zoptymalizuj doświadczenie debugowania.
-Og
umożliwia optymalizacje, które nie przeszkadzają w debugowaniu. Powinien to być wybrany poziom optymalizacji dla standardowego cyklu edit-compile-debug, oferujący rozsądny poziom optymalizacji przy zachowaniu szybkiej kompilacji i dobrego wrażenia z debugowania. Będziemy używać-Og
w CS107, gdy będziemy debugować.
Zobacz stronę man
dla gcc
po więcej szczegółów na temat optymalizacji (lub zobacz tutaj, aby uzyskać więcej informacji o optymalizacjach).
Inną popularną flagą jest opcja -std=gnu99
, która mówi gcc
, aby użyć „wersji gnu c standardu c z 1999 roku.” Standard ten zapewnia składnię taką jak możliwość zdefiniowania zmiennej wewnątrz deklaracji pętli for (np. for (int i = ...)
. Będziemy używać tego standardu w CS107.
Wykorzystamy również flagę -g
, która pozwala nam używać debuggera, gdb, do podawania nam dokładnych numerów linii w naszym kodzie, kiedy go uruchamiamy.
Przykład:
$ gcc -std=gnu99 -g -Og loop.c -o loop
Jeśli jesteś zainteresowany jeszcze większą ilością informacji o gcc
, sprawdź Sekcję 1 tego dokumentu Stanford Unix Programming Tools, jak również pełny podręcznik gcc(GNU).