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
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
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..
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.
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
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
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..)
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.
> 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 ;-)
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.
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.
>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..
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.
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..
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.
>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)
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.