Ergebnis 1 bis 5 von 5

DLL aus Source Code kompilieren

  1. #1 Zitieren
    banned
    Registriert seit
    Jan 2022
    Beiträge
    24
    Hallo alle zusammen,

    ich versuche schon ganz verzweifelt das hinzukriegen. Weder mit CMake noch mit Microsoft Visual Studio bekomme ich es hin.

    Ich brauche eine aktuelle sdl.dll (für Win32) vom SDL 1.2 Source Code:
    https://github.com/libsdl-org/SDL-1.2

    Die letzten binaries sind nicht mehr auf dem neuesten Stand. Nur noch der Source Code wurde weiterentwickelt mit Patches und Fixes.
    Daraus möchte ich nun selber eine aktuelle .dll bauen. Kann mir jemand helfen? Kennt sich hier wer damit aus?

    Interessant für mich wäre auch der SDL Compat Layer:
    https://github.com/libsdl-org/sdl12-compat

    Wäre euch unendlich dankbar.

    LG
    Usselwetter
    Usselwetter ist offline

  2. #2 Zitieren
    Mythos
    Registriert seit
    Jul 2011
    Beiträge
    8.286
    Hi, ich habe mal alles von Dir Angefragte durchprobiert (inkl. SDL Compat Layer und CMake, wo nötig), es hat geklappt.

    Dazu bin ich aber nur in etwa schnellstmöglich vorgegangen, da ich erst mal antworten und nicht "endlos" herumkonfigurieren wollte (normalerweise mache ich das gründlich, aber dann könnte das bei der Komplexität gut und gerne einen halben bis ganzen Tag dauern (nur für das Wichtigste...)), also wirklich nur ganz faul...
    • mit Visual Studio 2022 (ein älteres, idealerweise ab 2010 aufwärts, sollte es auch tun, wobei VIEL neuere, ab einer bestimmten Toolset-Version, nur noch CPUs mit SSE2-Befehlssatzerweiterungen unterstützen, was nicht für alle "Vintage"-Geräte geeignet ist, z.B. nicht für Athlon-XP),
    • ohne Git-Client (obwohl in Visual Studio 2022 integriert),
    • ohne sorgfältiges Projekt-Setup (kann man nachholen, wenn man sich ernsthaft damit befassen will),
    • Projektkonfigurationen aus Bequemlichkeitsgründen für das Windows-10-SDK mit aktuellem Compiler ausgerichtet,
    • aus Kompatibilitätsgründen zu alter Software bzw. für Performance jeweils alles auf 32-Bit-Release umkonfiguriert,
    • das dynamische Linken beibehalten, muss also die C-Runtime auf dem Target vorhanden sein,
    • irgendeine Default-Header-Datei, die anscheinend als Vorlage und zum Anpassen gedacht ist, kopiert und passend (ohne "default") umbenannt (sonst hagelt es Fehler, da die Datei unter dem Namen nicht existiert, habe mir nicht die Mühe gemacht, mich mit den Optionen dort zu befassen),
    • Namen der zuvor erstellten Libs (*.lib), von denen das aktuelle Projekt abhängig ist und die Pfade zu ihren Verzeichnissen in Visual-Studio-Projekteigenschaften eingetragen (jeweils unter "Linker"),
    • die alten Abhängigkeiten zu den Libs, welche im GUI angezeigt werden (weil irgendwer meinte, das bequeme und unzuverlässige GUI-Feature gegenüber der zuverlässigeren manuellen Konfiguration bevorzugen zu müssen) wegen Inkompatibilität des Konfigurationsformates (man sieht nicht, was in der Projektdatei steht und hat per GUI keinen Zugriff auf alle Details, z.B. falsche Pfade) entfernt (aber mit einem geeigneten Texteditor mal nachgeguckt, woran es hakt und was die Originalpfade waren, um das bei Interesse so nachbilden/wiederherstellen zu können, wie es früher beim Originalprojekt gewesen ist),
    • DLLs jeweils manuell (lässt man normalerweise automatisch machen) dorthin kopiert, wo sie gebraucht werden,
    • CMake-Liste für ein CMake-Projekt unter Visual Studio benutzt (doch, ein modernes VS unterstützt das inzwischen (sonst direkt CMake nehmen)!), wo keine Visual Studio-Solution (*.sln) angeboten wird,
    • Umgebungsvariablen, die die Skripte des CMake-Projektes unter VS2022 brauchen, um für das SDL Compat Layer einzubinden, was es von SDL2 braucht, für den aktuellen Benutzer gesetzt (siehe dazu die aussagekräftigen Fehlermeldungen), danach den Cache von CMake leeren, dann neu konfigurieren lassen -> klappt nun mit den Variablen -> dann unter VS2022 für CMake die x64-Debug-Konfiguration kopiert, in x86-Release umbenannt und entsprechend nachkonfiguriert, damit auch x86-Releases herauskommen -> nochmal neu konfigurieren lassen -> Buildvorgang "Build all" angestoßen -> klappt alles einwandfrei,
    • nun auch dies Tests für das SDL Compat Layer ausprobiert -> Erfolg (natürlich nur mit der zuvor unter dem "SDL"(2.0)-Projekt erstellten DLL für SDL2.0, denn auf die wird ja mit dem Wrapper umgeleitet).

    Die offiziellen Tests, die ich ausprobiert habe (für alle fehlte mir die Zeit, aber waren wohl mit die komplexesten), liefen bei allen drei involvierten Projekten problemlos durch. Die Importtabellen einiger ausführbarer Dateien (DLL, Exe) habe ich auch kurz überprüft.

    Vielleicht kannst Du Dich an meiner Auflistung entlanghangeln. Fehler bitte melden, wo Du nicht weiterkommst, sollten sich beheben lassen. Bisher wissen wir nämlich noch nicht, woran es bei Dir überhaupt scheitert.

    *.sln -Projekt("Solution")-Dateien bitte gegenüber *.dsw-Dateien bevorzugen, denn *.dsw ist ein reichlich (ca. 20 Jahre, z.B. von VS6 aus dem Jahr 1998 genutzt) altes Format, welches sich nicht so gut wie die späteren *.sln-Formate zum Konvertieren zum jeweils aktuellen *.sln-Format eignet, da es nicht für alles direkte Entsprechungen gibt. Und grundsätzlich, wo gegeben, bei solchen Projekten CMake gegenüber VS-Makefiles bevorzugen, weil die CMake-Files nämlich neuer sind. Trotzdem würde ich mal die alten VS-Makefiles und sogar die *.dsw-Files gegenchecken, nämlich wegen der gesetzten Kommandozeilenparameter für Compiler und Linker, um die zu überprüfen. Denn niemand garantiert Dir, dass die moderneren Pendants korrekt konvertiert wurden. "Korrekt" heißt, dass neben der automatischen Konvertierung (bei der etwas schiefgehen kann) auch eine manuelle Nachkontrolle erfolgt ist und dass derjenige, der es gemacht hat, wusste, wie sich die Flags unter verschiedenen Versionen von Visual Studio auswirken. Die dazu nötige Erfahrung, verbunden mit dem Willen zu Recherchen, haben nämlich nicht so viel Entwickler. Aber unrter anderem das sind Optimierungen, die Du später durchführen kannst, nachdem du weißt, dass wenigstens die Tests funktionieren. Normalerweise pflegt man jeweils eine Debug- und eine Release-Konfiguration je CPU-Architektur, wobei es ratsam ist, sogar die Tests mit beiden Konfigurationen durchzuführen, auch wo nur Debug vorgesehen ist.

    Zu meinem Stil gehört es, den kleinsten sinnvollen gemeinsamen Nenner bei der Windows-Version herauszufinden und dafür alles komplett nachzukonfigurieren und auch eine Version mit statischem Linken bereitzustellen, für den Fall, dass die benötigte C-Runtime nicht verfügbar ist (wo dieses passieren kann und wo statisches Linken keine Nachteile hat). Allgemein sehe ich zu, dass ich bei den Release-Versionen jeglichen Ballast aus den ausführbaren Dateien heraushalte und evtl. ungenutzte Optimierungen aktiviere, wo es von Vorteil ist. Aber um das zu wissen, muss man messen. Damit wären wir bei einer großen Variantenmatrix (Windows-Versionen + CPU-Arch + CPU-Features(SSE2) + statisches oder dynamisches Linken, Optimierung Size vs Speed + Intrinsics + Optimierung beim Linken (MS-Sprech: "LTCG", GNU-Sprech: "LTO") ... (alles zusammen fürchterlich zeitfressend)) und Messungen, womit man gut und gerne mal eine Woche oder länger verplempern kann, ohne richtig am Code gearbeitet zu haben. Um nicht wieder in Versuchung zu geraten, alle Register zu ziehen und in dem Prozess hängen zu bleiben (ohne die Zeit dafür zu haben), habe ich es eben erst einmal schlampig probiert. Diese Build-Konfigurationen sind nämlich ein altes "Hobby" von mir. Oder sagen wir besser, dass es aus Schmerzen gewachsen ist, wo Dinge auf den Punkt genau stimmen mussten. Und erst danach fängt die Modernisierung des Codes an. Gut, hier geht es nur um C, das ist (z.B. gegenüber C++) vergleichweise harmlos. Trotzdem kann man Wochen damit vergeuden, obwohl man nur mal eben etwas kompilieren wollte und das Ergebnis dieses Erstversuchs eigentlich schon irgendwie brauchbar gewesen ist...

    So auf die faule Tour (s.o.) war ich ungefähr in einer Stunde durch (weil ich mich erst einmal umgucken musste und nicht alles auf Anhieb klappte, aber das ist bei solchen alten Sachen, insbesondere bei Multi-Plattform-Kram, normal). Das Schreiben hier war anstrengender, sollte also vom Aufwand her im Rahmen sein.

    Klappt immer noch nicht? Konkrete Fragen? Her damit (kostet ja nichts)!

    Grundsätzlich: Fehlermeldungen das Compilers/Linkers sind nützliche Helferlein. Bitte nicht davon entmutigen lassen. Irgendwann versteht man sie fast alle. Speziell hier geht es bloß um Namen, Pfade und Umgebungsvariablen, die man jeweils beizusteuern hat (neben evtl. noch fehlenden Installationsoptionen unter Visual Studio, die es teilweise auch "in sich" haben, sind aber i.d.R. bekannte Problemstellungen, für die es bekannte Lösungen gibt), ist also eine der harmloseren Varianten.
    jabu ist offline Geändert von jabu (07.02.2022 um 21:47 Uhr) Grund: kleine Korrektur

  3. #3 Zitieren
    banned
    Registriert seit
    Jan 2022
    Beiträge
    24
    Oh ich bin so froh, dass du dich damit auskennst. Ich habe nämlich überhaupt keine Ahnung von der Materie, weiß aber dennoch nicht wieso es bei mir nicht klappt, da ich ja alles habe, womit es gehen sollte und schon wirklich alles versucht habe die .dlls aus den Source Codes zu erstellen.

    Zumindest bei SDL12-compat muss man das SDL2 Development Kit (https://libsdl.org/release/SDL2-devel-2.0.20-VC.zip) mit CMake oder dem Visual Studio linken. Er fragt immer nach SDL2_INCLUDE_DIR und ich habe da auch ein Video gefunden, indem erklärt wurde wie man das im Visual Studio linkt, aber es kommen weiterhin Fehlermeldungen. Wie konfiguriere ich CMake darauf?

    Stell dir vor ich habe gerade Windows 10 frisch installiert, Visual Studio 2022 und auch CMake und habe sonst nur die Source Codes vorliegen. Wie gehe ich nun Schritt für Schritt vor?
    Ich starte Visual Studio und dann? Ein Tutorial über jeden einzelnen Mausklick würde mir helfen.

    Kannst du mir zur Not die .dlls beider Projekte erzeugen und als .zip verpackt schicken?
    Das würde mich sehr freuen. Dennoch würde ich es trotzdem gerne selber hinbekommen. Mit deinen Kenntnissen kriegen wir das bestimmt hin. Bin froh, dass du Ahnung davon hast.

    Update:
    Inzwischen hat man mir auch bei GitHub geholfen und zwar muss man für SDL-1.2-main im Ordner "include" die "SDL_config.h.default" umbenennen in "SDL_config.h" (also ohne das default) und dann im Ordner "VisualC" die Datei "SDL_VS2010.sln" ausführen, ein Upgrade auf VS2022 ausführen und dann kann man die Datei ganz ohne Fehler erstellen. Hab jetzt die SDL.dll mit der Versionsnummer 1.2.16.0.

    Jetzt muss ich nur noch das SDL12-compat hinkriegen das muss ja gelinkt werden.

    Update #2:
    So, hier die Lösung für SDL12-compat
    Download latest SDL2-devel-2.0.xx-VC release

    Extract it to C:\SDL2


    Start CMake, check the option "Advanced", press Configure, let it fail

    Edit SDL2_INCLUDE_DIR = C:\SDL2\include
    Edit SDL2_LIBRARY = C:\SDL2\lib\x86\SDL2.lib


    Configure again, Generate


    Start SDL12-compat.sln with Microsoft Visual Studio, set everything to "Release Win32", rebuild everything
    Usselwetter ist offline Geändert von Usselwetter (10.02.2022 um 11:44 Uhr)

  4. #4 Zitieren
    Mythos
    Registriert seit
    Jul 2011
    Beiträge
    8.286
    Schön, dass du drangeblieben bist!

    Zitat Zitat von Usselwetter Beitrag anzeigen
    Update:
    Inzwischen hat man mir auch bei GitHub geholfen und zwar muss man für SDL-1.2-main im Ordner "include" die "SDL_config.h.default" umbenennen in "SDL_config.h" (also ohne das default) und dann im Ordner "VisualC" die Datei "SDL_VS2010.sln" ausführen, ein Upgrade auf VS2022 ausführen und dann kann man die Datei ganz ohne Fehler erstellen. Hab jetzt die SDL.dll mit der Versionsnummer 1.2.16.0.
    Richtig. Das steht auch, etwas gröber formuliert, in meinem letzten Beitrag:
    Zitat Zitat von jabu Beitrag anzeigen
    • [. . .]
    • irgendeine Default-Header-Datei, die anscheinend als Vorlage und zum Anpassen gedacht ist, kopiert und passend (ohne "default") umbenannt (sonst hagelt es Fehler, da die Datei unter dem Namen nicht existiert, habe mir nicht die Mühe gemacht, mich mit den Optionen dort zu befassen),
    • [. . .]
    Und in irgendeinem Readme (daher habe ich es) steht es auch. Readmes zu lesen, ist allgemein ratsam.

    Zitat Zitat von Usselwetter Beitrag anzeigen
    Jetzt muss ich nur noch das SDL12-compat hinkriegen das muss ja gelinkt werden.
    Muss nicht gelinkt werden, denn sonst würde dieses, was du im folgenden Zitat beschreibst, nicht klappen. Es klappt, weil speziell hier die Angabe des Include-Pfades, in dem sich u.a. die SDL.h, die der Compiler vermisst (siehe Fehlermeldung) genügt. Der hier angegebene, anscheinend einem Projektstandard entsprechende, Lib-Pfad ist unter der vorgegebenen "VisualC"-Konfiguration unzutreffend. Es werden die Libs also nicht gefunden. Warum das Erstellen der SDL12-compat-DLL trotzdem klappt, steht weiter unten.

    Zitat Zitat von Usselwetter Beitrag anzeigen
    Update #2:
    So, hier die Lösung für SDL12-compat
    Download latest SDL2-devel-2.0.xx-VC release

    Extract it to C:\SDL2


    Start CMake, check the option "Advanced", press Configure, let it fail

    Edit SDL2_INCLUDE_DIR = C:\SDL2\include
    Edit SDL2_LIBRARY = C:\SDL2\lib\x86\SDL2.lib


    Configure again, Generate


    Start SDL12-compat.sln with Microsoft Visual Studio, set everything to "Release Win32", rebuild everything
    So ähnlich habe ich es im Erstansatz auch gemacht (bin von selber darauf gekommen). Ich habe dieses dann aber durch eine Umgebungsvariable, die ich für den Windows-Benutzer angelegt habe, gelöst (mit verschiedenen funktionierenden Ansätzen, sind nicht alle hier gezeigt).

    Die erste wichtige Erkenntnis ist, dass das CMakeSettings.json weder zum Projekt noch zu CMake gehört, sondern von Visual Studio (kürze ich als "VS" ab) aus den im CMakeList.txt angelegten Settings generiert wird, um dem Benutzer ein bequemes GUI zur Steuerung der Eingaben für CMake anzubieten und damit das Intellisense in der IDE funktioniert. Anstatt dass VS CMake anweist, VS-Projektdateien zu erstellen (um das Buildsystem von Microsoft, MSBUILD genannt, zu verwenden), weist VS CMake an, Projektdateien für das Buildsystem Ninja zu erstellen. VS unterstützt anscheinend Ninja, um die Builds anstoßen zu können etc.

    Die zweite wichtige Erkenntnis ist, dass einem niemand sagt, ob dieser Weg überhaupt unterstützt wird.

    Doch er hat seinen Reiz (leider ohne zu wissen, was genau im Sinne des Erfinders ist, also Fragen wegen Konfigurationsoptionen offen lässt):
    VS ist gut darin, halbwegs korrekte parallele Build-Setups, also die typischen vier Varianten (32 Bit Release / 32 Bit Debug / 64 Bit Release / 64 Bit Debug) systematisch nachkonfigurierbar zu machen, was mit CMakeSettings.json (und dann Buildsteuerung durch Ninja) auch gut klappt, aber strukturell eine bis zwei Ebenen zu spät kommt:
    Die Vorgabe für CMake beim SDL1.2-compat-Projekt versagt nämlich darin, CMake so anzuweisen, dass es entsprechende (am liebsten VS...)-Projektdateien von vornherein generiert!

    Es fehlt ein CMake-Skript, das das von Anfang an richtig macht (egal ob dann Ninja oder MSBUILD zum Zuge kommt). Das wäre nämlich dem Sinn von CMake entsprechend (und nicht dieses Nachfrickeln, obwohl es bei mir funktioniert hat, aber das will man lieber wegautomatisiert haben).

    Vielleicht gibt es irgendwo ein Skript, welches CMake die entsprechenden Parameter mitgibt? Auf dem normalen Weg ist es nicht so ganz einfach. Man will ja alle Konfigurationen in einem VS-Solution-File haben und das gleich richtig. Irgendwie scheint das zu fehlen oder nur auf Umwege erreichbar zu sein. Manuell kann ich mir zwar alles hinfummeln, aber das ist nicht der Sinn der Automatisierung. Überhaupt sind die SDL-Projekte kein Paradebeispiel für gelungenes Build-Setup. Trotzdem steckt einige Know-How im Code und sowieso verdammt viel Arbeit, was ich natürlich wertschätze.

    Um innerhalb des CMakeSettings.json auf Umgebungsvariablen zuzugreifen, ist folgendes Schema nötig: ${env.EnvironmentVariableName}

    Damit ergibt sich zum Beispiel (müsste i.d.R. an die realen Pfade angepasst werden; MY_USER_ENVIRONMENT_VARIABLE_SDL2INCPATH steht hier als Platzhalter für die Benutzer-Umgebungsvariable, die man unter der Windows-Systemsteuerung für den Pfad des Wurzelverzeichnisses der Lib-Builds anlegen würde, wobei natürlich i.d.R. auch die Pfade Anpassungen bedürfen, wobei ein für VS typischer z.B. auf \Win32\Release\SDL2.lib enden kann; wichtige Frage: Warum ist das nicht definiert? Diese Pfade dem Zufall bzw. den jeweils gültigen Visual-Studio-Defaults zu überlassen, ist doch dumm! Oder es müsste die SDL2.lib wenigstens abschließend, z.B. per benutzerdefiniertem Build-Schritt, ans endgültige Ziel kopiert werden.):

    Für 32-Bit-Release-Builds
    SDL2_INCLUDE_DIR = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2INCPATH}
    SDL2_LIBRARY = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2LIBPATH}\x86\release\SDL2.lib

    Für 32-Bit-Debug-Builds
    SDL2_INCLUDE_DIR = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2INCPATH}
    SDL2_LIBRARY = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2LIBPATH}\x86\debug\SDL2.lib

    Für 64-Bit-Release-Builds
    SDL2_INCLUDE_DIR = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2INCPATH}
    SDL2_LIBRARY = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2LIBPATH}\x64\release\SDL2.lib

    Für 64-Bit-Debug-Builds
    SDL2_INCLUDE_DIR = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2INCPATH}
    SDL2_LIBRARY = ${env.MY_USER_ENVIRONMENT_VARIABLE_SDL2LIBPATH}\x64\debug\SDL2.lib

    Ob bei im Pfad enthaltenen Leerzeichen Anführungszeichen nötig sind und ob hier Backslashes erlaubt sind, bin ich überfragt (Edit: Inzwischen nicht mehr). Ich tippe vorsichtig darauf, dass man hier schon intuitiv ziemlich weit kommt (Edit: Kommt man, denn VS übernimmt das Escaping, im JSON stehen die doppelten Backslashes; Anführungszeichen sind automatisch gesetzt), aber falls nicht, könnte man diese Alternativen probieren (ist von allgemeinem Nutzen):
    "${. . . . .}\ . . . . .\SDL2.lib"
    "${. . . . .}\ \. . . . .\\SDL2.lib" (Backslash escaped)
    "${. . . . .}/ . . . . ./SDL2.lib" (Slash, wie außerhalb von Windows üblich)
    ${. . . . .}\ \. . . . .\\SDL2.lib (Backslash escaped)
    ${. . . . .}/ . . . . ./SDL2.lib (Slash, wie außerhalb von Windows üblich)

    CMake selbst (z.B. bei CMakeList.txt und von dort aus eingebundenen Dateien) verwendet dagegen folgende Schemata (ENV vorangestellt):
    $ENV{EnvironmentVariableName}
    und innerhalb von manchen Ausdrücken:
    ENV EnvironmentVariableName

    Bei CMake selbst leiten in Strings eingebettete Backslashes Escape-Sequenzen (ungefähr wie unter der Sprache C, z.B. \t für Tabulator, \n für einen Zeilenumbruch etc.) ein, weswegen dem Backslash selbst ein Backslash vorangestellt werden muss (\\), da sonst das nächste Zeichen ein Steuerzeichen wäre. Siehe dazu die drei oben aufgeführten Varianten. Was unter VS an Backslashes bei Pfaden noch funktionieren mag, funktioniert direkt in CMake-Skripten nicht mehr. Wo String-Variablen an Listen angehängt werden, ist es ratsam, sie in Anführungszeichen zu setzen, damit ein möglicherweise enthaltenes Leerzeichen nicht als Listentrenner interpretiert wird. Dabei ist hilfreich, dass auch innerhalb von Double-Quotes interpretiert wird. Sonst würde manches nicht sinnvoll funktionieren.

    Nach dem kleinen Exkurs zur Fehlervermeidung wieder auf das von Dir angeführte C:\SDL2\lib\x86\SDL2.lib verwiesen:
    Das Schema SDL2\lib\x86\SDL2.lib entspricht anscheinend einem Standardpfad von SDL-Build-Setups für Linux. Dagegen passt diese Konvention gar nicht zu den Visual-Studio-Builds von SDL2, und zwar weder über den CMake-Umweg noch direkt über das vorgegebene Solution-File. Deswegen ist das Fehlschlagen des Auffindens normal.

    Trotzdem klappt das Erstellen der SDL-1.2-compat-DLL, da eben nicht gegen die SDL2-DLL gelinkt wird. Das liegt daran, dass SDL2.lib Importinformationen beinhaltet, die man nur (durch den Linker) der Importtabelle der SDL-1.2-compat-DLL hinzufügen lassen muss, wenn der Programmlader von Windows gleich beim Programmstart die SDL2-DLL binden soll. Dieses ist bei der vorliegenden Standardkonfiguration der SDL-1.2-compat-DLL nämlich nicht der Fall.

    Es gibt dort ein anderes Vorgehen:

    Wie kommt es also trotzdem dazu, dass die DLL geladen wird? -> Das veranlasst die SDL-1.2-compat-DLL nach dem Start selber, nämlich per Aufruf der Windows-API-Funktion LoadLibrary.

    Wie kommt es dazu, dass die Funktionen aus der SDL2-DLL aufgerufen werden können, so ganz ohne entsprechende Einträge in der Importtabelle? -> Das veranlasst die SDL-1.2-compat-DLL ebenfalls selber, nämlich nach dem Aufruf von LoadLibrary, und zwar per GetProcAdress (<- auch ein Beispiel dabei). GetProcAdress braucht ein Handle zur DLL und den Namen der Funktion, deren Adresse gesucht wird. Der Rückgabewert ist die Adresse der Funktion. Natürlich muss die komplette Signatur der Funktion (bzw. der Typ des Funktionszeigers) bekannt sein, z.B. weil sie im Code steht oder über ein Header-File der Abhängigkeit bekannt gemacht wird.

    "SDL2_LIBRARY = C:\SDL2\lib\x86\SDL2.lib" muss also nicht stimmen, weil die Importinformationen aus dieser Import-Lib beim Standard-Build-Setup der SDL-1.2-compat-DLL nicht benötigt werden. Das gibt bestenfalls eine Fehlermeldung, die man ignorieren darf. Der Pfad stimmt nämlich bei Windows-Builds mit Visual-Studio in Standardkonfigurationen nicht. Verwendet man das vorgegebene Solution-File, so kommt bei VS2022 dieser Pfad heraus:
    C:\SDL\VisualC\Win32\Release\SDL2.lib
    Man kann ihn natürlich in VS (unvorteilhaft) auf C:\SDL2\lib\x86\SDL2.lib abändern. Das ist unvorteilhaft, weil zwischen vielen Varianten (s.o.) - die nicht immer zueinander passen (worunter z.B. ein Debug-Build mit Performancenachteilen oder ein Build mit inkompatiblem Ausgabeformat (falscher Compiler/Linker oder inkompatible Settings derselben Tools) sein kann - nicht differenziert wird.

    Natürlich kannst du den Pfad eintragen. Er nützt nur nichts, solange nicht eine SDL-1.2-compat-DLL in einer Variante, die die SDL2.dll durch Windows bereits beim Programmstart geladen haben will, erstellt wird. Ob eine solche Variante angeboten wird, müsste man gucken. Beide Verfahren haben jeweils ihre Vor- und Nachteile. Eine aussagekräftige Fehlermeldung, z.B. dass die SDL2-DLL nicht gefunden wurde und wie eine Fehlerbnehebung aussehen könnte, lässt sich nicht implementieren, wenn die SDL2.dll bereits beim Programmstart von Windows geladen wird und fehlt. Der Programmlader von Windows muss nämlich die Adressen der aufzurufenden (importierten) Funktionen erst einsetzen. Falsche Adressen (Platzhalter) würden jedoch Programmabsturz (besser) oder Vandalismus (schlechter) bedeuten. Deswegen unterbindet Windows den Programmstart konsequent, falls die Abhängigkeit nicht geladen werden konnte oder falls Importe fehlen. Der Entwickler der abhängigen Datei kann demnach keine hilfreiche Reaktion oder Alternative implementieren, da sein Code niemals läuft. Das ist ein Nachteil der, hier unbenutzten (aber ansonsten häufigeren!), Variante mit dem Einbinden der Importbibliothek.

    Das Elend mit der Konfiguration geht tiefer:
    Eigentlich sollte die CMake-Konfiguration des SDL1.2-compat-Projektes unter Zuhilfename einer Umgebungsbvariable, nämlich mit dem Namen "SDL2DIR", über ein Such-Skript mit dem Namen "FindSDL2.cmake" (liegt unter sdl-1.2-compat\cmake\modules), welches die CMakeLists.txt des SDL1.2-compat-Projektes einbindet, die Pfade automatisch ermitteln. Dieses schlägt aber bei mir an mehreren Stellen fehl:
    Das Ergebnis des per Umgebungsvariable ermittelten Pfades lässt sich bei mir nicht direkt in SDL2_INCLUDE_DIR (innerhalb von FindSDL2.cmake) speichern, aber über eine Zwischenspeicherung in einer anderen Variable und dann als Zuweisung an SDL2_INCLUDE_DIR funktioniert es. Es hilft nicht, bloß den Cache immer wieder zu leeren. Das Zuweisen innerhalb von find_path muss anders als normales Zuweisen sein. Die Zuweisung an SDL2_INCLUDE_DIR innerhalb von find_path funktioniert nämlich nicht, wogegen die Zuweisung an eine Hilfsvariable und von dort aus an SDL2_INCLUDE_DIR funktioniert. Also habe ich das als Workaround eingebaut.
    Befriedigend ist das nicht, solange die Ursache nicht geklärt ist. Der Ersteller von FindSDL2.cmake sollte damit wohl Erfolg gehabt haben, ich aber nicht. Das ist schon seltsam. Vielleicht handelt es sich um ein obskures Scoping- oder Zugriffsproblem, vielleicht wegen des von VS erstellten CMakeSettings.json? Oder ein komisches Copy-on-write-Artefakt? Irgendwas muss beim Zuweisen per find_path anders als beim normalen Zuweisen sein. Von Windows-Batch-Skripten kennt man (in der Natur der Sache liegende, wohlbekannte) Probleme, die eine ähnliche Symptomatik zeigen. Vielleicht sind die Ursachen ähnlich?
    Wie auch immer, der Workaround funktioniert. Dann habe ich noch das Zusammensetzen der Lib-Pfade zu den "VisualC"-Pfaden aus SDL2 passend gemacht. Schlussendlich findet FindSDL2.cmake jetzt anhand der vorgesehenen Umgebungsvariable SDL2DIR alles, was es finden muss, um auch andere Varianten, zum Beipiel die, für welche für man die Import-Lib brauchen würde, zumindest theoretisch, zu unterstützen (obwohl derzeit unbenötigt). Das ist näher an dem dran, wie das System mal angedacht war (universeller verwendbar). Aber im Web lässt sich kaum etwas finden, wie man das System im Sinne des Erfinders betreibt. Wie man es manuell hinfrickelt, weiß ich. Dafür brauche ich keine Tutorials. Interessanter wäre schon, wie man das alles automatisiert und konsistent hinbekäme.

    Andere Baustelle:
    Ich habe viel Zeit mit der SDL2-VisualC-Konfiguration verbracht und musste feststellen, dass die teilweise suboptimal ist, insbesondere beim Erstellen der Tests, da ist sie unvollständig und auch etwas fehlerhaft, z.B. indem keine Konsole erstellt wird, wo eine nötig ist (leicht zu fixen, nervt trotzdem) oder indem Ressourcen, z.B. Bitmaps, nicht mitkopiert werden (oder nicht an die richtige Stelle). Das habe ich zwar größtenteils gefixt, ist aber unbefriedigend, solange das nur in meiner VS-Projektkonfiguration und in keinem CMake-Skript steht. Eventuell ist auch das Original mit Handarbeit entstanden.
    Das Verzeichnis zum Testen für "VisualC" ist ja ein anderes, und zwar das, in welchem auch die anderen Ausgabedateien erstellt werden. Das ist auch gar nicht mal schlecht, weil damit die Ergebnisse anderer Builds nicht überschrieben werden und 32 Bit, 64 Bit, Release und Debug schön auseinandergehalten werden. Dafür hat man die Ressourcendateien viermal zusätzlich vorzuhalten, wenn man alle vier Kombinationen erstellen lässt.
    Auch bei den Optimierungen bezüglich SSE und SSE2 ist nicht alles astrein. PGO (Profile Guided Optimization) funktioniert auch nicht. Für manches habe ich Lösungen gefunden, sodass ich jetzt endlich weitgehende SSE2-Builds (auch jenseits der vom Autor mühsam manuell hineingeklöppelten Intrinsics) habe und Whole-Program-Optimization mit Linktime-Code-Generation nutzen kann, geht aber nur mit ein paar kleineren Kompromissen an der einen oder anderen Stelle. Der Autor hat zu viel handoptimiert, und der Compiler von Microsoft hat ein paar Unzulänglichkeiten bei SSE und SSE2. Diese Kombination macht es schwer, den Compiler dazu zu überreden, sein volles Optimierungspotential auszuschöpfen. Zudem ist die originale Optimierung schon ziemlich gut, vorausgesetzt man verwendet keine Debug-Konfiguration, die ist nämlich standardmäßig aktiv. Mit der hättest du eine sehr miese Performance (ist bei Debug-Builds normal). Du müsstest bei SDL2 die Release-Konfiguration wählen.
    Unabhängig davon, was dir die SDL-Leute sagen, würde ich immer vorsichtshalber, auch wo die Debug-Konfiguration dicht an einer Release-Konfiguration eingestellt ist (hier bei SDL2 ist es für "VisualC" nicht so, sondern eher wie erwartet, also Release für Performance und Debug für Debugging), und die angeblich genügen soll, extra eine Release-Konfiguration anlegen und die akribisch kontrollieren und nötigenfalls nachkonfigurieren. Bei Debug-Builds könntest du nämlich Probleme mit den performancemindernden Defaults von MSVC bekommen und dich über zu wenig FPS oder Ruckeln wundern. Grundsätzlich kann man die Namen und Settings zwar frei wählen, aber da mit automatischer Generierung gearbeitet wird, weiß man nicht ohne Weiteres, ob die performancemindernden Settings einer Standard-Debug-Konfiguration unter allen Umständen sinnvoll abgeändert wurden bzw. werden, eben wie bei einem Release-Build. Sobald Visual-Studio heruminterpretiert, muss man nämlich damit rechnen, dass es seine Standardsettings wählt und die eben durch das Gefundene lediglich ergänzt, ändert oder überlagert. Alles andere wäre unbelegt und damit mehr oder minder dem Zufall überlassen. Man kann ja nicht immer alle Skripte und jegliches Tool-Verhalten udn alle Projektspezialitäten im Kopf haben. Ich kann es nicht ausstehen, wenn mich Code oder ein Projektsetup anlügt, sodass nur die Eingefleischten mit den Details umzugehen wissen (zumal sie selber den Überblick verloren haben, wenn man sich die Tests anschaut).
    Fromme Versprechungen beziehen nicht unbedingt alle Wege der automatischen Generierung ein. Da könnten so komische Sachen herauskommen, dass z.B. Linux-Builds beste Performance liefern, aber Windows-Builds nicht, was dann Windows zugeschoben werden könnte, aber doch bloß an mangelnder Sorgfalt beim Build-Setup für Windows liegen könnte. Es wäre nicht das erste Mal, dass es heißt, dass irgendwas unter Linux besser läuft, wo es dann hauptsächlich doch bloß an schlechterem Support für Windows liegt, da die Entwicklung hauptsächlich von Linux her betreiben wird (und auch die, teils subtilen, Unterschiede der Compiler und Libs nur unzureichend einbezieht). Damit sage ich nicht, dass Linux nicht in Teilbereichen messbare Vorteile gegenüber Windows hätte, aber viele Beobachtungen bezüglich Unterschieden haben ihre Ursachen doch beim "unausgegorenen" Low-Level-Teil eines Cross-Plattform-Unterbaus. Das kann schon wegen der enormen Mühen der Mehrgleisigkeit passieren. Das Betriebssystem ist ein Teil, der Unterschiede ausmachen kann, die Tools und Ansätze zur Anwendungsentwicklung ein anderer. Es ist kaum leistbar, alle relevanten Pitfalls jeder Umgebung zu kennen und sie geschickt zu überbrücken.

    Fazit:
    Bei der bestehenden Komplexität sind Wartbarkeit und Zuverlässigkeit kaum noch gegeben. Es müssten viel mehr Mühen in Restrukturierung und Komplettierung der Build-Skripte gesteckt werden. Es müsste im Code der Low-Level-Teil modernisiert werden, sodass er den Raum der Möglichkeiten weniger beschränkt. Das ganze System steht kurz vor der vorübergehenden "Unwartbarkeit". Wird irgendwo nochmal am Compiler etwas verändert, kann es leicht komplett brechen. Manches ist zu speziell. Man sieht das erst, nachdem man tiefer eingetaucht ist. Das Projekt ist (mit einigem Fleiß) wegen gewisser Qualitäten rettbar, es ist kein Sackgassenkandidat. Aber es kann leicht passieren, dass sich niemand mehr findet, der den Kram auf ein angenehmeres und leichter wartbares Level bringt. Mit solchen Sachen kann man schlecht punkten, wenn man einen Job sucht, obwohl gerade solche Aufgaben besonders wichtig sind. Man kann auch kein tolles Feature, das man erschaffen hätte, vorzeigen. Es handelt sich um eine Aufgabe für Idealisten, könnte man sagen. Im Grunde wurde mit der Einführung von CMake schon ein guter Ansatz verfolgt. Das müsste konsequenter umgesetzt werden, wie man es bei anderen Projekten schon gesehen hat. Aber wer hat schon Bock darauf, das unbezahlt in seiner Freizeit zu machen? Wer räumt schon gerne anderen Leuten ihre Zimmer auf? Man müsste es schon zum "eigenen Zimmer" machen, und selbst dort klappt es erfahrungsgemäß nicht so recht...


    PS

    Konsistenz bei Konventionen ist wichtig. Und Meidung von Definitionslücken ist wichtig. Beides vermisse ich bei diesen drei Projekten stark. Es sollte mehr Verlässlichkeiten und weniger Potential für Überraschungen geben. Eine Dokumentation ist kaum vorhanden. In solchen Fällen sollte alles mehr für sich sprechen. Dass die Leute längerfristig vom GNU-Buildsystem weg wollen, ist schon mal eine gute Einsicht.

    Leider gibt es nicht viel Gutes für Buildkonfiguration, vermutlich gar nichts Gutes. Wenn mich einer fragen würde, was ich mit hunderttausend Euro, für die ich eine Gegenleistung erbringen müsste, Konstruktives anfangen würde, dann vielleicht genau das, nämlich ein taugliches System für Buildkonfiguration und dazu auch ein Buildsystem erschaffen (habe konkrete Ideen, worauf es ankäme, um es sogar besser als CMake zu machen).

    Was ich bisher gesehen habe, ist immer wieder anders, aber nicht gut. Alles Unintuitive in dem Bereich gehört meiner Meinung nach auf die Müllhalde der Geschichte. Systeme, die ein schwer vorhersehbares Verhalten zeigen, da sie stark auf Systemtools und damit auf das Verhalten des unten drunter liegenden Systems angewiesen sind (oder diesen ohne guten Grund ähneln), kann man getrost in die Tonne kloppen. Aber das ist ja, mehr oder minder, meistens so. Und so kommt es meistens zu seltsamen Überraschungen (und einer unsteten Lernkurve).

    Es gibt schon gute Gründe dafür, dass Leute sich das nicht antun wollen und sich an ihre IDE ketten oder mit nacktem GNU Make nach der Freiheit suchen (diese aber damit auch nicht erlangen), was eine andere Form der Kapitulation vor einer eigentlich lösbaren Aufgabe ist. Die zu erschaffende Sprache muss erst einmal etwas taugen, sonst sind alle Mühen sinnlos. Bei CMake wurde das leider auch verbockt. Das wird nur so oft verwendet, weil nichts Besseres da ist. Aber ein paar Ansätze davon sind gut. Es geht eben nur mit Trippelschritten weiter. CMake ist universell und mächtig und bevormundet wenig, was schon mal gut ist, aber es fehlen geeignete Abstraktionen für ein Problem, welches tyischerweise und naturgemäß immer dieselben Abstraktionen beeinhaltet. Dass das keiner so richtig merkt, finde ich schon seltsam.

    Am dichtesten an der richtigen Abstraktion dran, und zwar weit vor allen anderen Systemen, die ich mir bisher angeguckt habe, ist MSBUILD, welches unter der Haube von Visual Studio eingesetzt wird. Aber es ist zu inflexibel für allgemeinen Gebrauch und eine kaum für Menschen lesbare XML-Hölle, die jedoch ganz passabel Eigenschaftenvererbung ermöglicht (worauf es im Wesentlichen ankommt!), wenn man denn das GUI von VS benutzt. Sonst ist es unbenutzbar! Die Abstraktionen gehören natürlich generalisiert. Es gibt z.B. im Projektbaum der Eclipse-IDE ein paar Freiheiten, die VS nicht bietet. Und Makefiles für GNU Make müssten auch gescheit abbildbar sein. Das muss alles generisch möglich sein, ohne Nachfrickeln. Sonst sind die Abstraktionen untauglich. Eine der überhaupt universellsten IDEs von den Buildsystemen her ist Eclipse. Und komplett anders ist reines GNU Make. Es sollte nicht ganz falsch sein, solche als Prüfstein für ein Buildkonfigurationsprogramm zu benutzen. Damit meine ich nicht, dass man alles von Anfang an als Ausgabeformate konkret untertützbar haben müsste, sondern dass die Abstraktionen grundsätzlich mit abgedeckt werden müssten, also ein Geradeaus-Vererbungssystem ebenso wie rekursive Abhängigkeiten und das alles mit einer einfachen menschenlesbaren Syntax, und zwar mit Einfachheit durch Mächtigkeit des Ansatzes. Denn je mehr man frickeln muss, desto komplizierter wird es.

    Man muss Eigenschaften ("Properties") auf einfache Weise erben, explizit kopieren und überschreiben können. Das kann MSBUILD bzw. Visual Studio ganz hervorragend. Aber man kann das dazu nötige XML nicht mehr regelmäßig manuell hinschreiben, ohne davon verrückt zu werden. Ein Teil steckt im VS-Solution-File, ein Teil in den Projektdateien und der interpretierende in MSBUILD. Man müsste MSBUILD sozusagen atmen, um alles auszuschöpfen. Zwar sehen die VS-Solutions und Projekte beim Durchgucken mit einem Editor einfach aus, was schon gut ist, aber der Eindruck täuscht über die Mächtigkeit hinweg. Und selber schreiben kann man den Kram kaum, weil man zu viel von dem, was MSBUILD und die Tools und SDKs verbergen, auswendig wissen müsste und weil der Kram längst nicht so intuitiv ist, wie ihn ein Mensch bräuchte. Man kann sich natürlich an einer Vorlage entlanghangeln, aber dann weiß man noch nicht, welche Alternativen unterstützt werden.

    Dieses verborgene "Wissen" zur korrekten Generierung von Build-Setups gehört als eine Art Datenbank für Regelsätze in den Teil für die Transformation zur Ausgabe hinein und müsste einen großen Wartungsaufwand erfordern. Das ist aber der Brot-und-Butter-Fleiß-Teil. Spannender finde ich, den Teil der Formulierung des eigentlichen Problems in für Menschen leicht zugänglicher Form und zugleich mit passenden und einleuchtenden und keine Schranken auferlegenden Abstraktionen zu lösen. Bisher ist jeder Versuch, dieses zu erreichen, gescheitert! Der Weg, den reale Systeme gehen, um universell verwendbar zu sein, sind ihre prozeduralen und imperativen Ausdrucksmittel, die aber von ihrer Auslegung her objektorientierten und deklarativen und damit für Menschen mit viel wneiger Aufwand konfigurierbaren Systemen im Weg stehen. Das miteinander zu vereinen, und zwar so, dass es ein Mensch kapiert, ist eine schwierige Aufgabe.

    Menschen verstehen entweder gut:
    "Tu dies, dann das, dann..."
    oder
    "So will ich es haben, wobei X wie Y ist, aber die Komponente X.a anders als Y.a ist, und zwar so und so überschrieben (spezialisiert)."

    Dabei gibt es noch die Unterscheidung, ob man die Dinge bei Abhängigkeiten vom Ende her oder von vorne betrachtet, also ob man entweder ein Rezept hat, das etwas nach und nach aufbaut (kann in abbrechende Äste enden) oder ob man zuerst definiert, was erstellt werden soll und dann alle Vorprodukte (Abhängigkeiten) dafür ebenfalls definiert und deren (Unter)-Abhängigkeiten usw., ungefähr wie bei GNU Make (wobei auch damit Mischformen möglich sind), wobei diese Konzeption dazu führen kann, dass schlussendlich gar nichts entsteht und das schwer zu fixen ist. Dafür gibt es einige Garantien für Vollständigkeit, wenn es baut.

    Es ist gewiss nicht trivial, geeignete und zugleich beherrschbare Abstraktionsmittel für alles zu finden. Aber der rein wirtschaftliche Wert, sich dem mehr als bisher anzunähern, müsste im Multizigmilliarden-Dollarbereich liegen. Die eingesparte Menschenversklavung wäre der eigentliche Bonus.

    Alles zusammen ist schwer zu denken, wird aber selten wirklich im selben Atemzug gebraucht, kann also teils separat behandelt werden. Bestehene Systeme lösen den Übergang und das Zusammenwirken nicht in geeigneter Weise. CMake ist gut (wäre schlimm, wenn es nicht mal das geben würde), aber noch nicht gut genug, um Menschen auf diesem Feld von der Sklaverei durch die Maschine zu befreien. Bei genauerer Betrachtung ist es jedoch nicht Sklaverei durch die Maschine sondern durch frickeligen Code, der aus zu kurz gedachten Ansätzen wegen irgendwelcher Spezialprobleme entstanden ist. Ich finde es schrecklich, wie die IT Menschen versklavt - regelrecht verbrennt! Und es wird immer schlimmer, wenn ich mir die Hipster-Höllen-Ansätze angucke, je moderner, desto menschenverachtender. Und immer wieder kommt Neues hinzu, anstatt etwas einmal besser zu machen.

    Ohne zig Programmiersprachen zu lernen (die der Tools mitgerechnet), kommt man nicht mehr zurecht, was aber die Problematik, nachher nichts richtig zu können, impliziert. Man lernt dann nur noch und bekommt nichts produktiv mehr auf die Reihe. Da ist die IT im Jahr 2022 angelangt. Trotz immer mehr Automatisierung wird alles immer schlimmer. Ohne extra angestellte Dev-Ops-Experten kein Produkt etc. Solche Konzepte geißeln die Menschheit. Ich bin schon lange davon überzeugt, dass das mehr schadet als nützt. Man braucht immer mehr Entwickler, um Probleme zu lösen, die früher als einfach galten. Und es wird immer teurer.

    Katastrophal ist heutzutage GUI-Entwicklung, was größtenteils daran liegt, dass Microsoft das Windows-API und C++ vernachlässigt und die .NET-Hölle erschaffen hat und damit wichtige Grundlagen und Anreize, um darauf etwas Gescheites aufzubauen, fehlen. Nichts gegen C#, das ist nicht das eigentliche Problem. Es gibt kein einziges rundherum taugliches plattformübergreifendes GUI-Toolkit. Und es gibt nicht mal ein einziges taugliches für Windows. Mit welch kleinem Aufwand wurden einst vor 20 Jahren von winzigen Programmierklitschen kompakte Programme mit Borland Delphi erstellt, die ein GUI haben und auf den Punkt genau das tun, was sie tun sollen? Dafür braucht man heutzutage ca. 150 MB mehr (einen eingebetteten Browser) und mindestens dreimal so viele, nämlich unterschiedlich spezialisierte, Leute. Es ist ja nicht so, dass die Web-Programmierer, die man heutzutage für die grässlichen eingebetteten Browser (Chromium) braucht, die normale Anwendungsprogrammierung beherrschen würden und umgekehrt. Beides zuammen ist für eine Person längst nicht mehr beherrschbar. Und irgendwer muss sich um das überbordend komplexe Gesamtkonstrukt und dessen Wartung, bis hin zu Paketierung und Verteilung, kümmern. Eine etwas andere Variante, wie man ins Verderben laufen kann, ist Bindung an die Knebellizenzen und Abhängigkeiten von Qt. IMO müsste WxWidgets viel mehr Aufmerksamkeit, Unterstützung und Anerkennung finden, nicht etwa weil das technisch ideal wäre, sondern weil es tatsächlich mit am ehesten ein reales Problem, welches von vielen Entwicklern nicht mal als solches erkannt wird, im Rahmen seiner beschränkten personellen und finanziellen Möglichkeiten, tatsächlich löst (eine Art plattformübergreifender MFC-Ersatz). Solche echten Lösungen sind sehr selten in der IT. Leider steckt zu wenige Manpower dahinter, um das auf das für universellen Einsatz und gute Qualität benötigte Level zu heben (es wird ganz allmählich besser, ist also nicht so, dass man sich dessen nicht bewusst wäre). Für mich wesentlich ist, dass das zugrundeliegende Problem verstanden wurde, was nämlich nur sehr selten passiert. Aus meiner Sicht ist schon das lange Weiterpflegen enorm wertvoll, weil damit gezeigt wird, wie es gehen kann bzw. könnte, kleine Macken hin oder her. SDL hat ja auch etwas von dieser Denkweise. Sonst (wenn es Hipsterkram wäre) hätte mich das jetzt gar nicht interessiert. Ich habe schon, trotz einiger Schwächen, gewisse Sympathien dafür.

    Die IT geht völlig falsche Wege, indem sie sich längst ihre Probleme selber konstruiert.
    jabu ist offline Geändert von jabu (13.02.2022 um 10:38 Uhr)

  5. #5 Zitieren
    Mythos
    Registriert seit
    Jul 2011
    Beiträge
    8.286
    Wie man meinem länglichen Geschreibsel entnehmen kann, bin ich über die Situation des Build-Setups von SDL2 (wie auch der anderen Versionen) unglücklich, da es wer weiß wieviele Wege nach Rom gibt, aber alle irgendwie krückenhaft erscheinen, insbesondere wenn man Windows und Visual Studio verwenden will. MinGW, also der GCC für Windows, ist unter Windows nur die zweitbeste Lösung.

    Für mich ist jetzt, nach zahlreichen Versuchen mit und Einblicken in Variablen, Makrokonstanten, Optimierungsoptionen sowie diversen und teils fiesen Fehlerkonstellationen endgültig klar, dass der Zweig unter "VisualC" die schlechteste aller Optionen ist, obwohl sich anscheinend extra jemand die Mühe gemacht hat, händisch nachzuarbeiten. Ich möchte diesen Zweig, bei aller Liebe, nicht mehr benutzen. Mir kam der von Anfang an "fishy" vor. Man entwickelt ja mit der Zeit einen Riecher für so was. Meinetwegen kann der als Legacy-Zweig stehenbleiben, aber dann sollte der auch so heißen. Leider soll das, der Doku nach zu urteilen, immer noch der allgemein für Windows gedachte Zweig sein. Na ja...

    Begründung:
    Der Zweig unter "VisualC" ist ein Spezialfall, welcher nicht automatisch erbt, was er aus der übergeordneten Konfiguration erben müsste. Warum ist das so schlimm? Verändert man unter Visual-Studio Projekteigenschaften in noch so sinnvoller Weise, so mangelt es dabei an ebenfalls abzuändernden Makrokonstanten, die sich sonst über den Umweg von Umgebungsvariablen oder Parametern, die CMake mitgegeben werden müssen, ergeben.
    Und so ist es nicht verwunderlich, dass manche sinnvolle Optionen, die man sich nachträglich hinkonfiguriert, nicht harmonieren wollen und dann unerwartet fehlschlagen oder ein falsches Verhalten zeigen. Es müssten dafür nämlich auch die Variablen aus den CMake-Skripten geändert werden. In einfachen Fällen, nämlich wie offiziell unterstützt, genügt es sogar, nur die Variablen aus den CMake-Skripten zu ändern. So ist das System, welches wohl in erster Linie für Cross-Compiling ausgelegt ist, eigentlich gedacht. Das dedizierte Visual-Studio-Setup ist dabei nur ein Nebenprodukt, bei dem es meinem, natürlich nur ganz persönlichen, Eindruck nach wohl darum ging, wenigstens eine SDL2-DLL abzuliefern, um den "Windows-Noobs" das Maul zu stopfen.
    Daher sind die Tests zwar vorgesehen, aber aufgrund längst geänderter Konventionen für Pfade nur dann funktionsfähig, wenn man a) diese manuell fixt oder die Ressourcen manuell in das Testverzeichnis kopiert und b) die Linker-Optionen so anpasst, dass die Windows-Konsole eingebunden wird, wo benötigt.
    Das heißt, dass das dedizierte Visual-Studio-Build-Setup wohl schon lange verwaist ist! Und es ist sowieso nicht sinnvoll, da es nicht zur Generierung durch CMake vorgesehen ist oder dann, wenn man es unbedingt will, jedesmal nachträglich hingebogen werden müsste.
    Wer dennoch funktionierende individuelle Builds (z.B. für Maschinen mit/ohne bestimmte Befehlssatzerweiterungen oder mit/ohne bestimmte Optimierungen) aus dem "VisualC"-Zweig herausholen will, muss schon genau hingucken, welche Voraussetzungen dafür gegeben sein müssen. Machbar ist das allemal, aber ist bezüglich der Wartung umständlich und fehleranfällig.

    Das war beim letzten Edit meines vorangegangenen Beitrages und schon weit davor klar, aber ich hatte noch nicht meine abschließende Entscheidung darüber treffen können, wie es denn nun weitergehen soll, also mit einem Fixen der "VisualC"-Konfiguration oder mit einem Fixen der allgemeinen Konfiguration. Denn es musste erst die Frage, was "im Sinne des Erfinders" ist bzw. welche guten Gründe hinter bestimmten Entscheidungen stecken, geklärt werden. Erst danach lässt sich einigermaßen abschätzen, welcher Weg sich auch längerfristig erweisen könnte.

    Meine Entscheidung steht nun vorerst insofern fest, dass ich die "VisualC"-Konfiguration ignorieren werde, da es mir schon aus den vorgenannten Gründen nicht sinnvoll erscheint, mit dieser weiterzuarbeiten. Denn der Abhängigkeiten-Rattenschwanz führt zur Notwendigkeit ständigen manuellen Nachfixens, und das fortan zu vermeiden, ist gerade meine Motivation für die längerfristige Perspektive gewesen. Denn ich wüsste nicht, wie ich bei einem SDL2-compat-Build, welches mit bestimmten angepassten Optionen arbeitet, beim derzeitigen Setup ohne langwierige und fehleranfällige Frickelei auch noch eine dazu passende SDL2-Variante erhalten sollte, z.B. als statische Lib (zum direkten Einbinden) oder einmal mit statisch eingebundener VC-Runtime und einmal ohne oder mit bestimmten Optimierungen oder ohne oder...
    Das ergibt nämlich eine riesige, praktisch unkontrollierbare, Variantenmatrix, wenn man manuell nachkonfigurieren muss. Wenn ich nur eine einzige Option bei der SDL1.2-compat ändern will, muss ich in manchen Fällen an hunderten(!) Stellen unter der "VisualC"-Konfiguration von SDL2 manuelle Anpassungen vornehmen, schon zum kurzen Ausprobieren! Wie soll das möglich sein? Praktisch gar nicht!

    Wegen des Durchmessens solcher Probleme und des Evaluierens von Möglichkeiten zur Besserung der Lage habe ich längere Zeit zur Rückmeldung gebraucht und meine Texte nicht präzise formulieren können. Zu viel Energie ging in das Durchdringen des Chaos hinein. Letzteres zeichnet sich dadurch aus, dass bei oberflächlicher Betrachtung alles ganz einfach erscheint und man auch schnell seine popelige DLL bekommt. Aber wehe, man meint es mit der ganzen Sache ernst, nämlich indem man sie "im Sinne des Erfinders" auch unter Windows mit Visual Studio umsetzen will, und zwar in allen Varianten, die dieser "Erfinder" vorgesehen hat. Dann bricht plötzlich alles zusammen.

    Dass das bisher keinen so richtig zu kratzen scheint, könnte daran liegen, dass Linux-User sich manchmal auf ihre CPU-Architektur hin optimierte Builds selber kompilieren lassen, wogegen das bei Windows-Usern nur selten vorkommt. Zudem ist es eine gängige Meinung, dass Windows-Usern kaum zugemutet werden kann, dass eine ausführbare Datei (Exe, DLL etc.) nicht auf allen Systemen läuft (weswegen man ihnen eine schlechter optimierte, die fast überall läuft, gibt (eine für mich unbefriedigende Pauschalität)). Zudem kennen sich mache Entwickler, die Anwendungen von Linux zu Windows portieren wollen, nicht gut mit der Windows-Compiler-Toolchain aus - was kein Vorwurf meinerseits ist, denn wer kann schon alles überblicken? Es ist heutzutage wohl kaum noch zu schaffen, und wenn man das alles überblickt, dann hat man naturgemäß woanders Lücken.

    Ich vermute vorsichtig, dass für eine Cross-Compiling-Variante, bei der der GCC-C-Compiler Windows-Binaries ausspuckt, ebenso wie bei MinGW (GCC für Windows, was aber manchmal suboptimal oder inkompatibel ist), keine Spezialkonfiguration nötig gewesen ist, wohl aber für Visual Studio. Nun hat sich aber Visual Studio, mitsamt Compiler, Linker, C-Lib und Windows-SDK mit den Jahren weiterentwickelt, was einige alte Probleme verschwinden und dafür neue enstehen ließ. Das heißt, dass die Voraussetzungen, die für Windows früher mal galten oder heute noch für Support alter Windows-Versionen gelten, längst nicht mehr stimmen. Aber diese alten Voraussetzungen sind noch im "VisualC"-Zweig berücksichtigt, da er sonst für manche ältere Umgebungen ungeeignet wäre.
    Die Problematik erstreckt sich teils über Weichen, die per Makros gesetzt werden, bis tief in den Code hinein und existiert daher auch teils bei den anderen Zweigen. Es gibt gute Gründe für diese Weichen bezüglich bestimmter Compiler-Toolchains. Aber es gibt kaum gute Gründe, die gegen ein weiter vereinheitlichtes Setup auf äußerer Ebene, also konsequenter per CMake, auch für Visual-Studio-Builds, sprechen. Voraussetzung für Beibehaltumng bisheriger Bequemlichkeit ist natürlich Unterstützung von VS2010 durch CMake, aber die ist gegeben.
    Derzeit ist das, grob gesagt, nur halbe Ausnutzung der CMake-Power, mit jenen Konsequenzen, zu deren Meidung CMake ersonnen wurde. Das ist nämlich ein altbekanntes Problem, und es muss irgendwie von den SDL-Leuten ebenfalls grundsätzlich verstanden worden sein. Sonst hätte man sich die Mühe, mit CMake anzufangen, doch wohl erspart.

    Daraus folgt für mich, dass ich, zumindest für den Support neuerer Windows-Versionen, lieber auf den allgemeinen Zweig setze und mir, davon ausgehend, ein paar Gedanken darüber mache, wie man die Windows-Builds sinnvoll verwalten kann.

    Als bisher bestes Tool, um den Aufwand für die Übersicht und das Austesten von Verzeichnisstrukturen und Setups zu bewältigen, hat sich bei mir das GUI-Tool, welches CMake beiliegt, herausgestellt. Zuerst habe ich, weil es flexibler ist, mit dem nackten CMake gearbeitet. Aber das war für den Anfang, wo es um Übersicht und Konsequenzen der vielen einzelnen Optionen geht, zu aufwendig, weswegen ich zu Visual Studio und dem JSON-File übergegangen war. Aber das ist, bei aller Bequemlichkeit und trotz teilweise hinzugefügter Optionen nicht so "im Sinne des CMake-Erfinders" wie das GUI-Tool, welches CMake beiliegt. Zwar leistet Visual Studio mehr und macht auch manches besser und komfortabler, aber ich habe den vagen Eindruck, dass das CMake-GUI-Tool hinsichtlich Wahrung von Korrektheit und Reproduzierbarkeit besser geeignet ist. Zumindest sprechen die bisherigen Erfolge dafür, und ich kann mir teilweise auch schon denken, woran das liegen könnte. Aber ich will das mit dem JSON-File unter VS sowieso nicht weiterverfolgen, da ich nun froh bin, Visual Studio endlich aus dieser Prozessebene heraushalten zu können. Denn eine Abhängigkeit von VS gehört nicht in diese Ebene hinein (obwohl die Asisstenz durch VS bequem ist und schnell zu Ergebnissen bei simplen Einzelaufgaben führt).

    Längerfristig bzw. allgemein ist es besser, ein Skript (Windows-Batch, Linux-Bash o.ä.) zu erhalten und damit dem eigentlichen CMake (per Kommandozeile) das passende Environment bereitzustellen und passende Anweisungen zu übergeben, Cache-Behandlung inklusive. Denn irgendwo muss die Persistenz hin. Es ist wenig sinnvoll, alles immer wieder in das GUI-Tool eingeben zu müssen. Zwar kann ein guter Teil in CMake-Skripte eingepflegt werden, aber einerseits ist das schwer zum Originalprojekt synchron zu halten, weswegen man das gering halten will, und andererseits gibt es nun mal bei einigen Optionen die Qual der Wahl, also keine universelle Lösung. Oder man verwendet spezialisierte CMake-Skripte, die das originale einbinden oder ein einziges mit Switches, welches das originale einbindet. Die letzte Option wäre dann durch das CMake-GUI-Tool bequem einsehbar und bedienbar. Eventuell eignen sich zur Umsetzung auch "Module", wie sie CMake unterstützt.

    Also baue ich mir jetzt mein SDL2 unter Visual Studio so, wie es eigentlich für Cross-Compiles oder MinGW vorgesehen ist. Da wollte ich ja mit einigen meiner Versuche während der letzten Tage hin, aber ich hatte zunächst andere Baustellen zu durchmessen. Man will doch nicht erst nach großer Fehlinvestition merken, dass man aufs falsche Pferd gesetzt hat. Jedenfalls ist es für mich viel befriedigender, bei meinen Visual-Studio-Builds wenigstens einigermaßen mit der Hauptlinie synchron zu bleiben. Wenn man nicht ganz synchron bleiben kann, dann kommt es darauf an, dass die Stelle, wo man das fixen kann, wohldefiniert (am besten extra ausgelagert oder autogeneriert) ist, sodass man auch später, wenn man nicht mehr alles im Kopf hat, damit zurechtkommt. Natürlich hat auch das Grenzen (die von der Art der Änderungen abhängen).

    Im Idealfall ließe sich ein übergeordnetes VS-Projekt so gestalten, dass alle drei SDL-Projekte mit exakt denselben gemeinsam gültigen Settings kompiliert werden, ohne dabei die Synchronität mit dem Originalprojekt zu verlieren. Ich möchte einfach einen Knopf drücken, sodass das durchrattert und fertig. Dort möchte ich längerfristig hin. Erst dann habe ich das Gefühl, dass ich überhaupt SDL für Windows habe (und dass ich ein Problem gelöst habe). Solange das nicht wenigstens annähernd so ist, bleibt das für mich typisches Nerdgefrickel.

    Idealerweise würde man das auch multiplattformfähig vereinheitlicht automatisiert haben wollen. Aber dann müsste schon das ganze System auf CMake setzen und das GNU-Buildsystem herausgekickt werden. Ich bin nicht bereit, nicht mal für mich selbst, auch nicht unter Cygwin, viele Stunden in die Pflege solcher Altlasten zu stecken. Das ist jetzt kein Verriss des GNU-Buildsystems, sondern stützt sich auf die Erkenntnis, dass das für diese Art von Aufgabe nicht wirklich geeignet ist - was daran liegt, dass dem "First-Citizen" Makefile (als Input) die geeigneten Ausdrucksmittel fehlen, um eine für Menschen nachvollziehbare Konfiguration zu gestalten, zumal unter GNU-Make manches nur über komplizierte Umwege geht, wobei manchmal sogar Unix- bzw. Linux-Tools aus dem Environment nötig sind. GNU-Makefiles taugen daher maximal als Legacy-Format oder als Nischenlösung (z.B. für ein bestimmtes Projekt, dessen Übersetzung stets mit GNU-Make gesteuert werden soll, da setze ich das auch selber ein). Das heißt, dass die Linux-Frickler meinetwegen damit weitermachen können, aber dass ich, für meinen Teil, nicht dazu bereit bin, deutlich unterkomplexe Tools für ein komplexes Problem einzusetzen.

    Zwar bin ich inzwischen darin geübt, mit nackten Makefiles zu arbeiten, auch für den Compiler von Microsoft (cl.exe etc.), da ich sowohl mit Make als auch mit den Compilerswitches umgehen kann, und es wäre auch hier ganz witzig, um das alles von Visual Studio zu entkoppeln und den reinen Compiler einzusetzen, aber ich will mir die Hose nicht mit der Kneifzange anziehen müssen. Ich finde es viel eleganter, von vornherein die Sprache eines Generators zu verwenden, um den diverse Buildskripte generieren zu lassen. Für mich ist das Pferd nur so richtig herum aufgezäumt, weil ich nur so eine einzige Sprache mit der Maschine sprechen muss, woraufhin diese dann diverse Zwischensprachen, die ich nicht alle lesen will, generieren soll. Sonst ist das für mich keine Automatisierung. Gegen einen alternativen Makefile-Output spricht dabei, solange es machbar ist, nichts. Ich will ihn bloß nicht von Hand schreiben müssen, um mir dann auch noch eine Transformation überlegen zu müssen (das falsch herum aufgezäumte Pferd). Das würde niemals mit irgendwie vertretbarem Aufwand unter allen Umständen (von Spezialfällen will man weg, aber sie existieren auf unterer Ebene, und nur dort gehören sie hin) einen gescheiten Output ergeben, andersherum (z.B. mit CMake als zentraler Generator) durchaus.

    Der Witz an der Sache ist ja, dass Makefiles zwar gut Abhängigkeiten abbilden können, aber dass man sie wegen Fehlens einiger für Menschen sinnvoller Ausdrucksmöglichkeiten und wegen gewisser tatsächlicher Einschränkungen nicht zur zentralen Steuerung benutzen will. In der Objektorientierung leitet man auch nicht von Spezialisierung eine Generalisierung ab. Das meine ich im übertragenen Sinn, also nicht so, dass Makefiles nicht generalisieren können, sondern dass die Ausdrucksmittel von Makefiles für den menschlichen Leser zu arm sind. Dadurch ergeben ich nämlich bereits für simple Aufgaben unüberschaubare Konstrukte, mit der inhärenten Gefahr, dass diese ungewollt speziell werden, um die Aufgabe irgendwie gelöst zu bekommen. Und die will ich nicht warten müssen, sondern die zentrale Stelle, die über bessere Ausdrucksmittel verfügt. Die darf dann gerne nebenher auch, als eine von vielen Varianten, ein für mich unübersichtlicheres, Makefile produzieren. Gut an GNU-Makefiles sind die wenigen simplen Regeln, dafür kann man sie mögen. Schlecht daran ist, welcher Wust daraus manchmal entsteht.

    Mit den Details befasse ich mich durchaus, und zwar einmal exemplarisch, um diese zu optimieren, z.B. im GUI von Visual Studio oder, wo kein VS benutzt wird, als Parameter für den Compiler innerhalb eines Makefiles. Dann gehört das aber, generisch zusammengesetzt oder über eine Weiche, in das CMake-Skript eingepflegt, sodass der nächste CMake-Output diese Optionen dann bereits enthält, sodass das Nachfrickeln entfällt. So hatte ich es eigentlich von Anfang an erwartet, und zwar für sämtliche Builds!

    Die Details hängen ja wiederum von anderen Details ab, und da sind wir eben bei Abhängigkeitenrattenschwänzen, weswegen man das automatisiert haben will. Hunderte kollaborative "Inder", wie man sie für manuelles Nachfrickeln je Ausprobieren einer Konfigurationsoption bräuchte, kann ich nicht bezahlen. Außerdem müssten die sich erst einmal abstimmen. So oder so würde das nie etwas werden, weder bei einem, bei zwanzig, noch bei tausend "Indern". Und wenn sie fertig sind, müssten sie mit Fehlerkontrollen anfangen, aber bitte mit einem Kontrolleur je "Inder", um zu gewährleisten, dass der nicht versehentlich oder absichtlich bloß abnickt, was er sieht.

    Natürlich bin ich mein ganz persönlicher "Inder", der irgendwann den Erschöpfungstod stirbt oder zumindest daran verzweifelt, dass er ohne geschlafen zu haben, den Tag nicht durchsteht. So geht es also nicht. Trotzdem sind die meisten Projekte so schlimm ausgelegt. Man muss viele Stunden, die einem niemand zurückgibt, damit verbringen, bis man tief genug drinsteckt, um zu wissen, wie man es besser macht, um sich dann darüber zu wundern, warum es diejenigen, die bereits so tief drinstecken und es die ganze Zeit über gewusst haben und den geringsten Aufwand gehabt hätten, nicht gleich so gemacht haben. Das mag daran liegen, dass auch bei den Leuten der Tag zu wenige Stunden hat und niemand für die Arbeit zahlt...

    Der ganze Aufwand entsteht vor allem daraus, wie ich mein SDL bauen will, und zwar in allen vorgesehenen Varianten, zumindest unter Windows, flexibel baubar und dabei gut wartbar. Es geht längst nicht mehr darum, eine der Varianten einmal kompilieren zu lassen. Falls Ihr mich so versteht, dass mein Text davon handeln würde, dass etwas nicht zu kompilieren ginge, versteht Ihr ihn falsch. Es geht nicht nur darum, ob man etwas kompilieren kann, wenn man möchte, dass die Entscheidung, ob etwas verwendet wird, zugunsten einer bestimmten Lösung ausfällt. Wenn man Software am Leben erhalten will, gehört mehr dazu, als dass sie in der Nerdstube unter dem Nerdsetup funktioniert. Dass das so schwer begriffen wird, hat mich schon gewundert, als ich vor Jahrzehnten meinen ersten GCC herunterladen wollte. Software ist für Menschen da, sonst hat sie keinen Wert. Und Menschenleben sind verdammt kurz, und zwar viel zu kurz für das Studieren von Nerdchaos.

    Ihr versteht mich richtig, wenn Ihr meint, dass mich das im Kern eher auf einer philosophischen Ebene interessiert. Denn warum sollte speziell SDL für mich so wichtig sein? Ist es nicht. Für mich ist das exemplarisch geeignet, um etwas mehr davon zu verstehen, wie IT zugleich schadet und nützt und welche Tragik dem innewohnt und was man vielleicht tun könnte, um den Schattenseiten beizukommen. Dabei geht es mir nicht darum, ein Projekt schlechtzureden (im Gegenteil!), sondern darum, die Tragik von Komplexität zu durchmessen und zu überlegen, welche Konsequenzen man daraus ziehen könnte. Ohne hin und wieder mal herumzuspielen, ist es schwer, die gesamte Tragweite zu durchmessen. Das ist also eine Ebene über dem Ganzen, hat also nichts mehr damit zu tun, eine Software haben zu wollen und maximalen Nutzen daraus ziehen zu wollen (es sollen aber sehr wohl diejenigen, die meinen, dass es ihnen nützt, können, und zwar mit weniger Aufwand, worum es hier geht). Ich bin mir nicht mehr so wichtig, dass ich unbedingt etwas haben wollte. Aber ich kann mir grob ausmalen, wieviel allgemein von solchen Problemen (die grob dieser Natur sind) abhängt, und zwar viel zu viel. Das ist so die Ebene, die mich doch noch ein wenig interessiert.
    jabu ist offline Geändert von jabu (13.02.2022 um 10:21 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •