Forum: Compiler & IDEs Crossplatform mit PlatformIO


von Robert L. (lrlr)


Lesenswert?

Vielleicht sehe ich den Wald vor lauter Bäumen nicht

Grundidee: für 2 bis 3 Plattformen (AVR, ESP, ..)
habe ich 95% identischen Code, und 5% Plattform abhängig..

nur wie mach ich das am Besten, Speicher-schonensten, usw.


einfaches Beispiel: Netzwerk..

Ich würde jetzt einen CallBack machen, der aufgerufen, wird, wenn über 
Netzwerk irgendwelche Daten empfangen wurden (der ESP über WIFI, der AVR 
über W5100, ENJxxx, usw. )

was konkret tun?

einen netzwerk.h
netzwerk_W5100.cpp
netzwerk_ESP.cpp
netzwerk_ENC.cpp

oder Unterverzeichnisse:
einen netzwerk.h
W5100\netzwerk.cpp
ESP\netzwerk.cpp
ENC\netzwerk.cpp



was ich hier in beiden Fällen nicht verstehe ist: dass ich "relativ 
kompliziert" mit SRC_Filter jeweils bestimmen muss, weches CPP File 
kompiliert werden soll und welches nicht

ist das "üblich"?

gibt für den konkreten Fall bessere Ideen (library, module??)

natürlich ohne "IFDEF Orgien" ..



danke

von Ben S. (theben)


Lesenswert?

mit der Arduino IDE kenn ich mich jetzt nicht so aus. Die halbwegs 
proffessionelle Welt mach das mit Make Files aber der Sinn sollte der 
selbe sein.

Wenn man "sauber" programmiert geht man in Schichten vor. Dabei sind 
deine Plattform abhängigen Routinen eine dieser Schichten (zb: ein 
Netzwerkprotokoll wäre eine andere Schicht)

Und diese unterschiedlichen Platformarten werden in unterschiedliche 
Ordner geteilt. Im Make File bzw. im SRC_Filter wird dann nur noch ein 
einziges IFDEF gesetzt, welches beschreibt welcher Ordner eingebunden 
werden soll. Ist alles sauber programmiert besitzen alle Platformen das 
selbe Interface. Das bedeutet im Code steht nur noch zB. 
wifiNetzwerkInit(); und den Rest macht der Compiler/Linker welcher auf 
die richtige Datei verweist.

In deiner Frage demnach die zweiteEinteilung:
W5100\netzwerk.cpp
ESP\netzwerk.cpp
ENC\netzwerk.cpp

von Robert L. (lrlr)


Lesenswert?

ok, danke
ich hab mich (aktuell) jetzt aber für ein anderes Konzept entschieden:

einen netzwerk.h
netzwerk_W5100.cpp
netzwerk_ESP.cpp
netzwerk_ENC.cpp

wobei ich bei jedem .cpp File ganz am Anfang ein #infdef habe

also in netzwerk_W5100.cpp z.b.
#infdef W5100
..

das hat meiner Meinung nach ein paar Vorteile

wundere mich aber weiterhin dass ich zu dem Thema noch kein "best 
practice" gefunden habe..

von W.S. (Gast)


Lesenswert?

Robert L. schrieb:
> was konkret tun?

Ein Verzeichnis für jede Plattform und Projekt, wo alle benötigten 
Quellen hineinkommen. Sinn der Übung ist, daß möglichst wenig oder gar 
keine Referenzen auf andere Verzeichnisse usw. vorkommen. Also soll auch 
eine Kopie der zuständigen MyControllerxxx.h in dieses Verzeichnis 
hinein. Das einzige, was da nicht hinein muß, ist alles was in spitze 
Klammern kommt ( #include <....> )

Heutzutage sollten Festplatten groß genug dafür sein und der Vorteil 
ist, daß man das ganze Projekt in einem einzigen Verzeichnis hat, so daß 
man es gut archivieren und auf andere Rechner transportieren kann, ohne 
Verzeichnis-Strukturen berücksichtigen zu müssen. Obendrein entfallen 
dann auch alle #ifdef's im Projekt, weil es ja jeweils nur für genau 1 
Plattform gilt.

Wenn man an den hardwareunabhängigen Moduln ne Änderung vornimmt, dann 
muß man die natürlich in alle beteiligten Projekte bzw. Projektvarianten 
kopieren. Wem das zu mühselig ist, so daß er sich lieber mit #ifdef's 
herumschlägt, den bedauere ich nicht.

W.S.

von Robert L. (lrlr)


Lesenswert?

3-4 Plattformen (esp8266, esp32, stm32, AVR)
3-4 Kommmunikationsmöglichkeiten (W5100, W5200, ENCJ.., ESP-WIFI, u.u. 
rs485)
3-4 "Debug"/"Logging" möglichkeiten (Seriell, Syslog, NULL, UDP)
3-4 DMX-"Libraries"

und da mache ich jetzt für jede Variante ein Verzeichnis??
4x4x4x4? also 100
und habe in jedem Verzeichnis 95% identischen Code


(ja 100: du kommst mir so vor wie der Typ dessen Namen ich vergessen 
habe, der einen 8-bit PC entwickelt hat und uns erklärten wollte, warum 
wir ab jetzt in HEX rechnen sollten)



welches "Problem" mit Verzeichnisstrukturen beim "Archiviere und 
kopieren" von Daten hast du ? (GIT und SVN kommen mit Verzeichnissen 
ansich ganz gut zurecht..)



>daß möglichst wenig oder gar
>keine Referenzen auf andere Verzeichnisse usw. vorkommen.

ich hab genau KEINE "Referenz" auf andere Verzeichnisse..


PlatformIO macht meines wissens aber sowas ähnliches wie du es 
vorschlägst, es erstellt vor/für jeden "BUILD" (temporär?) einen extra 
Ordner, indem alle relevanten sourcen (z.b. die "libraries") in ein 
Verzeichnis zusammen kopiert werden und vor dort aus compiliert

>Wenn man an den hardwareunabhängigen Moduln ne Änderung vornimmt, dann
>muß man die natürlich in alle beteiligten Projekte bzw. Projektvarianten
>kopieren.

bin ich der Depp vom Dienst? Monotone, wiederkehrende Tätigkeiten zu 
automatisieren, wäre jetzt GENAU der Job eines Programmierers. Ich weiß 
ja nicht was dein Job ist?

: Bearbeitet durch User
von soso (Gast)


Lesenswert?

Wenigstens hast Du den passenden Titel gefunden für Dein Thema;-)
Schau Dir mal CMAKE an. Da kannst dann mit Make alles bauen, was Du 
willst.
Läuft auch alles unter Windoof, falls Linux grad nicht so angesagt ist 
bei Dir im Unternhemen.

Da solltest Du einen geringen Einarbeitungsaufwand nicht scheuen, es 
lohnt sich. Dafür musst Du nix mit Makefiles rumeiern, das erledigt dann 
CMAKE für Dich.

In Abhängigkeit von der Konfiguration verwendet dann make eben die 
passende Toolchain.

Cu

von soso (Gast)


Lesenswert?

Ähhh und lass diesen Schlunz weg - Plattformio;-)

von Robert L. (lrlr)


Lesenswert?

kennst du zufällig ein OpenSource Projekt, dass das so macht?


gehts jetzt darum dass ich MAKE verwende, weil MAKE so super ist,
oder weil das Konzept von MAKE so super ist, und ich jetzt jetzt auch 
etwas anderes verwenden könnte was "ähnlich" wie MAKE funktioniert

an meiner grundlegenden Frage (wie organisiere ich den Source, also die 
h und cpp Files, ändert das ja nichts)


PlatformIO verwendet https://www.scons.org/ als alternative zu MAKE


(auch wenn es mein job ist zu programmieren: nein, ich mach das 
"natürlich" nicht beruflich, sondern als hobby..)

von soso (Gast)


Lesenswert?

CMAKE ist ein Autokonfigurations-Tool(Erstellt automatisiert die 
Makefile Struktur). Make ist ein Build-Tool.

Die Flexibilität ist unendlich. Die Bedienung 'leicht' zu erlernen. Bei 
PlattformIO musst Du ja auhc halbwegs wissen, was Du da tust.

The Way 2 go.

von Robert L. (lrlr)


Lesenswert?

> Bei PlattformIO musst Du ja auhc halbwegs wissen, was Du da tust.

Nein, da kommen immer so kleine blaue Fensterchen, die einem sagen was 
man zu tun hat ;-)

von Jack (Gast)


Lesenswert?

Robert L. schrieb:
> was ich hier in beiden Fällen nicht verstehe ist: dass ich "relativ
> kompliziert" mit SRC_Filter jeweils bestimmen muss, weches CPP File
> kompiliert werden soll und welches nicht

Platformio ist ein Tool für Leute die das Problem nicht verstanden 
haben, aber unbedingt ein Framework mit einem Haufen Tools zur Lösung 
haben wollen.

X-Plattform Code wird seit Jahrzehnten erfolgreich ohne Platformio 
geschrieben, und das geht auch weiterhin:

Kern-Applikation (Neudeutsch "Business Logic") in plattformunabhängigem 
C schreiben. Dabei besonders die C-Features zur Plattformunabhängigkeit 
nutzen: Standard-Library, statt Sonderfunktionen eine Zielplatform. 
stdint.h Datentypen wie int32_t, keine Vanitytypen wie DWORD oder 
qint32. Wenn man hat Posix Funktionen. Keine Grenzfälle ausnutzen (Z.B. 
wenn "alle" Implementierungen einer Standardfunktion ein NULL-Argument 
akzeptieren, das aber nicht im Standard garantiert wird, dann nicht 
drauf bauen.). Im Code der Kern-Applikation keine Feature-Tests (#ifdef) 
auf eine Plattform.

Ein plattformunabhängiger Hilfslayer - wenn man ihn braucht. Hier 
implementiert man plattformunabhängig gängige Algorithmen und 
Datenstrukturen. Was man so braucht und auch sonst als HIlfsbibliotheken 
verwenden würde.

Wenn nötig ein dünner plattformabhängiger Kompatibilitätslayer. In dem 
biegt man nur einfache Dinge gerade. Auf einer Zielplattform fehlt eine 
Funktion aus der Standard-Bibliothek? Für die Plattform eine einfache 
Version der Funktion implementieren. Eine Zielplattform hat ähnliche 
Funktionen? Wrapper um die Funktionen der Zielplattform, so dass sie wie 
Standardfunktionen aussehen. Eine Zielplattform hat ein gängiges Makro 
oder enum nicht? Im Kompatibilitätslayer implementieren. Der 
Kompatibilitätslayer wird zu einer Library compiliert. Für den 
Kompatibilitätslayer gibt es maximal ein Headerfile, das, wenn benötigt, 
von Code der Kern-Applikation inkludiert wird.

Ziel ist es viele Standard-APIs(native oder nachgebaut) wie möglich 
bereit zu stellen.

Für komplizierte Dinge Abstraktionslayer. Es gibt komplett 
unterschiedliche Mechanismen und Bibliotheken die das Gleiche auf 
unterschiedlichen Plattformen zu machen? Einen an der Anwendung 
orientierten Abstraktionslayer (Header-File mit der Schnittstelle) 
definieren, für jede Plattform separat implementieren.

Feature-Tests, wenn immer es geht, zur Compiletime (#ifdef ) machen. 
Wenn es geht immer vorhandene Macros testen, zum Beispiel 
Compiler-Makros, die die Plattform identifizieren. Keinen eigenen 
Macro-Zoo zur Plattform-Identifizierung abufbauen.

Nur in äußerster Not Runtime-Tests implementieren (if(has_serial()) { 
init_serial(); }

Simple Makefiles. Selektion wofür compiliert werden soll erfolgt durch 
ein einzelnes, einfaches Commandline-Argument. Danach im Makefile 
plattform-spezifische Werte (Compilerpfade, -name, -flags, Verzeichnis 
für Binaries, ... ) setzen. Wenn es geht möglichst keine 
plattformspezifischen Quelltext-Verzeichnisse setzen. Einfach alles 
durch den Compiler jagen und durch die sowieso vorhandenen Feature-Tests 
(#ifdef) im Code aussortieren lassen.

Wegen letzterem ist es ziemlich egal, ob man plattformspezifischen Code 
(Kompatibilitätslayer, Abstraktionslayer) als

> einen netzwerk.h
> netzwerk_W5100.cpp
> netzwerk_ESP.cpp
> netzwerk_ENC.cpp

oder

> oder Unterverzeichnisse:
> einen netzwerk.h
> W5100\netzwerk.cpp
> ESP\netzwerk.cpp
> ENC\netzwerk.cpp

strukturiert. Es sollte nur einheitlich sein. Ich bevorzuge die zweite 
Variante.

von W.S. (Gast)


Lesenswert?

Robert L. schrieb:
> und da mache ich jetzt für jede Variante ein Verzeichnis??
> 4x4x4x4? also 100

lerne zunächst Rechnen.


Robert L. schrieb:
> Grundidee: für 2 bis 3 Plattformen (AVR, ESP, ..)
> habe ich 95% identischen Code, und 5% Plattform abhängig..

Du schreibst konfusen Unsinn. Also was denn nun? 16 verschiedene 
Projekte und die auf 16 verschiedenen Plattformen?

Ich glaube dir ab jetzt kein Wort mehr. Und wenn du schon schlauer bist 
als diejenigen, die dir helfen wollen, dann frag einfach NICHT.

W.S.

von Robert L. (lrlr)


Lesenswert?

>lerne zunächst Rechnen.


lol
(und ich hab es sogar erklärt, extra für dich, weil ich gedacht hab, 
vielleicht kapiert er es sonst nicht..)

(auf den Semmel: für jede Paltform ein Verzeichnis mit allen Files, 
werde ich nicht weiter eingehen)

@Jack (Gast)

danke, ich denke dass ich den großteil schon so mache,
wüsste aber grad nicht, welcher der aufgeführten Punkte sich jetzt mit 
PlatfomIO über Kreuz kommen sollte ?

also warum ich nicht all deine Ratschläge befolge und trotzdem 
PlatformIO verwende..

von Zweig (Gast)


Lesenswert?

W.S. schrieb:
> Wenn man an den hardwareunabhängigen Moduln ne Änderung vornimmt, dann
> muss man die natürlich in alle beteiligten Projekte bzw. Projektvarianten
> kopieren.

Alles was mit kopieren zu tun hat ist allergrößter Müll.

Auch hier gelten die Clean Code Regeln!

CMAKE ist der richtige Weg!

Auch gilt: Konvention vor Konfiguration

Das bedeutet in deinem Fall, dass es sinnvoll ist, die Plattform 
abhängigen Dateien in unterschiedlich Ordner zu schieben aber dort immer 
gleich zu benennen.

Nur dadurch kannst du es erreichen das wenn z.B. eine neue HW-Plattform 
hinzukommt man die bestehen Quelldateien nicht ändern muss.

von Ben S. (theben)


Lesenswert?

@Zweig

Bin genau deiner Meinung

von Robert L. (lrlr)


Lesenswert?

Der Code ist inzwischen online:

https://github.com/LechnerRobert/UDPtoDMX

es folgt folgenden "Prinzipien":

a) mir das Leben nicht unnötig schwer machen
b) am AVR ist Prio 1: RAM sparen
c) wegen a) und  b) gibt es keine vererbung und alle objekte sind 
singletons und auch sonst noch ein paar unschönheiten

Ich finde es jetzt nicht so schlecht, alle 6 "Platformen" lassen sich 
mit einem Knopfdruck erzeugen (avr, esp8266, x86)..

dazu gibt es noch unzählige "optionen" die man ein-/ausschalten kann




p.s. ich hasse C, deshalb schreibe ich Code oft nicht "C" like, sondern 
eher richtung lesbar..

von W.S. (Gast)


Lesenswert?

Zweig schrieb:
> Alles was mit kopieren zu tun hat ist allergrößter Müll.

Nein, ist es nicht. Es sorgt hingegen dafür, daß Projekte in sich 
geschlossen bleiben und nicht beeinflußt werden können von Änderungen an 
ganz anderer Stelle. Sowas ist eine Sicherheitsmaßnahme gegen 
versehentliches Zerdeppern von fertigen Projekten, auf die ich niemals 
verzichten werde.

> Auch gilt: Konvention vor Konfiguration
>
> Das bedeutet in deinem Fall, dass es sinnvoll ist, die Plattform
> abhängigen Dateien in unterschiedlich Ordner zu schieben aber dort immer
> gleich zu benennen.

Sobald du mit einer Verzeichnis-Struktur anfängst, bist du bereits auf 
der Verliererseite, denn damit handelst du dir eine Abhängigkeit von 
Strukturen ein, die mit dem jeweiligen Projekt rein garnichts zu tun 
haben und die selbst beim simplen Portieren von einem PC zum anderen 
bereits Probleme machen.

Nein, da wir hier bei unseren Mikrocontrollern keine Riesen-Firmware 
bauen, sondern sich das Ganze final um höchstens 1 MB an fertigem 
Maschinencode handelt, ist es das Allerbeste, jedes Projekt flach zu 
halten, also keinerlei Referenzen auf Dateien außerhalb des 
Projektverzeichnisses zuzulassen.

Das bedeutet natürlich auch, hardwareunabhängige Programmteile ebenfalls 
in Kopie des eigenen Portfolios im Projektverzeichnis zu haben - und 
falls sich da mal eine Änderung im Portfolio ergeben sollte, dann muß 
diese eben in alle Projekte übernommen werden, wo man die Änderung 
tatsächlich haben will. Und nicht automatisch in alle Projekte hinein 
knallen.

Keine professionelle Software versaut sich ihre fertigen Projekte durch 
leichtfertige "Konfiguration" wie du das genannt hast - nun ja, mit 
einer historischen Ausnahme: Xilinx hatte sich bei seiner ISE-8.2 so 
einen Batzen geleistet, weswegen dort Impact wegen versehentlich 
versauter Steuerfiles bei einigen Chips nicht mehr funktionierte.

Aber man kann ja aus solchen Fehlern lernen und genau DAS vermeiden, was 
du vorgeschlagen hast.

W.S.

von Robert L. (lrlr)


Lesenswert?

>Und nicht automatisch in alle Projekte hinein
>knallen.

man könnte sich ja auf HALB-automatisch einigen

nachdem man sowieso ein Versionverwaltungstool verwenden muss (svn oder 
git)

kann man gemeinsam genutze sourcen auch Zeile für Zeile kontrollieren, 
bevor man sie übernimmt in (in svn mit "vendor-merge", in git weiß ich 
nicht wie das heißt das kann das vermutlich noch besser)

von temp (Gast)


Lesenswert?

Wenn man sich selbst ein Framework für seine Aufgaben baut, dann wächst 
das auch mit der Zeit. Eine simple Klasse Gpio z.B. Irgendwann braucht 
man mal was, was bisher noch nicht aufgetreten ist oder ändert was. Für 
mich wäre es ein Grauen, wenn sich Änderungen auf alle Projekte 
auswirken würden wo das verwendet wird. Fertige Projekte sind fertige 
Projekte. Punkt. Manchmal ist es sogar sinnvoll den ganzen Compiler und 
die Libs mit im Projekt zu haben. Nichts ist schlimmer als wenn ein 
Projekt in 10 Jahren nicht mehr geht obwohl der gleiche Code übersetzt 
wird.

von Robert L. (lrlr)


Lesenswert?

das funktioniert (wenn überhaupt) nur in einer kleine Nische.. (99% der 
Softwareentwicker würd so genau nach 1 Woche wieder gefeuert werden..)

irgenwann fällt dir das mächtig auf den Kopf...

(aber so eine schmarren traut man sich soweiso nur als "Gast" posten, 
...)

das ist aber alles ziemlich OT hier..
es ging ja um meine 5-6 "Plattformen" die alle 90% den selben code 
teilen..
schon hier ist es vollkommen unrealistisch 5-6 ordner mit jeweils kopien 
vom code zu haben..

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.