Czy Wasz zespół kiedykolwiek poświęcał czas, aby dokładnie zdefiniować, jaki powinien być system budowania aplikacji — system kompilacji? Często widać, że osoby zainteresowane zaczynają projekt, mając pewien luźny pomysł, świadomi tego, że potrzebują jakiegoś systemu kompilacji oraz potoku ciągłej integracji/ciągłego wdrażania (CI/CD). Jednak, gdy narzędzie takie jak oparte na Eclipse kompilatory/IDE od dostawcy układów wbudowanych może pomyślnie skompilować przykładowy projekt, często stawia się ptaszka przy zadaniu związanym z systemem kompilacji. Zespoły następnie w pośpiechu rozwijają kod bez dalszych rozważań nad systemem, który później buduje i wypuszcza ich kod.
Bez dobrze sprecyzowanej wizji tego, jak powinna wyglądać całość, można odkryć, że grupa programistów jest mniej produktywna, niż mogłaby być. Powoduje to, że pomijane są istotne funkcje i koncepcje, które napędzają szybszy i niezawodny rozwój oprogramowania. Istnieje duża szansa, że sam zespół nawet tego nie zauważy, ponieważ nie wykorzystuje stosownych metryk, ani nie szacuje, jakie są koszty czy czas.
W poniższym artykule zostanie omówiona postać idealnego projektu budowania aplikacji dla systemu wbudowanego. A więc jego wejścia i wyjścia oraz jak można zacząć rozwijać własny, doskonały system kompilacji.
Z czego składa się perfekcyjny system kompilacji?
Kiedy o nim słyszymy, prawdopodobnie od razu na myśl przychodzi instrument taki jak make czy cmake. Narzędzie to zbiera wszystkie dane wejściowe, a następnie przekształca je w binarny plik, który można umieścić na docelowym urządzeniu. Niestety, jest to o wiele więcej niż tylko instrument, który sprawia, że dzieje się jakaś magia.
System budowania powinien zawierać następujące elementy:
* Repozytoria — to miejsce, z którego pobierany jest kod źródłowy do kompilacji (może być jedno lub więcej).
* Kod źródłowy — to wejścia do systemu, składające się z konfiguracji platformy źródłowej, kodu wygenerowanego i pisanego ręcznie.
* Testy — to testy jednostkowe, integracyjne i systemowe, używane do weryfikacji zachowania kodu po kompilacji.
* Konfiguracje kompilacji — określają, jaki będzie wynik kompilacji.
* Narzędzie kompilacyjne — instrument, który zbiera wszystkie dane wejściowe i generuje oczekiwany rezultat w postaci pliku binarnego/heksadecymalnego/itp. ze skompilowanym firmware.
Dla zespołu pracującego nad nowoczesnym oprogramowaniem wbudowanym warto nawet rozważyć włączenie potoku CI/CD do systemu budowania aplikacji. Potok CI/CD to zestaw narzędzi, które nie tylko automatyzują wiele procesów kompilacji, ale mogą także wypuścić najnowsze oprogramowanie do użytku. W poniższym opisie omówione zostaną kluczowe elementy oddzielnie, a potokowi CI/CD poświęcony zostanie osobny artykuł.
W ramach przedmiotowego systemu kompilacji dwie kluczowe dziedziny wymagają określenia pewnej wizji; są to konfiguracje kompilacji oraz kod źródłowy. Przyjrzyjmy się krótko tym zagadnieniom.
Definiowanie idealnego systemu kompilacji
Wiele zespołów programistów, tworzących systemy wbudowane, posiada tylko jedną konfigurację kompilacji, czyli tryb debugowania. Konfiguracje debugowania są świetne, gdy chcemy uruchomić kod w laboratorium lub na stanowisku testowym. Choć budowanie w trybie debugowania jest pewnym standardem, to nie powinno ono być konfiguracją kompilacji, którą używamy najczęściej. Nie powinno to być ujęciem domyślnym!
W artykule zatytułowanym: „Opanowanie systemów budowania oprogramowania wbudowanego: Poznanie 5 istotnych konfiguracji”, wskazano, że istnieje pięć zasadniczych konfiguracji kompilacji, które powinno się wykorzystywać:
1. Analiza — wykonuje analizę metryczną kodu źródłowego.
2. Symulacja — kompiluje kod do wykonania w środowisku gospodarza, a nie na docelowym urządzeniu.
3. Testy — kompiluje i uruchamia testy jednostkowe, integracyjne i regresji.
4. Wersja finalna — kompiluje kod do wersji przeznaczonej do instalacji na sprzęcie klienckim.
5. Debugowanie — kompiluje kod do wykonania na docelowym urządzeniu, ale w warunkach laboratoryjnych.
Czy w swojej praktyce używacie wszystkich tych konfiguracji kompilacji? Czy kiedykolwiek ich wykorzystanie omawiane było z całym zespołem software?
Każdy nowoczesny system kompilacji oprogramowania wbudowanego powinien zawierać w sobie te pięć konfiguracji. Idealny powinien przynajmniej umożliwiać korzystanie z każdej z nich. Jednak, jeśli ich spożytkowanie nie było dotychczasowo omawiane i zdefiniowane, to może okazać się, że mamy w systemie kompilacji tylko konfigurację debugowania i brakuje pozostałych.
Definicja stosu programowego dla perfekcyjnego systemu kompilacji
Może się wydawać, że stos oprogramowania, który jest wykorzystywany, nie ma nic wspólnego z systemem kompilacji aplikacji. Niemniej, wybrane konfiguracje kompilacji mogą dyktować organizację stosowanego oprogramowania. Przecież budowanie kodu w celu symulacji aplikacji nie powinno obejmować np. sterowników niskiego poziomu. Można w ten sposób odkryć, że nawet używane w systemie middleware jest zupełnie inne, zależnie od stosu oprogramowania! Zdefiniowanie idealnych konfiguracji kompilacji może wpłynąć na wykorzystywany stos oprogramowania i odwrotnie.
Nowoczesny stos oprogramowania wbudowanego będzie obejmować kilka warstw niezależnego oprogramowania, które są ze sobą łączone poprzez tzw. HALe (warstwy abstrakcji sprzętu) i interfejsy API. Docelowy stos oprogramowania prawdopodobnie będzie zawierać następujące elementy:
1. Konfiguracja Platformy — oprogramowanie generowane przez narzędzia docelowego systemu, takie jak sterowniki niskiego poziomu, system operacyjny typu RTOS oraz middleware.
2. Kod aplikacji wygenerowany przez model — oprogramowanie generowane przez narzędzie modelujące. Mogą to być na przykład maszyny stanów, algorytmy DSP itp.
3. Kod zarządzania konfiguracją — oprogramowanie generowane i zarządzane przez kod systemowy. Przykładem może być liczba grzałek lub zaworów włączonych w danej aplikacji. To dosłownie kod konfiguracyjny oparty na plikach formatowanych w formacie np. YAML lub innym.
4. Ręcznie pisany kod aplikacji — oprogramowanie stworzone przez zespół programistów bez pomocy innych narzędzi.
5. Konfiguracje testów — różne ustawienia i kod do skutecznego uruchamiania testów jednostkowych, integracyjnych, systemowych i innych, jakie przeprowadzane są w systemie.
Gdy dokładnie zdefiniowano wykorzystywany stos oprogramowania i uwzględnione zostanie to, gdzie kod znajduje się w stosie i jak jest generowany, szybko uda się dostrzec wiele korzyści. Na przykład omawiany stos oprogramowania pozwoli na tworzenie łatwo konfigurowalnego, przenośnego i nieskomplikowanego w kwestii wielokrotnego wykorzystania oprogramowania do użytku w szeregu aplikacji. Choć można uznać to za zbędne, w pewnych firmach można spostrzec tendencję do budowania wewnętrznych platform, które umożliwiają wprowadzanie wielu produktów opartych na częściowo wspólnym kodzie źródłowym. Aby to uzyskać, potrzebny jest elastyczny stos oprogramowania i konfiguracja kompilacji, które go obsługuje.
Przykładowy system kompilacji
Każdy programista i zespół będą wiedzieć, co ich idealny system budowania aplikacji ma za zadanie osiągnąć. Jak dotąd przedstawiono pewne pomysły na to, co powinien zawierać taki perfekcyjny projekt. Gdyby połączyć wszystkie te koncepcje, można otrzymać diagram wyglądający mniej więcej jak na rysunku 1 poniżej.
Rys.1. Idealny system kompilacji, łączący istotne
konfiguracje kompilacji i stosy oprogramowania
dla nowoczesnych systemów wbudowanych.
Powyższy schemat obejmuje wszystkie elementy, o których wspominano powyżej. Po pierwsze, odznaczone są repozytoria prowadzące do chmury i procesu CI/CD u dołu. Następnie, na podstawie zapisanych konfiguracji kompilacji i stosów oprogramowania (widać stos oprogramowania u góry po lewej stronie) definiowane jest środowisko i sposób kompilacji. Finalnie, jak obrazuje to schemat, wykorzystanie testów musi być w systemie kompilacji uwzględnione. Wydaje się, że obecnie programiści wbudowani coraz chętniej korzystają z testów jednostkowych itp. Jednak wciąż jest jeszcze długa droga do przebycia, aby dorównać do standardów branżowych. Ostatecznie, widać jak wszystkie te elementy oprogramowania są łączone w różnych konfiguracjach kompilacji, aby uruchamiać testy, symulować aplikację i wykonywać kod na docelowym urządzeniu. W omawianym schemacie wykluczono konfigurację kompilacji: „analiza”, ponieważ w żaden sposób nie: „przetestowuje” to kodu.
Rysunek 1 przedstawia pomysł na to, jak powinien wyglądać nowoczesny system budowania oprogramowania embedded. Należy zauważyć, że jest on niezależny od narzędzia kompilacyjnego. Można użyć takiego jak make, cmake lub innego preferowanego systemu budowania. Zapewnia to elastyczność i ułatwia ponowne wykorzystanie. System ten obejmuje także testowanie i, co być może równie istotne, założenie, że warto symulować i emulować kod naszej aplikacji.
Podsumowanie
Niezależnie, czy korzystacie dzisiaj z idealnego dla siebie systemu budowania, czy wiecie, jak taki perfekcyjny projekt wygląda i jakie korzyści tworzy dla Waszego zespołu, zdecydowanie warto poświęcić kilka chwil, aby odpowiedzieć sobie na te pytania. Szczególnie jeśli nie macie jeszcze zoptymalizowanego pod własne wymagania systemu budowania — można łatwo zdefiniować swój w 30 minut lub mniej.
Gdy już będziecie taki mieć, można przeanalizować, gdzie znajduje się obecnie używany system kompilacji i spojrzeć, co zostało jeszcze do zrobienia. Ustalenie działań, jakie trzeba przeprowadzić, aby dojść do ideału jest bardzo ważne. Pozwala określić proste cele i zadania, wraz z terminami ich wykonania, i rozpocząć pracę nad stworzeniem doskonałego rozwiązania. Nie wydarzy się to oczywiście z dnia na dzień. W rzeczywistości może okazać się, że pracując powoli nad rozbudową systemu kompilacji, jego ukończenie może zająć nawet kilka lat. Jednak, gdy poszczególne elementy zostaną już wdrożone, łatwo zauważyć będzie, że mamy nowe możliwości i wgląd w to, jak działa Wasze oprogramowanie, co sprawi, że stanie się ono bardziej wydajne i niezawodne.
Źródło: https://www.embedded.com/how-to-define-your-ideal-embedded-build-system/
Bez dobrze sprecyzowanej wizji tego, jak powinna wyglądać całość, można odkryć, że grupa programistów jest mniej produktywna, niż mogłaby być. Powoduje to, że pomijane są istotne funkcje i koncepcje, które napędzają szybszy i niezawodny rozwój oprogramowania. Istnieje duża szansa, że sam zespół nawet tego nie zauważy, ponieważ nie wykorzystuje stosownych metryk, ani nie szacuje, jakie są koszty czy czas.
W poniższym artykule zostanie omówiona postać idealnego projektu budowania aplikacji dla systemu wbudowanego. A więc jego wejścia i wyjścia oraz jak można zacząć rozwijać własny, doskonały system kompilacji.
Z czego składa się perfekcyjny system kompilacji?
Kiedy o nim słyszymy, prawdopodobnie od razu na myśl przychodzi instrument taki jak make czy cmake. Narzędzie to zbiera wszystkie dane wejściowe, a następnie przekształca je w binarny plik, który można umieścić na docelowym urządzeniu. Niestety, jest to o wiele więcej niż tylko instrument, który sprawia, że dzieje się jakaś magia.
System budowania powinien zawierać następujące elementy:
* Repozytoria — to miejsce, z którego pobierany jest kod źródłowy do kompilacji (może być jedno lub więcej).
* Kod źródłowy — to wejścia do systemu, składające się z konfiguracji platformy źródłowej, kodu wygenerowanego i pisanego ręcznie.
* Testy — to testy jednostkowe, integracyjne i systemowe, używane do weryfikacji zachowania kodu po kompilacji.
* Konfiguracje kompilacji — określają, jaki będzie wynik kompilacji.
* Narzędzie kompilacyjne — instrument, który zbiera wszystkie dane wejściowe i generuje oczekiwany rezultat w postaci pliku binarnego/heksadecymalnego/itp. ze skompilowanym firmware.
Dla zespołu pracującego nad nowoczesnym oprogramowaniem wbudowanym warto nawet rozważyć włączenie potoku CI/CD do systemu budowania aplikacji. Potok CI/CD to zestaw narzędzi, które nie tylko automatyzują wiele procesów kompilacji, ale mogą także wypuścić najnowsze oprogramowanie do użytku. W poniższym opisie omówione zostaną kluczowe elementy oddzielnie, a potokowi CI/CD poświęcony zostanie osobny artykuł.
W ramach przedmiotowego systemu kompilacji dwie kluczowe dziedziny wymagają określenia pewnej wizji; są to konfiguracje kompilacji oraz kod źródłowy. Przyjrzyjmy się krótko tym zagadnieniom.
Definiowanie idealnego systemu kompilacji
Wiele zespołów programistów, tworzących systemy wbudowane, posiada tylko jedną konfigurację kompilacji, czyli tryb debugowania. Konfiguracje debugowania są świetne, gdy chcemy uruchomić kod w laboratorium lub na stanowisku testowym. Choć budowanie w trybie debugowania jest pewnym standardem, to nie powinno ono być konfiguracją kompilacji, którą używamy najczęściej. Nie powinno to być ujęciem domyślnym!
W artykule zatytułowanym: „Opanowanie systemów budowania oprogramowania wbudowanego: Poznanie 5 istotnych konfiguracji”, wskazano, że istnieje pięć zasadniczych konfiguracji kompilacji, które powinno się wykorzystywać:
1. Analiza — wykonuje analizę metryczną kodu źródłowego.
2. Symulacja — kompiluje kod do wykonania w środowisku gospodarza, a nie na docelowym urządzeniu.
3. Testy — kompiluje i uruchamia testy jednostkowe, integracyjne i regresji.
4. Wersja finalna — kompiluje kod do wersji przeznaczonej do instalacji na sprzęcie klienckim.
5. Debugowanie — kompiluje kod do wykonania na docelowym urządzeniu, ale w warunkach laboratoryjnych.
Czy w swojej praktyce używacie wszystkich tych konfiguracji kompilacji? Czy kiedykolwiek ich wykorzystanie omawiane było z całym zespołem software?
Każdy nowoczesny system kompilacji oprogramowania wbudowanego powinien zawierać w sobie te pięć konfiguracji. Idealny powinien przynajmniej umożliwiać korzystanie z każdej z nich. Jednak, jeśli ich spożytkowanie nie było dotychczasowo omawiane i zdefiniowane, to może okazać się, że mamy w systemie kompilacji tylko konfigurację debugowania i brakuje pozostałych.
Definicja stosu programowego dla perfekcyjnego systemu kompilacji
Może się wydawać, że stos oprogramowania, który jest wykorzystywany, nie ma nic wspólnego z systemem kompilacji aplikacji. Niemniej, wybrane konfiguracje kompilacji mogą dyktować organizację stosowanego oprogramowania. Przecież budowanie kodu w celu symulacji aplikacji nie powinno obejmować np. sterowników niskiego poziomu. Można w ten sposób odkryć, że nawet używane w systemie middleware jest zupełnie inne, zależnie od stosu oprogramowania! Zdefiniowanie idealnych konfiguracji kompilacji może wpłynąć na wykorzystywany stos oprogramowania i odwrotnie.
Nowoczesny stos oprogramowania wbudowanego będzie obejmować kilka warstw niezależnego oprogramowania, które są ze sobą łączone poprzez tzw. HALe (warstwy abstrakcji sprzętu) i interfejsy API. Docelowy stos oprogramowania prawdopodobnie będzie zawierać następujące elementy:
1. Konfiguracja Platformy — oprogramowanie generowane przez narzędzia docelowego systemu, takie jak sterowniki niskiego poziomu, system operacyjny typu RTOS oraz middleware.
2. Kod aplikacji wygenerowany przez model — oprogramowanie generowane przez narzędzie modelujące. Mogą to być na przykład maszyny stanów, algorytmy DSP itp.
3. Kod zarządzania konfiguracją — oprogramowanie generowane i zarządzane przez kod systemowy. Przykładem może być liczba grzałek lub zaworów włączonych w danej aplikacji. To dosłownie kod konfiguracyjny oparty na plikach formatowanych w formacie np. YAML lub innym.
4. Ręcznie pisany kod aplikacji — oprogramowanie stworzone przez zespół programistów bez pomocy innych narzędzi.
5. Konfiguracje testów — różne ustawienia i kod do skutecznego uruchamiania testów jednostkowych, integracyjnych, systemowych i innych, jakie przeprowadzane są w systemie.
Gdy dokładnie zdefiniowano wykorzystywany stos oprogramowania i uwzględnione zostanie to, gdzie kod znajduje się w stosie i jak jest generowany, szybko uda się dostrzec wiele korzyści. Na przykład omawiany stos oprogramowania pozwoli na tworzenie łatwo konfigurowalnego, przenośnego i nieskomplikowanego w kwestii wielokrotnego wykorzystania oprogramowania do użytku w szeregu aplikacji. Choć można uznać to za zbędne, w pewnych firmach można spostrzec tendencję do budowania wewnętrznych platform, które umożliwiają wprowadzanie wielu produktów opartych na częściowo wspólnym kodzie źródłowym. Aby to uzyskać, potrzebny jest elastyczny stos oprogramowania i konfiguracja kompilacji, które go obsługuje.
Przykładowy system kompilacji
Każdy programista i zespół będą wiedzieć, co ich idealny system budowania aplikacji ma za zadanie osiągnąć. Jak dotąd przedstawiono pewne pomysły na to, co powinien zawierać taki perfekcyjny projekt. Gdyby połączyć wszystkie te koncepcje, można otrzymać diagram wyglądający mniej więcej jak na rysunku 1 poniżej.

Rys.1. Idealny system kompilacji, łączący istotne
konfiguracje kompilacji i stosy oprogramowania
dla nowoczesnych systemów wbudowanych.
Powyższy schemat obejmuje wszystkie elementy, o których wspominano powyżej. Po pierwsze, odznaczone są repozytoria prowadzące do chmury i procesu CI/CD u dołu. Następnie, na podstawie zapisanych konfiguracji kompilacji i stosów oprogramowania (widać stos oprogramowania u góry po lewej stronie) definiowane jest środowisko i sposób kompilacji. Finalnie, jak obrazuje to schemat, wykorzystanie testów musi być w systemie kompilacji uwzględnione. Wydaje się, że obecnie programiści wbudowani coraz chętniej korzystają z testów jednostkowych itp. Jednak wciąż jest jeszcze długa droga do przebycia, aby dorównać do standardów branżowych. Ostatecznie, widać jak wszystkie te elementy oprogramowania są łączone w różnych konfiguracjach kompilacji, aby uruchamiać testy, symulować aplikację i wykonywać kod na docelowym urządzeniu. W omawianym schemacie wykluczono konfigurację kompilacji: „analiza”, ponieważ w żaden sposób nie: „przetestowuje” to kodu.
Rysunek 1 przedstawia pomysł na to, jak powinien wyglądać nowoczesny system budowania oprogramowania embedded. Należy zauważyć, że jest on niezależny od narzędzia kompilacyjnego. Można użyć takiego jak make, cmake lub innego preferowanego systemu budowania. Zapewnia to elastyczność i ułatwia ponowne wykorzystanie. System ten obejmuje także testowanie i, co być może równie istotne, założenie, że warto symulować i emulować kod naszej aplikacji.
Podsumowanie
Niezależnie, czy korzystacie dzisiaj z idealnego dla siebie systemu budowania, czy wiecie, jak taki perfekcyjny projekt wygląda i jakie korzyści tworzy dla Waszego zespołu, zdecydowanie warto poświęcić kilka chwil, aby odpowiedzieć sobie na te pytania. Szczególnie jeśli nie macie jeszcze zoptymalizowanego pod własne wymagania systemu budowania — można łatwo zdefiniować swój w 30 minut lub mniej.
Gdy już będziecie taki mieć, można przeanalizować, gdzie znajduje się obecnie używany system kompilacji i spojrzeć, co zostało jeszcze do zrobienia. Ustalenie działań, jakie trzeba przeprowadzić, aby dojść do ideału jest bardzo ważne. Pozwala określić proste cele i zadania, wraz z terminami ich wykonania, i rozpocząć pracę nad stworzeniem doskonałego rozwiązania. Nie wydarzy się to oczywiście z dnia na dzień. W rzeczywistości może okazać się, że pracując powoli nad rozbudową systemu kompilacji, jego ukończenie może zająć nawet kilka lat. Jednak, gdy poszczególne elementy zostaną już wdrożone, łatwo zauważyć będzie, że mamy nowe możliwości i wgląd w to, jak działa Wasze oprogramowanie, co sprawi, że stanie się ono bardziej wydajne i niezawodne.
Źródło: https://www.embedded.com/how-to-define-your-ideal-embedded-build-system/
Cool? Ranking DIY