Statisch linken mit SFML - gelöst



  • Hi Ihr,

    ich wollte mal mit SFML experimentieren, habe aber ein Problem mit dem linken:

    Ich hab mir das aktuelle SFML - ZIP-File (V2.5.1) für Windows für meinen VS-Version (C/C++-Optimierungscompiler Version 19.00.24215.1 für x64) runtergeladen und will das Beispiel SFML\Examples\window neu statisch erstellen.
    Ich habe das cpp-File kopiert und als test.cpp gespeichert.

    Mein makefile sieht so aus:

    CPP = cl.exe
    PROG = test
    
    INCLUDE = $(INCLUDE)D:\Entwicklung mit MS\SFML\include
    LIB = $(LIB)D:\Entwicklung mit MS\SFML\lib
    
    ALL : $(PROG).exe
    
    LINK32 = link.exe
    LINK32_FLAGS = /nologo opengl32.lib winmm.lib advapi32.lib user32.lib gdi32.lib \
      sfml-window-s.lib sfml-system-s.lib sfml-graphics-s.lib /out:$(PROG).exe 
    
    $(PROG).exe: $(PROG).obj
        $(LINK32) $(PROG).obj $(LINK32_FLAGS)
    
    $(PROG).obj: $(PROG).cpp
        $(CPP) /EHsc /DSFML_STATIC /c $(PROG).cpp
    

    Ich kriege eine Menge Linker-Meldungen/Fehler, schon die erste kann ich nicht lösen, deshalb bin ich nicht sicher, ob die weiteren nicht Folgefehler sind:

    sfml-window-s.lib(VideoMode.cpp.obj) : error LNK2038: Konflikt ermittelt für "RuntimeLibrary": Der Wert 
    "MD_DynamicRelease" stimmt nicht mit dem Wert "MT_StaticRelease" in test.obj überein.
    

    Laut Doku sollten die ...-s.lib - Files für das statische Linken geeignet sein 🤔
    Was mach ich falsch?





  • @Th69
    Ich hab am n dumpbin auf mein obj-File und auf die sfml-window-s.lib gemacht:
    mein obj-File:

    ...
       Linker Directives
       -----------------
       /FAILIFMISMATCH:_MSC_VER=1900
       /FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0
       /FAILIFMISMATCH:RuntimeLibrary=MT_StaticRelease
       /DEFAULTLIB:libcpmt
       /FAILIFMISMATCH:_CRT_STDIO_ISO_WIDE_SPECIFIERS=0
       /DEFAULTLIB:uuid.lib
       /DEFAULTLIB:uuid.lib
       /DEFAULTLIB:LIBCMT
       /DEFAULTLIB:OLDNAMES
    ...
    

    das lib-File:

    
    ...
       Linker Directives
       -----------------
       /FAILIFMISMATCH:_MSC_VER=1900
       /FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0
       /FAILIFMISMATCH:RuntimeLibrary=MD_DynamicRelease
       /DEFAULTLIB:msvcprt
       /FAILIFMISMATCH:_CRT_STDIO_ISO_WIDE_SPECIFIERS=0
       /DEFAULTLIB:uuid.lib
       /DEFAULTLIB:uuid.lib
       /DEFAULTLIB:MSVCRT
       /DEFAULTLIB:OLDNAMES
    ...
    

    Das sieht mir so aus, als ob die lib nicht für statisches Linken geeignet ist?
    Denn die richtige Runtime-Library für statisch gelinkte Projekte sollte doch die in meinem obj-File vorgesehen libcmt sein?



  • Okay, Problem gelöst:
    Ich kompiliere mein cpp-File mit dem Schalter /MD, dann funktionierts ...
    Wundert mich allerdings, denn ich dachte, dieser Schalter ist gerade NICHT für das statische Linken gedacht 🤔



  • Vielleicht geht's eben darum, dass SFML mit dieser C-runtime dynamisch verlinkt ist, und nur der SFML-Code selber statisch in deine EXE verlinkt wird (bin mir nicht sicher, habe da eher Halbwissen ^^). Wenn Dich das stört,kannst Du SFML auch selbst kompilieren (mit CMake). Das geht relativ einfach sobald man es mal gemacht hat.

    Hier hatte jemand auch das Problem, wenn ich es richtig interpretiere.



  • @Belli sagte in Statisch linken mit SFML - gelöst:

    Okay, Problem gelöst:
    Ich kompiliere mein cpp-File mit dem Schalter /MD, dann funktionierts ...
    Wundert mich allerdings, denn ich dachte, dieser Schalter ist gerade NICHT für das statische Linken gedacht 🤔

    Der Schalter bestimmt wie die C++ Runtime von MSVC gelinkt werden soll und hat nichts mit dem statischen linken von SFML an sich zu tun.

    Wenn dein Programm statisch gegen eine externe Library linken möchte, welche in C++ geschrieben ist, dann muss dein Programm gegen die gleiche Version der C++ Runtime gelinkt werden wie die Library.
    Ansonsten gibt es chaos (z.b. unerklärliche Abstürze)



  • @firefly sagte in Statisch linken mit SFML - gelöst:

    Wenn dein Programm statisch gegen eine externe Library linken möchte, welche in C++ geschrieben ist, dann muss dein Programm gegen die gleiche Version der C++ Runtime gelinkt werden wie die Library.
    Ansonsten gibt es chaos (z.b. unerklärliche Abstürze)

    Ja, das habe ich soweit verstanden ...
    Heißt das nun, SFML ist jetzt zwar statisch gelinkt, die C++ Runtime - Lib aber nicht, so dass das Programm auf einem Rechner ohne VS nicht läuft - es sei denn, die C++ Runtime - Lib ist auf irgendeinem anderen Weg auf den Rechner gelangt?



  • @HarteWare sagte in Statisch linken mit SFML - gelöst:

    Vielleicht geht's eben darum, dass SFML mit dieser C-runtime dynamisch verlinkt ist, und nur der SFML-Code selber statisch in deine EXE verlinkt wird (bin mir nicht sicher, habe da eher Halbwissen ^^). Wenn Dich das stört,kannst Du SFML auch selbst kompilieren (mit CMake). Das geht relativ einfach sobald man es mal gemacht hat.

    Mal sehen, ich hab mir CMake nun das erste Mal angesehen, so ganz trivial scheint mir das nicht zu sein, aber vielleicht nehme ich das mal in Angriff, einfach aus akademischem Interesse ...



  • @Belli

    Ich probiers mal schnell aus für VS2019:

    • VS19 starten -> "Code klonen oder auschecken" -> "https://github.com/SFML/sfml" klonen

    • Standardmäßig habe ich dann eine x64-Debug Konfiguration, welche VS19 automatisch erstellt - damit kann man arbeiten.

    • Aus VisualStudio: [Projekt] -> "CMake-Einstellungen für SFML", hier sollte Konfigurationstyp: Debug sein, weiter unten "CMake-Variablen und -Cache", hier häckchen bei BUILD_SHARED_LIBS=FALSE weg und setzen bei SFML_USE_STATIC_STD_LIBS=TRUE. Speichern und dann [Erstellen] -> "Alle Erstellen"

    • Dann wieder [Projekt] -> "CMake-Einstellungen für SFML", jetzt lediglich Konfigurationstyp: auf Release umstellen, speichern, nochmals [Erstellen] -> "Alle Erstellen". Nicht verwirren lassen, dass unsere Konfiguration immernoch x64-Debug heißt - es zählen die CMake Variablen (CMAKE_BUILD_TYPE).

    • Jetzt sollte in CMAKE_INSTALL_PREXIF (Pfad) ein Ordner "lib" sein mit allen SFML libs. Jetzt muss man halt noch mühsam alle libs+deps linken wie davor, aber jetzt mit /MT bzw. /MTd. Bei mir war standardmäßig der Pfad C:\Users\HarteWare\Source\Repos\sfml\out\build\x64-Debug\lib entsprechend wurde das Projekt in C:\Users\HarteWare\Source\Repos\sfml geklont.

    So viel zu Visual Studio bzw. Windows. Optimal wäre natürlich, den ganzen Prozess zu automatisieren, aber hab keine Lust so ein Skript zu schreiben gerade (bzw. hatte ich schonmal, aber für MSYS2). Sieht ca. so aus:

    cd "PathToSFML"
    git pull
    mkdir -p build
    cd build
    cmake .. -G"MSYS Makefiles" -DSFML_USE_STATIC_STD_LIBS=TRUE -DBUILD_SHARED_LIBS=FALSE -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX -DCMAKE_BUILD_TYPE=Debug
    make -j
    make install
    # Für CMAKE_BUILD_TYPE=Release analog
    

    Bei Visual Studio muss man ja irgendwie immer diese Developer Konsole verwenden [Extras] -> "Befehlszeile", damit die Toolchain Pfade passen.



  • @HarteWare
    Vielen Dank für die Hinweise!
    Ich muss mal schauen, ich hab die IDE vom VS noch nie benutzt 🙃
    Ich schreib meinen Code normalerweise in einem Editor und erstelle mein Programm aus der Konsole via cl .... oder aber ich schreibe ein makefile ...
    Naja, ich mach das ganze allerdings auch nur aus Spaß an der Freude.

    Du siehst ja weiter oben, wie mein makefile so prinzipiell aussieht ... Gestern habe ich mal für das gleiche Progrämmchen CMake ein makefile machen lassen wollen ... mal davon abgesehen, dass ich ewig gebraucht hatte, bis ich die ersten Einstiegshürden überwunden hatte (wie gibt man CMake include/lib - Verzeichnisse oder Makros mit), war ich doch sehr überrascht, was für einen Wust an Ordnern und Dateien da erstellt wurden 😆
    Ich fand das ganz interessant, aber doch auch iwie abschreckend ...


Log in to reply