Kompilacja całego systemu lub pakietów
Ostatnia zmiana: 2024-11-26 18:34
Ten poradnik nie jest przeznaczony dla zupełnie początkujących - jeżeli nie wiesz co to
make, jak nakłada się łatki czy jak wygląda praca z repozytorium - najpierw zgromadź tą wiedzę u wujka Google.
Założenie - w poradniku będzie opisana kompilacja wersji stabilnej OpenWrt, źródła będą znajdować się w katalogu domowym, w podkatalogu
openwrt. Kompilację wykonuje się na zwykłym komputerze, więc do kompilacji potrzebny jest system *unix (np. Linux) lub MacOS/OS X. System powinien zawierać podstawowy zestaw programów przeznaczonych do kompilacji, czyli np. dla debiana/ubuntu/mint należy zainstalować odpowiednie pakiety poleceniem:
$ sudo apt install build-essential binutils bzip2 gawk gettext git libncurses5-dev patch unzip zlib1g-dev
oraz w zależności od wersji systemu
$ sudo apt install python3-setuptools
lub
$ sudo apt install python3-distutils
Mogą być też potrzebne też inne pakiety - jeżeli tak będzie to podczas procesu kompilacji zwykle zostanie wyświetlona odpowiednia informacja.
Do kompilacji można używać systemu na maszynie wirtualnej, ale wymagane jest 4GB lub więcej pamięci ram. Przy 2GB mają wystąpić problem typu
out-of-memory.
OpenWrt nie powinno się kompilować jako użytkownik root. Najlepiej zrobić jako jako "zwykły" użytkownik.
Kompilacja działa prawidłowo dla Debiana i pochodnych (Ubuntu/Mint), dla x86/64. W tym przykładzie kompilowany będzie system dla architektury
ath79 - w przypadku innej platformy należy po prostu dostosować polecenia czy opcje. W zależności od wybranych opcji potrzebne jest od 10GB do kilkuset gigabajtów wolnej przestrzeni dyskowej i dostęp online do internetu (do pobierania źródeł). Może się wydawać dziwne że potrzeba aż kilkudziesięciu gigabajtów żeby wyszedł obraz o wielkości kilku megabajtów, ale OpenWrt kompiluje wszystko łącznie z kompilatorem C dla danej architektury, więc większość tej przestrzeni wymagana jest do kompilacji odpowiednich wersji programów narzędziowych.
Kompilacja OpenWrt
Pobieranie źródeł określonego wydania stabilnego
$ cd ~
$ git clone https://github.com/openwrt/openwrt.git
$ cd openwrt
$ git fetch --tags
$ git checkout v23.05.5
Te polecenia pobierają sam podstawowy system, aktualną stabilną wersję wydania OpenWrt (numer wersji może się zmienić, więc należy pobrać tą wersję która ma być kompilowana). Listę wszystkich dostępnych wersji można uzyskać poleceniem:
Dostępne są jeszcze dodatkowe pakiety, które uzupełniają całość (tzw.
feeds), które też warto pobrać.
Wszystkie poniższe operacje wykonuje już się będąc w katalogu ze źródłami, czyli wg założeń w
~/openwrt.
Wydanie stabilne w określonej wersji (
tag) nie zmienia się i zawsze jest w tej samej wersji. Jeżeli wyszło nowe wydanie OpenWrt należy zrobić
git checkout podając jako argument odpowiedni
tag.
Pobieranie źródeł aktualnego wydania stabilnego (opcjonalnie)
Jeżeli chcemy skompilować aktualną gałąź wydania stabilnego OpenWrt 23.05 (tzw. "branch" openwrt-23.05, który wewnętrznie przez samo OpenWrt nazywany jest 23.05-SNAPSHOT) to zamiast określonego wydania (
tag) robimy:
$ git checkout openwrt-23.05
Branch i tags to nie jest to samo!
Jeżeli wybraliśmy całą gałąź wersji stabilnej (
branch openwrt-23.05) to są tam wprowadzane poprawki dopóki jest ona utrzymywana (to z niej właśnie kiedyś może powstać następna wersja stabilna oznaczona określonym numerem). Aktualizację tej gałęzi można wykonać poleceniami (będąc w katalogu ze źródłami):
$ git pull
$ make package/symlinks
$ make defconfig
O ile byliśmy przełączeni na
branch openwrt-23.05 (można to sprawdzić poleceniem
git branch). Zawartość repozytorium gałęzi wydania stabilnego zmienia się co jakiś czas (a jeszcze rzadziej wydawane są oficjalne wydania obrazów przez zespół OpenWrt), więc jeżeli budujemy obrazy to warto mieć aktualne źródła.
Konfiguracja
Tu należy wybrać żądną platformę i pakiety. Na samym początku wystarczy zostawić wartości domyślne, wybieramy tylko
Target System np. Atheros ATH79 oraz
Target Profile jako TP-Link TL-WR1043ND jeżeli chcemy kompilować dla tego urządzenia.
Znaczek <*> oznacza że z tego pakietu będzie z tego zrobiona paczka ipk i zostanie wkompilowany w wynikowy obraz, <M> - zostanie tylko skompilowany jako paczka. <--> oznacza że pakiet jest domyślnie wybrany, bo od niego zależy inny pakiet i nie da się go odznaczyć. Jeżeli wiemy że jakiś pakiet będzie używany i niezbyt często aktualizowany (np. moduły do USB, serwer ftp czy transmission) warto takie pakiety wkompilować w obraz - będą zajmowały znacznie mniej miejsca niż ich późniejsza instalacja w systemie.
Kompilacja środowiska
Podczas kompilacji wymagane jest połączenie do internetu, ponieważ ściągane są źródła pakietów (można ściągnąć najpierw wszystkie wymagane źródła poleceniem
make download). Początkowa kompilacja (kroskompilator, kernel, pakiety) w zależności od ilości wybranych pakietów może trwać nawet kilka godzin! Przy kolejnych kompilacjach, np. dodaniu kolejnego pakietu, kompilacja będzie już krótsza, bo kompilowane są tylko zmiany.
Jeżeli mamy kilka rdzeni w CPU to przy późniejszych operacjach możemy uruchomić kompilację "równoległą" poleceniem
(nie należy używać tej opcji jeżeli wyskoczą błędy podczas kompilacji i chcemy się dowiedzieć w jakich pakietach się one pojawiły).
Jeżeli chcemy uzyskać więcej informacji podczas kompilacji należy posłużyć się odpowiednim przełącznikiem
Obrazy wynikowe i pakiety zostaną umieszczone w podkatalogu
bin/. Jeżeli zaznaczymy za dużo pakietów i przekroczy to dopuszczalny rozmiar obrazów (np. 8MB dla TL-WR1043ND v1) to obraz po prostu nie zostanie wygenerowany.
Czasami (w bardzo rzadkich przypadkach) może przydać się zmiana opcji kompilacji kernela. Można to zrobić poleceniem (po uprzedniej kompilacji systemu!)
zaznaczyć niezbędne opcje, zapisać a potem jeszcze raz skompilować cały system poleceniem
make.
Czyszczenie kompilacji
Przy zmianie czegoś w kernelu może okazać się konieczna ponowna rekompilacja jądra i pakietów z modułami, przed kompilacją należy więc je wyczyścić:
$ make target/linux/clean
Czasami wykonane zostało więcej zmian i nie da się skompilować ponownie obrazu. W takich przypadkach pomaga wyczyszczenie całego środowiska z plików kompilacji:
Dodanie własnych plików do obrazu
Niekiedy istnieje potrzeba dodania do obrazów własnych plików konfiguracyjnych, ustawień lub skryptów. OpenWrt posiada do tego specjalny mechanizm, pozwalający łatwo wprowadzać zmiany do obrazu. Tworzymy folder o nazwie
files w głównym katalogu z naszymi źródłami:
$ cd ~
$ cd openwrt
$ mkdir -p files
A następnie umieszczamy w nim pliki lub katalogi które mają znaleźć się w docelowym obrazie. Cała struktura katalogów zostanie przeniesiona w identyczny sposób, więc np. jeżeli chcemy podmienić plik
/etc/banner w obrazie wynikowym na swój, to w katalogu
files robimy podkatalog
etc a w nim umieszczamy plik
banner z własną zawartością:
$ mkdir -p files/etc
$ echo ">>>> to dziala!!! <<<<" > files/etc/banner
Jeżeli chcemy dodać skrypt który wykonuje się
jeden raz przy uruchomieniu routera (np. wprowadza jakiś ustawienia - poniższy przykład uruchamia wifi przy starcie routera) to należy to zrobić w katalogu
etc/uci-defaults, np tak:
$ mkdir -p files/etc/uci-defaults
$ chmod 755 files/etc/uci-defaults/01-mojskrypt.sh
$ echo "#!/bin/sh" > files/etc/uci-defaults/01-mojskrypt.sh
$ echo "uci del wireless.@wifi-device[0].disabled" >> files/etc/uci-defaults/01-mojskrypt.sh
$ echo "uci commit" >> files/etc/uci-defaults/01-mojskrypt.sh
Kompilacja pojedynczego pakietu
$ make package/nazwa_katalogu_z_pakietem/compile
Gdzie
nazwa_katalogu_z_pakietem to nazwa katalogu w którym znajduje się pakiet (to trzeba niestety wiedzieć). Czyli jeżeli chcemy skompilować np. pakiet
libffmpeg, a znajduje się on w katalogu
ffmpeg, to kompilacja wygląda następująco: "make package/ffmpeg/compile", a nie "make package/libffmpeg/compile"! Żeby pakiet dało się skompilować musi być także wcześniej zaznaczony w konfiguracji (w
make menuconfig - trzeba go wybrać przez <M> lub <*>).
Dostępna jest opcja czyszczenia kompilacji pakietu, czyli
$ make package/nazwa_katalogu_z_pakietem/clean
Co może być pomocne w przypadku dużych aktualizacji pakietów czy samodzielnego tworzenia łatek.
Aby móc skompilować jeden pakiet wcześniej musi być skompilowane całe środowisko dla danej platformy!
Kompilacja programu z kodu źródłowego
Ogólnie - należy zrobić odpowiedni plik
Makefile który pozwoli na przygotowanie pakietu ze skompilowanym programem. W niektórych przypadkach chcemy tylko skompilować prosty program i można to zrobić "ręcznie".
Kroskompilator i resztę wymaganych plików (nagłówki, biblioteki) można znaleźć w katalogu
staging_dir/toolchain-XXX (dla ath79 i openwrt-22.03 jest to np.
staging_dir/toolchain-mips_24kc_gcc-11.2.0_musl). Kroskompilator znajduje się w podkatalogu
bin (
mips-openwrt-linux-musl-gcc), biblioteki są w
staging_dir/target_*/usr/lib, pliki nagłówkowe w
staging_dir/target_*/usr/include (w zależności od wersji mogą to być katalogi odpowiednio
usr/bin,
usr/lib i
usr/include). Kompilacja przykładowego programu może więc wyglądać następująco:
$ export STAGING_DIR=~/openwrt/staging_dir/toolchain-mips_24kc_gcc-11.2.0_musl
$ cd ${STAGING_DIR}
$ bin/mips-openwrt-linux-musl-gcc -o program plik1.c plik2.c ... -I${STAGING_DIR}/../target-mips_24kc_musl/usr/include -L${STAGING_DIR}/../target-mips_24kc_musl/usr/lib -ljakas_biblioteka
Oczywiście należy podać wszystkie opcje kompilacji i linkowania niezbędne do stworzenia danego programu (zamiast
plik*.c i
jakas_biblioteka). Powyższy przykład sprawdzi się dla prostych programów, dla bardziej zaawansowanych projektów prościej jest napisać odpowiedni
Makefile podobnie jak to jest zrobione dla innych pakietów w katalogach
package lub
feeds. Budowa takiego Makefile opisana jest na wiki openwrt (po angielsku):
http://wiki.openwrt.org/doc/devel/packagesPrzykładowy program
helloworld z odpowiednim
Makefile dostępny jest tutaj:
http://dl.eko.one.pl/projekty/helloworld.tar.gzAby móc skompilować własny pakiet wcześniej musi być skompilowane całe środowisko dla danej platformy i niezbędne biblioteki!
Kompilacja Gargoyle
Generalnie kompilacja wygląda w podobny sposób jak normalnego OpenWrt z tą różnicą, że Gargoyle zawiera własne skrypty służące do nakładania łatek i budowania całości.
Pobieranie źródeł
$ git clone https://github.com/ericpaulbishop/gargoyle.git
$ cd gargoyle
Kompilacja
Jeżeli chcemy zbudować
wszystko co buduje gargoyle:
lub można skompilować określoną platformę np:
lub określony subtraget, np:
Listę targetów/subtargetów można znaleźć w źródłach gargoyle w katalogu
targets.
Gargoyle samodzielnie pobiera źródła OpenWrt, nakłada swoje łatki i kompiluje środowisko. Po wykonaniu w/w operacji powstaje katalog o nazwie np.
ath79-src który zawiera wszystkie źródła wraz nałożonymi już łatkami. Jeżeli potrzebujemy minimalnej zmiany typu dodanie pakietu czy coś podobnego to nie ma sensu ponownie kompilować całego środowiska - należy po prostu wejść do tego katalogu i wykonać polecenia
make menuconfig && makeTworzenie własnego repozytorium
"Przepis" jak zrobić repozytorium pakietów zawarty jest w źródłach OpenWrt:
https://github.com/openwrt/openwrt/blob/openwrt-24.10/package/Makefile#L136Do utworzenia repozytorium niezbędne jest posiadania skryptów i plików wykonywalnych wchodzących w skład SDK OpenWrt, więc najlepiej posłużyć się źródłami z których zostały pakiety skompilowane.
Należy utworzyć katalog tymczasowy:
I skopiować do niego pakiety
ipk które mają wchodzić w skład repozytorium i mają zostać zaindeksowane.
Zakładając że źródła OpenWrt mamy w katalogu
/home/user/openwrt/ath79/generic należy wykonać po kolei:
$ cd /tmp/x
$ export OPENWRTDIR=/home/user/openwrt/ath79/generic
$ MKHASH=$OPENWRTDIR/staging_dir/host/bin/mkhash PATH=$OPENWRTDIR/staging_dir/host/bin:$PATH $OPENWRTDIR/scripts/ipkg-make-index.sh . 2>&1 > Packages.manifest
$ grep -vE '^(Maintainer|LicenseFiles|Source|SourceName|Require|SourceDateEpoch)' Packages.manifest > Packages
$ case "$(((64 + $(stat -L -c%s Packages)) % 128))" in 110|111) { echo ""; echo ""; } >> Packages; esac
$ gzip -9k Packages
$ $OPENWRTDIR/staging_dir/host/bin/usign -S -m Packages -s $OPENWRTDIR/key-build
$ cp $OPENWRTDIR/key-build.pub ./moje-repo.pub
To jest gotowe repozytorium. Teraz należy zawartość katalogu
/tmp/x wystawić w internecie tak, aby można było bezpośrednio pobierać pliki z danego adresu URL. Zakładamy że udostępniamy adres URL np.
https://moje-repo.domena.pl/openwrt/pakiety, czyli powinno dać się pobrać bezpośrednio plik np.
https://moje-repo.domena.pl/openwrt/pakiety/Packages.gzAby móc instalować pakiety z takiego repozytorium należy do routera z OpenWrt dodać do pliku /etc/opkg/customfeeds.conf następujący wpis:
src/gz moje_pakiety https://moje-repo.domena.pl/openwrt/pakiety
Gdzie
moje_pakiety to dowolna nazwa ale musi być unikalna dla każdego dostępnego repozytorium.
Jeżeli używany jest inny obraz OpenWrt, który nie był skompilowany z w/w źródeł to może on nie zawierać klucza publicznego naszego repozytorium. W takim przypadku należy jeszcze dodać do routera ten klucz poleceniami:
# wget https://moje-repo.domena.pl/openwrt/pakiety/moje-repo.pub -O /tmp/moje-repo.pub
# opkg-key add /tmp/moje-repo.pub
Następnie należy wykonać
opkg update, powinna wczytać się lista wszystkich pakietów i można instalować już żądane pakiety.