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?
-
Schau mal in LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' in file.obj.
Du mußt auch noch die passende C-Runtime benutzen:/MD
<->/MT
.
-
@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 gedachtDer 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 ...
-
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 beiBUILD_SHARED_LIBS=FALSE
weg und setzen beiSFML_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 inC:\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 ...