WinCE Patches
« | 08 May 2022 | »Mit jeder Plattform gibt es Probleme in Sachen Kompatibilität, aber mit keiner gibt es so viel wie mit Windows CE.
Und vermutlich beschäftigte ich mich genau deshalb immer wieder mit dieser eigentlich schon ausgestorbenen Umgebung, denn:
Ich liebe die Herausforderung.
Ich selbst habe mit WinCE eigentlich gar keine Probleme, doch leider haben eine Vielzahl anderer Bibliotheken ihre Probleme mit dem limitierten Funktionsset.
Und das liegt in erster Linie daran, dass der C-Standard nicht vollständig abgebildet ist. Das manifestiert sich folgendermaßen:
- Ein Header fehlt (z.B.:
stdbool.h
oderio.h
) - Funktionen sind im Header, aber nicht in der C-Runtime implementiert
(z.B.:
time()
oderclock()
) - Funktionen fehlen im Header (z.B.:
strcoll()
)
Ein fehlender Header lässt sich ganz leicht ersetzen. Man fügt ihn dem eigenen Projekt hinzu inklusive einer Implementierung, die z.B.: direkt auf WinAPI Aufrufe umleitet.
Wenn nur die Implementierung einer C-Funktion in der C-Runtime fehlt, verfährt man ähnlich: Man fügt einfach eine neue Implementierung im eigenen Projekt an und schon kann das “nicht-aufgelöste-Symbol” gefunden werden.
Am schlechtesten ist die dritte Variante, nämlich das Fehlen einer Funktion im Header und der CRT.
Viele Header in WinCE sind nur Umleitungen auf stdlib.h
in der vieles
notwendige enthalten ist. Doch leider fehlen die meisten IO-Funktionen
wie freopen()
,
remove()
oder
rename()
.
Nutzt man nun eine Bibliothek, die selbst nur stdio.h
einbindet und sich
eine Funktion dahinter erwartet, treten seltsame Seiteneffekte auf.
Denn C nutzt den Funktionsaufruf als Deklaration mit eine undefinierten
Prototyp wie:
int c_function(...);
Fügt man nun seine eigene Implementierung mit der richtigen Deklaration
parallel hinzu, gilt die One-Definition-Rule
als verletzt, weil das gleiche Symbol zwei mal unterschiedlich definiert
wurde.
z.B.:
Platform Support Layer
Im Platform-Layer des GATE Projektes nutzte ich bisher ein wince
Unterverzeichnis, in dem einige Header mit Inline Funktionen enthalten waren.
Diese Header wurden dann von CMake
aus adressiert, um unter Windows CE meine manipulierten Header zu laden und
nicht jene C-Standard-Bibliothek.
Doch leider nahm die Menge der notwendigen Funktionen zu und daher brauchte ich einen neuen Ansatz.
stdcpatches Bibliothek
Die Hilfsbibliothek stdcpatches
ist eine statische Bibliothek im libs
Ordner des GATE Projektes und soll eine Vielzahl von std-c
Header und
Implementierungen nachbilden.
Für jede Plattform und jeden Typ von C-Header gibt es Unterverzeichnisse,
die alle notwendigen Dateien beinhalten.
Am Ende entscheidet dann CMake
, welche Ordner als Include-Directories
eingebunden oder übersprungen werden sollen.
Auf diese Weise können Patches für Plattformen wie Windows CE oder Compiler wie MSVC eingebaut werden.
Fordert eine Bibliothek wie libpng
z.B.: errno.h
an, existiert dafür
in stdcpatches
ein eigener Header errno.h
, der fehlende Makros und
Definitionen nachliefert. Parallel dazu veröffentlicht eine eigene
wince_errno.c
Einheit die Implementierung innerhalb der statischen
Bibliothek.
Für den MSVC allgemein existieren Header wie sys/stat.h
oder stdint.h
,
die in älteren Versionen nicht enthalten waren.
Auch hier bindet CMake
die Dateien nur bei älteren Compilern ein und
verzichtet darauf, wenn sie in neuen Versionen schon enthalten sind.
Fazit
Die Umstellung von “kleinen Patches” in gate/platform/wince
auf eine eigene
Bibliothek stdcpatches
war eine größere und auch recht mühsam.
Dennoch glaube ich, dass es mir langfristig mehr bringt, solche
Codeverrenkungen kontrolliert an genau einer Stelle durchzuführen.
Schließlich hat die bisherige Implementierung den Abhängigkeitsbaum korrumpiert, denn externe Bibliotheken sollten vor dem GATE Framework Code kompiliert werden. Doch nur für WinCE wurden einige wenige Include-Directories schon vorher aus dem GATE-Projekt geladen.
Jetzt sind externe Bibliotheken in Sonderfällen von der Bibliothek
stdcpatches
abhängig, und am Ende wird alles zusammen vom GATE Projekt
konsumiert.
Framework]] EXT[[External
Libraries]] PATCH[[stdcpatches]] STDC[[STD-C
Libraries]] OS[[OS native API]] GATE --include--> EXT EXT --include--> PATCH EXT --include --> STDC PATCH --include--> STDC PATCH --include--> OS
Ein Vorteil ergibt sich daraus außerdem: stdcpatches
kann jetzt auch ohne
das GATE Projekt mit anderen Libs für Fremdprojekte benutzt werden.