Programowanie Systemów Wbudowanych
Transkrypt
Programowanie Systemów Wbudowanych
Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna KSEM WETI PG April 28, 2015 GNU Toolchain Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I GNU Toolchain to zbiór narzędzi do budowy i debugowania programów, zarówno prostych aplikacji jak i elementów jądra systemów Linux. I Toolchain zawiera: I I I I I I kompilator (GNU compiler), GNU linker GNU assembler GNU debugger narzędzia do manipulacji zbudowanymi plikami binarnymi (np. objdump, objcopy, readelf, strip, nm) glibc - podstawowa biblioteka C w systemach Linux The Linux Development Process Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain I Oprogramowanie Linux składa się ze względnie dużej liczby elementów, łączonych podczas budowania w zbiór małej liczby plików (wykonywalnych i niewykonywalnych): I I I I I pliki binarne aplikacji biblioteki (resources) dokumentacja dane dla systemu kontroli wersji (source code management, SCM) Pliki te są: I I spakowane w opublikowany pakiet dla konkretnej dystrybucji automatycznie zainstalowane na maszynie docelowej (z pominięciem etapu pakowania i instalacji pakietu) Cross-compilation The Linux Development Process Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Oprogramowanie Linux dostępne jest w dwóch formach: I archiwa źródeł (tarball); standardowy format to .tar.gz lub .tar.bz2. Rozpakowanie: tar xvfj toolchains.tar.bz2 lub: tar xvfz toolchains.tar.gz I system kontroli wersji (SCM); SCM automatyzuje proces pobierania źródeł, nadąża za zmianami oprogramowania, pobiera niezbędne patche. Cross-compilation Konfiguracja lokalnego środowiska I Pliki README i INSTALL opisują standardowy proces budowy programu, obejmujący m.in. konfigurację lokalnego środowiska I I różne platformy sprzętowe mogą mieć specyficzne ograniczenia (np. adresowanie pamięci little-endian lub big-endian), różne dystrybucje Linuxa mogą mieć różne wersje narzędzi i bibliotek systemowych. I Ponadto plik INSTALL powinien definiować sposób instalacji i deinstalacji programu, wraz z przykładami. I GNU Autoconf - narzędzie konfiguracji lokalnego środowiska w systemach UNIX. Skrypt configure automatycznie sprawdza, czy w systemie zainstalowane są narzędzia (i jakie ich wersje) do budowy programu: ./configure [OPTION]... [VAR=VALUE]... Na przykład: ./configure −−help Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation Konfiguracja lokalnego środowiska- GNU Make Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Większość oprogramowania Linux jest budowana przy użyciu narzędzia GNU make. Program ten czyta skrypt Makefile (lub makefile), który opisuje: I I I zależności pomiędzy plikami źródłowymi i plikami wynikowymi, sposób tworzenia plików wynikowych z plików źródłowych. Przykład (plik źródeł: hello.c): $ make $ ./hello Hello, World! I Makefile może być generowany automatycznie w przypadku przenośnego oprogramowania przewidzianego do pracy na różnych platformach. Automatyczny generator makefile identyfikuje wówczas dostepne narzędzia GNU i od nich uzależnia zawartosć pliku dla GNU Make (tak jest np. w przypadku narzędzi do kompilacji skrośnej). GNU Toolchain Cross-compilation Konfiguracja lokalnego środowiska- GNU Make Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Plik Makefile składa się głównie z reguł. Reguła ma następującą budowę: CEL: SKADNIKI KOMENDA gdzie CEL to nazwa pliku docelowego, który jest tworzony z plików wymienionych jako SKŁADNIKI, zaś KOMENDA podaje komendę, która tworzy plik docelowy CEL z plików składowych SKŁADNIKI I Przykład reguły: hello: hello.c aux.c gcc hello.c aux.c −o hello Reguła ta określa sposób tworzenia pliku wykonywalnego hello z plików hello.c i aux.c I Przed komendą musi obowiązkowo wystąpić znak tabulacji. GNU Toolchain Cross-compilation Narzędzia GNU Toolchain Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I Narzędzia GNU Toolchain automatycznie: I I I usprawniają powtarzalne cykle kompilacji zapewniają powtarzalność procesu kompilacji, eliminując możliwość popełnienia błędu czynią proces kompilacji (budowy) programu możliwie najprostszym. GNU Compiler Collection I GNU Compiler Collection (GNU C Compiler): I I 1987: Richard Stallman, założyciel GNU Project, postanowił opracować kompilator, który spełniałby wymagania wolnego oprogramowania (Free Software). kompilator GNU C szybko stał się popularny wśrod programistów wolnego oprogramowania ze względu na swoją przenośność. I Dziś GCC obsługuje różne języki programowania: C i C++, Ada, Fortran, Objective C, Java. I Jądra systemów Linux napisane są w języku C i skompilowane za pomocą GCC. I GCC współpracuje z procesorami o różnych architekturach: Intel IA32 ("x86"). AMD64, SPARC POWER/PowerPC oraz rosnącą liczbą procesorów wyspecjalizowanych. ”If it’s commercially available, GCC can probably compile code for it!” Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation Kompilacja pojedynczego pliku Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Proces budowy programu: compile ⇒ assembly GNU Toolchain ⇒ link I Kompilator: tłumaczy kod programu na język maszynowy (specificzny dla danej rodziny procesorów) I Assembler: tłumaczy skompilowane źródło na binarną reprezentację kodu maszynowego. I I I nadaje każdej instrukcji maszynowej adres pamięci (ale nie bezwzględny, raczej symbolicznie lub jako przesunięcie). tworzy listę wszystkich nierozwiązanych referencji, które prawdopodobnie zdefiniowane są w innych plikach programu Linker: łączy kod z plików wygenerowanych przez assembler (object code) w tzw. plik-kontener, który może być załadowany do pamięci i wykonany na danej platformie sprzętowej. Cross-compilation Programowanie Systemów Wbudowanych Program w pamięci GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation pamięć stos (adresy powrotu i zmienne lokalne) ⇓ ⇑ sterta (zmienne dynamiczne) zmienne statyczne program wysoki adres niski adres Kompilacja pojedynczego pliku Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I GCC nie potrafi zbudować wykonywalnego pliku programu, tłumaczy jedynie kod programu na język maszynowy. I Domyślnie GCC wykonuje wszystkie kroki potrzebne do zbudowania wykonywalnego pliku binarnego, jednak sam dokonuje jedynie kompilacji. Assembler i Linker to osobne narzędzia GNU Toolchain, z którymi komunikuje się kompilator. I Zwyczajowo plik wykonywalny dostaje nazwę a.out, chyba że użytkownik zdefiniuje ją inaczej za pomocą opcji -o kompilatora gcc. Kompilacja jednego źródła C Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna Przykład "Hello World" I kod źródłowy: /∗∗ Embedded Systems Programming − Hello World ∗/ #include <stdio.h> #include <stdlib.h> int main(int argc, char ∗∗argv) { printf("Hello, World!\n"); return(0); } I kompilacja: $ gcc −o hello hello.c I test: $ ./hello Hello, World! GNU Toolchain Cross-compilation Kompilacja wielu źródeł C Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I GNU linker potrafi łączyć ze sobą kilka plików objektów .o w jeden plik wykonywalny. I Przykład: message.c: #include <stdio.h> void goodbye_world(void) { printf("Goodbye, World!\n"); } Kompilacja message.c: gcc −c message.c Sterownik (driver) GCC woła swój wewnętrzny kompilator, przetwarza kod źródłowy na język maszynowy i przekazuje go na wejście zewnętrznego assemblera. Assembler tworzy plik z rozszerzeniem .o, który może być połączony przez GNU linker z innymi plikami .o. GNU Toolchain Cross-compilation Kompilacja wielu źródeł C Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna main.c: #include <stdlib.h> void goodbye_world(void); int main(int argc, char ∗∗argv) { goodbye_world(); return(0); } Kompilacja: gcc −c main.c Linkowanie: gcc −o goodbye message.o main.o Kompilacja i linkowanie w jednym poleceniu: gcc −o goodbye message.c main.c Uruchomienie programu: ./goodbye Goodbye, World! GNU Toolchain Cross-compilation Biblioteki zewnętrzne, GLIBC I Niemal każda aplikacja Liux używa biblioteki GLIBC (biblioteka GNU C) I I I I I I podstawowe operacje wejścia/wyjścia (np. zamknięcie programu) cienka wartwa między aplikacją a jądrem Linuxa; implementacja podstawowych procedur, które byłyby bardziej kosztowne (złożone), gdyby były w jądrze. Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation GCC zakłada, że GLIBC jest domyślnie dodawana do programu podczas etapu linkowania. Mimo to do źródeł programu należy dodać pliki nagłówkowe standardowych bibliotek Przykład: #include <stdio.h> #include <stdlib.h> #include <math.h> // system math library; part of GLIBC but not automatically inluded int main(int argc, char ∗∗argv) { ... } I Kompilacja i linkowanie: gcc −o trig −lm trig.c opcja -lm powoduje, że GCC przeszukuje bibliotekę matematyczną libm Biblioteki statyczne a współdzielone Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I Biblioteki statyczne (static) - podczas kompilacji programu kod biblioteki statycznej jest umieszczany w wynikowym pliku binarnym; każda funkcja ma tyle kopii, ile jest programów, które z niej korzystają. I Biblioteki współdzielone (shared) - tylko jedna wersja każdej funkcji współdzielona między aplikacjami; jest to możliwe dzięki pamięci wirtualnej - kilka niezależnych aplikacji ma bezpieczny dostęp do tego samego obszaru pamięci. Biblioteki statyczne a współdzielone Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Biblioteki współdzielone redukują rozmiar pliku wynikowego I Jeśli biblioteka jest współdzielona przez wiele różnych programów jednocześnie, pozostaje w pamięci i jest natychmiast dostępna. I Biblioteka współdzielona powinna być zbudowana tak, by jej działanie było niezależne od miejsca w pamięci, do którego została załadowana: gcc −fPIC −c message.c Flaga PIC informuje GCC, by w kodzie maszynowym programu nie umieszczał odwołań do adresów pamięci. Utworzenie biblioteki współdzielonej: (plik wyjściowy: libmessage.so): gcc −shared −o libmessage.so message.o GNU Toolchain Cross-compilation Biblioteki statyczne a współdzielone Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Użycie biblioteki współdzielonej: gcc −o goodbye −lmessage −L. main.o I I GCC informuje linkera, że ma połączyć kod pliku main.o z biblioteką libmessage.so. flaga -L oznacza, że biblioteki mogą znajdować się w bieżącym katalogu. Własna biblioteka współdzielona może być używana tak jak dostarczana wraz z dystrybucją Linux, pod warnkiem, że znajduje się w odpowiednim katalogu (np. /usr/lib/) ld-linux - dynamiczny linker; automatycznie uruchamiany, gdy uruchamiana jest aplikacja używająca bibliotek współdzielonych. Poszukuje ich w katalogu /lib i /usr/lib (te domyślne ścieżki mogą być zmienione w pliku konfiguracyjnym /etc/ld.so.conf. GNU Toolchain Cross-compilation Biblioteki statyczne a współdzielone Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I ldd - przeszukuje domyślne systemowe ścieżki bibliotek współdzielonych i wypisuje wersje tych bibliotek, używane przez program: ldd goodbye Przykładowy komunikat narzędzia ldd dla programu goodbye: linux−vdso.so.1 (0x00007ffc8f2bb000) libmessage.so => not found libc.so.6 => /lib/x86_64−linux−gnu/libc.so.6 (0x00007fb6d41c1000) /lib64/ld−linux−x86−64.so.2 (0x00007fb6d458e000) Przy próbie uruchomienia programu pojawi się błąd: ./goodbye ./goodbye: error while loading shared libraries: libmessage.so: cannot open shared object file: No such file or directory GNU Toolchain Cross-compilation Biblioteki statyczne a współdzielone Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna Rozwiązanie: I zmiana ustawień systemowych I instalacja libmessage.so w katalogach standardowych I ustawienie zmiennej środowiskowej LD_LIBRARY_PATH na dodatkową ścieżkę bibliotek współdzielonych: $ export LD_LIBRARY_PATH=$(pwd) I po tej operacji ldd zwróci: linux−vdso.so.1 (0x00007ffd78552000) libmessage.so => /opt/cpp_examples/libmessage.so (0x00007fc909dd2000) libc.so.6 => /lib/x86_64−linux−gnu/libc.so.6 (0x00007fc909a07000) /lib64/ld−linux−x86−64.so.2 (0x00007fc909fd5000) GNU Toolchain Cross-compilation GNU Binutils Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I GNU Binutils - zbiór narzędzi do tworzenia i obróbki plików wykonywalnych. Składa się z: I I I I I asemblera (GNU Assembler) linkera (GNU Linker) biblioteki obsługi różnych formatów plików z kodem narzędzi do obróbki plików z kodem (np. objdump) Binutils jest używany jako back-end przez GCC, ale też wiele innych programów operujących na kodzie. GNU Assembler Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Przetwarza kod skompilowany do języka maszynowego w kod nadający się do wykonania przez konkretny procesor. I GNU as obsługuje wiele różnych rodzin mikroprocesorów (włącznie z Intel IA32, czyli x86) I GNU as w danym systemie Linux jest wstępnie skonfigurowany do pracy z procesorem, na którym pracuje ów system, jednak można tą konfigurację zmienić (cross-compilation!) I Język maszynowy programu Hello World: gcc −S hello.c I Kompilacja źródła hello.s: as −o hello.o hello.s GNU Toolchain Cross-compilation GNU Linker Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain I Aby kod programu był wykonywalny, musi on zostać sformatowany do postaci ELF (Executable and Linkable Format), zrozumiałej przez systemy UNIX. Format ten obowiązuje: I I I I pliki wykonywalne, pliki obiektowe, bibliotki współdzielone zrzuty pamięci I Za formatowanie do ELF odpowiedziany jest linker. I Linker jest również odpowiedzialny za sprawdzenie, czy kod uruchamiany podczas startu (plik crtbegin.o automatycznie dołączany do aplikacji) oraz zamykania aplikacji (crtend.o) znajduje się w prawidłowym miejscu kodu wykonywalnego Cross-compilation GNU Linker Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I objcopy - kopiuje i przekształca pliki obiektowe generowane przez kompilator I objdump - zapisuje zawartość wykonywalnych plików binarnych w formacie tekstowym; wizualizuje zawartość plików wykonywalnych. Przykład: $ objdump −x −d −S hello GNU Debugger Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation C.D.N. Programowanie Systemów Wbudowanych Rodzaje toolchain-ów GNU Toolchain i kompilacja skrośna Pojecia podstawowe: I I I build machine (platforma budująca) - platforma budująca toolchain host machine (platforma hosta) - platforma na której działa toolchain target machine (platforma docelowa) - platformam, na ktorej działa skompilowany program. Rodzaje toolchain-ów I Native build machine arch. A I ⇒ host machine arch. A ⇒ target machine arch. A host machine arch. A ⇒ target machine arch. B Cross-compilation build machine arch. A ⇒ GNU Toolchain Cross-compilation Programowanie Systemów Wbudowanych Rodzaje toolchain-ów GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation I Cross-native - gdy toolchain działa na maszynie docelowej build machine arch. A I ⇒ host machine arch. B ⇒ target machine arch. B ⇒ target machine arch. C Canadian - rzadko spotykany build machine arch. A ⇒ host machine arch. B Kompilacja skrośna (cross-compilation) Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna I Narzędzia do kompilacji skrośnej muszą rozwiązywać dwa podstawowe problemy: I I I wszystkie wykorzystywane przez budowany program biblioteki C/C++ muszą być dostępne na maszynie budującej (build machine) kompilator oraz towarzyszące mu narzedzia musi generować kod możliwy do wykonania na platformie docelowej (target machine) Główne elementy kompilacji skrośnej: I I I toolchain do kompilacji skrośnej biblioteki C system plików (root filesystem, sysroot) na maszynie hosta z bibliotekami i plikami nagłówkowymi obecnymi również na platformie docelowej cross-compilation toolchain + sysroot = SDK GNU Toolchain Cross-compilation Narzędzia - Buildroot Buildroot I zbiór skryptów Makefile oraz patch-ów do budowy obrazów Linux dla systemów wbudowanych. I Generuje: I I I I toolchain do kompilacji skrośnej system plików (root filesystem) obraz jądra (kernel image) obraz programu rozruchowego (bootloader image) I Obsługuje różne architektury procesorów: x86, ARM, MIPS, PowerPC, etc. I Autor: Peter Korsgaard I Objęty licencją GNU GENERAL PUBLIC LICENSE V2 I Wykorzystanie Buildroot do budowy obrazu systemu dla Raspberry Pi: http://www.xappsoftware.com/wordpress/2013/06/06/how-tocreate-a-buildroot-environment-for-raspberry-pi/ Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation Narzędzia - Crosstool-NG Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation Crosstool-NG I I I Bardziej elastyczny (skalowalny) od Buildroot Strona: http://crosstool-ng.org Wykorzystanie Crosstool-NG do budowy kompilatora C i C++ dla Raspberry Pi: http://www.kitware.com/blog/home/post/426 Narzędzia - Eclipse Programowanie Systemów Wbudowanych GNU Toolchain i kompilacja skrośna GNU Toolchain Cross-compilation Eclipse I Eclipse + konfiguracja + Toolchain dla Intel Galileo: https://software.intel.com/en-us/iot/downloads I Wykorzystanie Eclipse do kompilacji skrośnej dla Raspberry Pi: http://hertaville.com/2012/09/28/development-environmentraspberry-pi-cross-compiler/