Suchen

Android anpassen – die Untiefen der Android-Anpassungsarchitektur

Seite: 2/2

Firmen zum Thema

Android-Anpassungen auf der Buildsystem-Ebene

Im Gegensatz zu anderen Make-basierten Buildsystemen werden in Android Makefiles nicht rekursiv aufgerufen. Globale Makefiles tragen zunächst alle Android.mk Dateien innerhalb der Code-Basis zusammen, inkludieren deren Inhalt und führen dann die Make-Anweisungen aus. Wieso wird das so gemacht? Es ermöglicht eine einfache Analyse und Optimierung des Buildprozesses. Doch dazu später mehr.

In den Modul-Makefiles werden dann unter anderem die Dateien ausgewählt, aus denen das Modul gebaut wird. Bild 6 zeigt hierfür ein typisches Beispiel. Es handelt sich dabei um eine Art von Polymorphismus auf Dateiebene. Dateien, die optional oder alternativ zum Bauen verwendet werden, lassen sich dadurch einfach ermitteln. Man verzichtet wohl gezielt auf die Verwendung des Präprozessors (#ifdefs) zugunsten von Module-Replacement, wodurch sich die Verständlichkeit der Quellcode Dateien erhöht.

Bildergalerie
Bildergalerie mit 8 Bildern

Um die Anpassungsarchitektur besser zu verstehen, haben wir die Auswahl-Konstrukte und die verwendeten Variablen näher analysiert. Hierfür haben wir das Kati-Werkzeug etwas modifiziert und anschließend bei der Analyse eingesetzt. Bei Kati handelt es sich um ein Open-Source-Werkzeug von Google, das Makefiles parst und diese in Ninja-Dateien umwandelt. Mit den Ninja-Dateien kann Android dann optimiert gebaut werden, wodurch der Buildprozess deutlich beschleunigt wird - ein durchaus interessanter Ansatz. Wir haben dabei 682 Buildvariablen gefunden, die sich in 4 Kategorien einteilen lassen: Produktkonfiguration, Boardkonfiguration, Build-OS und Build-Details. Bild 7 gibt einen Überblick, ob diese Variablen im Buildsystem oder im Quellcode zum Einsatz kommen.

Anpassungen auf der Code-Ebene

Da Androids Konfigurationsvariablen in Makefiles definiert werden und nicht in Header-Dateien, stehen sie dem Präprozessor bei der Verarbeitung der Quellcode-Dateien nicht direkt zur Verfügung, sondern müssen explizit übergeben werden. Ein entsprechendes Beispiel ist in Bild 8 dargestellt: In Abhängigkeit von übergeordneten Konfigurationsvariablen werden zunächst untergeordnete Konfigurationsvariablen gesetzt. Anschließend werden im Buildsystem in Abhängigkeit von den untergeordneten Konfigurationsvariablen Compilerflags gesetzt und darüber die Werte der Variablen an den Präprozessor / Compiler übergeben. Zunächst erscheint dies vielleicht etwas umständlich.

Bei näherer Betrachtung zeigt sich allerdings eine klare Konfigurationsarchitektur, welche die Anwendungskonfiguration klar von der technischen Konfiguration der Module separiert. Da die entsprechenden Zusammenhänge nur über die Makefiles zum Ausdruck kommen, lässt sich die Anpassungsarchitektur recht gut werkzeuggestützt analysieren, optimieren und weiterentwickeln. Hier kann man für große Projekte sicherlich etwas von Android lernen. Bei Bedarf ist das Kati-Werkzeug [5] hier sicherlich ein guter Startpunkt. Wir haben es etwas erweitert, um so an weitere Informationen zu gelangen, die bei der Analyse des Buildsystems im Werkzeug vorliegen.

Zusammenfassung

Den Android-Entwicklern gelingt es ein breites Maß an Anpassungen basierend auf einer heterogenen Codebasis, die sich nebenläufig weiterentwickelt, zu unterstützen. Damit liegt die Vermutung nahe, dass die Anpassungs- und Konfigurationsarchitektur von Android sicherlich ein sehr guter Ideengeber für Praktiker ist, die im Entwicklungsalltag mit der Variantenbeherrschung kämpfen. Da es leider nicht ganz einfach ist, sich einen entsprechenden Überblick zu verschaffen, haben wir eine entsprechende Analyse durchgeführt.

Die Analyse führte bei uns zu folgenden Erkenntnissen: Die Anpassungsunterstützung in Android kommt deutlich einfacher daher als wir das erwartet hatten. Statt ausgewieften Konfigurationsmodellen, -techniken und –werkzeugen sowie klaren Codierstandards, kommen eher die üblichen Verdächtigen zum Einsatz. Es fällt auf, dass die Drei-Ebenen-Konfigurations- und Anpassungsarchitektur sehr klar ist und sich im Wesentlichen auf Makefiles stützt. Die Konfiguration aus Anwendersicht ist strikt von der technischen Konfiguration der Module getrennt. Ein Muster, was uns auch schon an anderen Stellen begegnet ist. Die Abhängigkeiten zwischen Anwendungskonfiguration, Buildsystem und Quellcode steckt in den Makefiles und kann unter Verwendung des Kati-Werkzeuges extrahiert werden.

In den nächsten Releases von Android soll Make durch Kati/Ninja ersetzt werden. Am diesem Beispiel zeigt sich auch, wie die Transition zwischen verschiedenen Buildsystemen auch in komplexen Systemen gelingen kann.

Dr. Martin Becker, Abteilungsleiter des Bereichs Embedded Software Engineering am Fraunhofer Institut für Experimentelles Software Engineering (IESE).
Dr. Martin Becker, Abteilungsleiter des Bereichs Embedded Software Engineering am Fraunhofer Institut für Experimentelles Software Engineering (IESE).
(Bild: Fraunhofer IESE)

Die vorgestellten Analysen wurden von Nicolas Fußbender im Rahmen eines Studentenprojektes der TU Kaiserslautern am Fraunhofer IESE durchgeführt. Vasil Tenev und Dr. Bo Zhang haben die Durchführung der Arbeit maßgeblich unterstützt.

Dieser Beitrag stammt aus dem Tagungsband des ESE-Kongress 2017

Der Autor

*Dr. Martin Becker ist Informatiker und leitet die Abteilung Embedded Systems Engineering am Fraunhofer IESE. In einer Vielzahl von Forschungs- und Industrieprojekten hat er in den letzten 17 Jahren vielfältige Erfahrungen mit Varianten-Management in verschiedenen Anwendungsgebieten gesammelt, sowie neue Methoden, Techniken und Werkzeuge auf diesem Gebiet entwickelt.

(ID:45661669)