Wprowadzenie
W tej serii artykułów chcę omówić system kompilacji dystrybucji buildroot oraz podzielić się doświadczeniami związanymi z jego personalizacją. Będzie to praktyczne doświadczenie tworzenia małego systemu operacyjnego z interfejsem graficznym i minimalną funkcjonalnością.
Przede wszystkim nie należy mylić systemu kompilacji z dystrybucją. Buildroot może zbudować system z zestawu pakietów, które mu zaproponowano. Buildroot oparty jest na plikach make i dlatego ma ogromne możliwości personalizacji. Czy to wymiana pakietu na inną wersję, dodanie własnego pakietu, zmiana reguł kompilacji pakietu, czy też personalizacja systemu plików po zainstalowaniu wszystkich pakietów? To wszystko potrafi buildroot.
W Rosji buildroot jest używany, ale moim zdaniem brakuje ruskiej dokumentacji dla początkujących.
Celem pracy jest zbudowanie dystrybucji z live-bootem, interfejsem icewm i przeglądarką. Docelowa platforma to virtualbox.
Dlaczego warto tworzyć swoją własną dystrybucję? Często potrzebna jest ograniczona funkcjonalność przy ograniczonych zasobach. Jeszcze częściej w automatyzacji trzeba tworzyć oprogramowanie. Przystosowanie ogólnodostępnej dystrybucji poprzez usunięcie zbędnych pakietów i przekształcenie jej w firmware jest znacznie bardziej czasochłonne niż stworzenie nowego dystrybutora. Użycie Gentoo ma również swoje ograniczenia.
System Buildroot jest bardzo potężny, ale nic za ciebie nie zrobi. Może jedynie zapewnić możliwości i zautomatyzować proces kompilacji.
Alternatywne systemy kompilacji (yocto, open build system i inne) nie są rozważane ani porównywane.
Gdzie znaleźć i jak zacząć
Strona projektu — . Tutaj można pobrać aktualną wersję i przeczytać dokumentację. Tam można także skontaktować się ze społecznością, istnieje tracker błędów, listy mailingowe oraz kanał irc.
Buildroot operuje plikami defconfig dla docelowej płyty kompilacji. Defconfig to plik konfiguracyjny, zawierający tylko opcje, które nie mają wartości domyślnych. To właśnie on określa, co i jak będzie zbudowane. Można oddzielnie skonfigurować pliki konfiguracyjne busybox, linux-kernel, uglibc, bootloaderów u-boot i barebox, ale wszystkie one będą związane z docelową płytą.
Po rozpakowaniu pobranego archiwum lub sklonowaniu z gita mamy gotowy do pracy buildroot. Szczegóły dotyczące struktury katalogów można znaleźć w dokumentacji, opowiem o najważniejszych:
board — katalog z plikami specyficznymi dla każdej płyty. Mogą to być skrypty do tworzenia obrazów systemu (iso, sdcart, cpio i inne), katalog overlay, konfiguracja rdzeni i inne
konfiguracje — właściwa defconfig płyty. Defconfig to niepełna konfiguracja płyty. Przechowuje tylko parametry różniące się od domyślnych ustawień
dl — katalog z pobranymi kodami źródłowymi/plikami do budowy
output/target — zbudowany system plików uzyskanej ОС. Później z niego tworzone są obrazy do ładowania/instalacji
output/host — host-narzędzia do budowy
output/build — zbudowane pakiety
Konfigurowanie budowy odbywa się poprzez KConfig. Ta sama systema używana jest do budowy rdzenia linux. Lista najczęściej używanych poleceń (wykonuj w katalogu buildroot):
- make menuconfig — uruchomienie konfiguracji budowy. Można także użyć interfejsu graficznego (make nconfig, make xconfig, make gconfig)
- make linux-menuconfig — uruchomienie konfiguracji rdzenia.
- make clean — wyczyść wyniki budowy (wszystko co znajduje się w output)
- make — zbuduj system. Przy tym nie następuje powtórna budowa już zbudowanych procesów
- make defconfig_name — przełącz konfigurację na określony defconfig
- make list-defconfigs — pokaż listę defconfig’ów
- make source — tylko pobierz pliki instalacyjne, bez budowy.
- make help — wyświetl listę możliwych poleceń
Wažne uwagi i przydatne rady
Buildroot nie przearanżowuje już zbudowanych pakietów! Dlatego może powstać sytuacja, w której potrzebna będzie pełna przebudowa.
Można przearanżować pojedynczy pakiet komendą make packagename-rebuild. Na przykład, można przearanżować rdzeń linux:
make linux-rebuildBuildroot przechowuje stan każdego pakietu, tworząc .stamp-pliki w katalogu output/build/$packagename:

W związku z tym, można przearanżować root-fs i obrazy bez przearanżowania pakietów:
rm output/build/host-gcc-final-*/*.stamp_host_installed; rm -rf output/target; find output/ -name ".stamp_target_installed" | xargs rm -rf ; makePrzydatne zmienne
W buildroot istnieje zestaw zmiennych do wygodnej konfiguracji
- $TOPDIR — katalog główny buildroot
- $BASEDIR — katalog OUTPUT
- $HOST_DIR, $STAGING_DIR, $TARGET_DIR — katalogi budowy host fs, staging fs, target fs.
- $BUILD_DIR — katalog z rozpakowanymi i zbudowanymi pakietami
Wizualizacja
W buildroot istnieje możliwość wizualizacji. Można zbudować schemat zależności, wykres czasu budowy, wykres rozmiaru pakietów w finalnym systemie. Wyniki w postaci plików pdf (do wyboru są svn, png) w katalogu output/graph.
Przykłady poleceń wizualizacji:
generuj graph-dependszbuduj drzewo zależnościgeneruj -graph-dependszbuduj drzewo zależności dla konkretnego pakietuBR2_GRAPH_OUT=png generuj graph-buildzbuduj wykres czasu kompilacji z wyjściem w PNGgeneruj graph-sizezbuduj wykres rozmiaru pakietów
Przydatne skrypty
W katalogu buildroot znajduje się podkatalog utils z przydatnymi skryptami. Na przykład znajduje się tam skrypt, który sprawdza poprawność opisu pakietów. Może to być przydatne przy dodawaniu własnych pakietów (zrobię to później). W pliku utils/readme.txt znajduje się opis tych skryptów.
Zbudujemy stockowy dystrybucję
Ważne jest, aby przypomnieć, że wszystkie operacje są realizowane na koncie zwykłego użytkownika, nie root.
Wszystkie komendy są wykonywane w katalogu głównym buildroot. W dystrybucji buildroot już istnieje zestaw konfiguracji dla wielu popularnych płyt i wirtualizacji.
Zobaczmy listę konfiguracji:

Przechodzimy do konfiguracji qemu_x86_64_defconfig
generuj qemu_x86_64_defconfigI uruchamiamy budowę
makeBudowa kończy się pomyślnie, przyjrzyjmy się rezultatom:
![]()
Buildroot zbudował obrazy, które można uruchomić w Qemu i upewnić się, że działają.
qemu-system-x86_64 -kernel output/images/bzImage -hda output/images/rootfs.ext2 -append "root=/dev/sda rw" -s -SRezultat — uruchomiony w qemu system:

Tworzenie konfiguracji własnej płyty
Dodawanie plików płyty
Zobaczmy listę konfiguracji:

Na liście widzimy pc_x86_64_efi_defconfig. Stworzymy swoją płytę, kopiując ją z konfiguracji:
cp configs/pc_x86_64_bios_defconfig configs/my_x86_board_defconfigOd razu utworzymy katalog płyty do przechowywania własnych skryptów, rootfs-overlay i innych potrzebnych plików:
mkdir board/my_x86_boardPrzechodzimy do tej defconfig:
generuj my_x86_board_defconfigW ten sposób konfiguracja budowy (przechowywana w .config w katalogu głównym buildroota) odpowiada docelowej maszynie x86-64 z legacy (bios) bootowaniem.
Skopiujemy konfigurację linux-kernel (przyda się później):
cp board/pc/linux.config board/my_x86_board/Konfiguracja parametrów budowy przez KConfig
Uruchamiamy konfigurację:
generuj menuconfig Otworzy się okno KConfig. Istnieje możliwość konfiguracji z interfejsem graficznym (generuj nconfig, generuj xconfig, generuj gconfig):

Wchodzimy w pierwszy dział Target Options. Tutaj można wybrać celową architekturę, pod którą będzie prowadzone budowanie.

Opcje budowy — tutaj znajdują się różne ustawienia budowy. Można wskazać katalogi z kodami źródłowymi, liczbę wątków budowy, lustrzane odbicia do pobierania kodów źródłowych i inne ustawienia. Pozostawimy ustawienia domyślne.
Toolchain – tutaj konfigurujemy sam zestaw narzędzi do budowy. O nim więcej szczegółów.

Typ narzędziowy – typ używanego zestawu narzędzi. Może to być wbudowany w buildroot lub zewnętrzny zestaw narzędzi (można wskazać katalog z już zbudowanym zestawem lub url do pobrania). Dla różnych architektur dostępne są dodatkowe opcje. Na przykład dla arm można po prostu wybrać wersję zewnętrznego zestawu narzędzi Linaro.
Biblioteka C – wybór biblioteki C. Od tego zależy funkcjonowanie całego systemu. Zwykle używa się glibc, która obsługuje wszystkie możliwe funkcje. Może być jednak zbyt duża dla wbudowanego systemu, dlatego często wybiera się uglibc lub musl. Wybierzemy glibc (potrzebne to będzie później do użycia systemd).
Nagłówki jądra i niestandardowe nagłówki jądra – muszą być zgodne z wersją jądra, które będzie w budowanym systemie. Dla nagłówków jądra można również podać ścieżkę do tarballa lub repozytorium git.
WERSJE KOMPILATORA GCC – wybór wersji kompilatora, która będzie użyta do budowy
Włącz wspieranie C++ – wybierzemy budowanie z wsparciem dla bibliotek c++ w systemie. Będzie to nam potrzebne w przyszłości.
Dodatkowe opcje gcc – można określić dodatkowe opcje kompilatora. Na razie nam to nie jest potrzebne.
Konfiguracja systemu pozwala na określenie przyszłych parametrów stworzonego systemu:

Większość punktów jest jasna z nazwy. Zwróćmy uwagę na następujące punkty:
Ścieżka do tabel użytkowników – tabela z tworzonymi użytkownikami ().
Przykład pliku. Zostanie utworzony użytkownik user z hasłem admin, automatycznie gid/uid, powłoką /bin/sh, domyślną grupą user, członkiem grupy root, komentarzem Foo user
[alexey@alexey-pc buildroot ]$ cat board/my_x86_board/users.txt
user -1 user -1 =admin /home/user /bin/sh root Foo userKatalogi nakładki systemu plików – katalog, który nakłada się na zbudowany target-fs. Dodaje nowe pliki i zastępuje istniejące.
Niestandardowe skrypty do uruchomienia przed utworzeniem obrazów systemu plików – Skrypty wykonywane bezpośrednio przed spakowaniem systemu plików w obrazy. Na razie zostawimy ten skrypt pusty
Przejdźmy do sekcji Jądro

Tutaj ustawiane są opcje jądra. Samo jądro konfiguruje się za pomocą make linux-menuconfig.
Wersję jądra można ustawić na różne sposoby: wybrać z proponowanych, wpisać wersję ręcznie, wskazać repozytorium lub gotowy tarball.
Konfiguracja jądra – ścieżka do konfiguracji jądra. Można wybrać konfigurację domyślną dla wybranej architektury lub defconfig z Linux. W źródłach Linux znajduje się zestaw defconfigów dla różnych systemów docelowych. Można je znaleźć, . Na przykład, dla płyty beagle bone black można .
Sekcja Target packages pozwala wybrać, które pakiety zostaną zainstalowane w budowanym systemie. Na razie zostawimy to bez zmian. Później dodamy nasze pakiety do tej listy.
Obrazy systemu plików — lista obrazów systemów plików, które będą zbierane. Dodamy obraz ISO.

Bootloadery — wybór zbieranych bootloaderów. Wybierzemy isolinix.

Konfiguracja Systemd
Systemd staje się jednym z filarów linuksa, obok jądra i glibc. Dlatego jego konfigurację wydzieliliśmy do osobnego punktu.
Konfiguruje się przez make menuconfig, następnie Target packages → System tools → systemd. Tutaj można określić, które usługi systemd zostaną zainstalowane i uruchomione podczas startu systemu.

Zapisanie konfiguracji systemu
Zapisujemy tę konfigurację przez KConfig.
Następnie zapiszmy nasz defconfig:
make savedefconfigKonfiguracja jądra Linux
Konfiguracja jądra linuksa jest wywoływana następującą komendą:
make linux-menuconfigDodajemy wsparcie dla karty graficznej Virtualbox.

Dodamy wsparcie dla integracji gościa Virtualbox.

Zapisujemy i wychodzimy. WAŻNE: konfiguracja zostanie zapisana w output/build/linux-$version/config, ale nie w board/my_x86_board/linux.config

Dlatego trzeba ręcznie skopiować konfigurację do miejsca przechowywania:
cp output/build/linux-4.19.25/.config board/my_x86_board/linux.configNastępnie wykonamy pełną rekonstrukcję całego systemu. Ponieważ buildroot nie przerekompilowuje już zbudowanego, należy ręcznie wskazać pakiety do rekonstrukcji. Aby nie tracić czasu i nerwów, lepiej jest całkowicie zbudować mały system):
make clean;makePo zakończeniu kompilacji uruchamiamy VirtualBox (sprawdzano na wersji 5.2 i 6.0) z bootowaniem z płyty CD. Parametry systemu:

Uruchomienie z zbudowanego obrazu ISO:

Lista użytych materiałów
- Podręcznik Buildroot
Źródło: habr.com
