[SFML] Probleme beim linken statischer Bibliotheken - [Gelöst]
-
Hallo :),
ich versuche mich gerade an den Tutorials für SFML. Hier mal ein kurzer Beispielcode:
//main.cpp #include <SFML/Window.hpp> int main() { sf::Window App(sf::VideoMode(800, 600, 32), "SFML Window"); bool Running = true; while(Running) { App.Display(); } return EXIT_SUCCESS; }
Wenn ich bei den Einstellungen folgendes bei der Visual C++ 2008 Express IDE konfiguriere um die SFML-Bibliotheken dynamisch zu linken, dann lässt sich das Programm auch problemlos ausführen:
Unter Projekt -> Projekteigenschaften -> Konfigurationseigenschaften
Bei C/C++ -> Präprozessor -> Präprozessordefinitionen das Makro SFML_DYNAMIC hinzugefügt
Bei C/C++ -> Codegenerierung -> Laufzeitbibliothek (/MDd) ausgewählt
Bei Linker -> Eingabe -> Zusätzliche Abhängigkeiten die Bibliotheken angeben (für den obigen Beispielcode also sfml-window-d.lib)
Nachdem ich dann noch die entsprechende DLL-Datei in das Verzeichnis der EXE-Datei kopiert habe, läuft das Programm auch. Nun will ich allerdings nicht unbedingt jedesmal die DLL-Dateien hin- und herkopieren, darum dachte ich mir, dass ich die Bibliotheken statisch linke. Wenn ich das allerdings tue, dann kommen bereits beim kompilieren unmengen an Fehlermeldungen. Hier mal ein kurzer Auszug:1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) ist bereits in libcpmtd.lib(stdthrow.obj) definiert. 1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __thiscall std::_Container_base_secure::_Orphan_all(void)const " (?_Orphan_all@_Container_base_secure@std@@QBEXXZ) ist bereits in main.obj definiert. 1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Container_base_secure::~_Container_base_secure(void)" (??1_Container_base_secure@std@@QAE@XZ) ist bereits in main.obj definiert. 1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) ist bereits in libcpmtd.lib(xlock.obj) definiert. 1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) ist bereits in libcpmtd.lib(xlock.obj) definiert. 1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) ist bereits in main.obj definiert.
Weiter unten steht dann noch:
1>LINK : warning LNK4098: Standardbibliothek "MSVCRTD" steht in Konflikt mit anderen Bibliotheken; /NODEFAULTLIB:Bibliothek verwenden. 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall sf::Clock::Clock(void)" (??0Clock@sf@@QAE@XZ)" in Funktion ""public: __thiscall sf::Window::Window(void)" (??0Window@sf@@QAE@XZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall sf::Clock::Reset(void)" (?Reset@Clock@sf@@QAEXXZ)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl sf::Sleep(float)" (?Sleep@sf@@YAXM@Z)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: float __thiscall sf::Clock::GetElapsedTime(void)const " (?GetElapsedTime@Clock@sf@@QBEMXZ)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 4 nicht aufgelöste externe Verweise.
Um die Bibliotheken statisch zu linken, habe ich folgende Einstellungen vorgenommen:
Unter Projekt -> Projekteigenschaften -> Konfigurationseigenschaften
Bei C/C++ -> Präprozessor -> Präprozessordefinitionen das Makro SFML_DYNAMIC wieder entfernt
Bei C/C++ -> Codegenerierung -> Laufzeitbibliothek (/MTd) ausgewählt
Bei Linker -> Eingabe -> Zusätzliche Abhängigkeiten die Bibliotheken angeben (dieses mal die statische Version sfml-window-s-d.lib)Nun frage ich mich was ich beim statischen Linken falsch gemacht haben soll. Ich habe die Anleitung auf der SFML-Website jetzt schon mehrmals studiert und komme einfach nicht dahinter was hier schiefläuft. Vielleicht weiß jemand Rat und kann mir sagen was ich verkehrt gemacht habe. Vielen Dank im voraus dafür :).
-
ich kann dir leider nicht helfen aber ich würde mich bei sfml fragen immer zuerst an das englischsprachige forum wenden, wo laurent dir bestimmt helfen kann
es gibt auch ein deutschsprachiges forumwenns um sfml geht bist du dort wahrscheinlich besser aufgehoben
gruß vom raben
-
Probier mal statt /MTd /MDd aus beim statischen linken. Ich dachte bei den Grundeinstellungen, sei SFML bei der DLL und statischen Bibliothek auf MD eingestellt, also die CRT per DLL.
Grüssli
-
Dravere schrieb:
Probier mal statt /MTd /MDd aus beim statischen linken. Ich dachte bei den Grundeinstellungen, sei SFML bei der DLL und statischen Bibliothek auf MD eingestellt, also die CRT per DLL.
Grüssli
Wenn ich auf /MDd umstelle erhalte ich leider immernoch Fehlermeldungen beim kompilieren:
1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall sf::Clock::Clock(void)" (??0Clock@sf@@QAE@XZ)" in Funktion ""public: __thiscall sf::Window::Window(void)" (??0Window@sf@@QAE@XZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall sf::Clock::Reset(void)" (?Reset@Clock@sf@@QAEXXZ)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl sf::Sleep(float)" (?Sleep@sf@@YAXM@Z)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: float __thiscall sf::Clock::GetElapsedTime(void)const " (?GetElapsedTime@Clock@sf@@QBEMXZ)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 4 nicht aufgelöste externe Verweise.
Das sind aber immerhin schonmal rund 20 Fehlermeldungen weniger :). Vielleicht bringts ja was wenn ich die DLL-Dateien einfach mal neukompiliere. Ich melde mich wieder mit dem Ergebnnis :).
-
Mizar schrieb:
Vielleicht bringts ja was wenn ich die DLL-Dateien einfach mal neukompiliere. Ich melde mich wieder mit dem Ergebnis :).
Hmmm... ok, es hat zwar ein paar Minuten gedauert und die DLL-Dateien ließen sich auch alle ohne Fehlermeldungen neukompilieren, als ich allerdings nun nochmal versucht habe den obigen Beispielcode mit statisch gelinkten Bibliotheken zu kompilieren, traten erneut die gleichen Fehler auf :(. Nun gut, jetzt bin ich mit meinem Latein vollkommen am Ende. Ich werde mal ravenhearts Rat beherzigen und mich beim SFML-Forum umhören. Dennoch, falls hier jemand noch eine Möglichkeit sieht wie man das Problem lösen könnte, dann immer her damit :).
-
Sag mal, könnte es sein, dass du vergessen hast die
sfml-system-s-d.lib
hinzuzufügen? Das würde denke ich noch passen.Grüssli
-
Die sfml-system-s-d.lib hatte ich tatsächlich nicht mit dabei. Wenn ich jetzt bei
Linker -> Eingabe -> Zusätzliche Abhängigkeiten sfml-system-s-d.lib und sfml-window-s-d.lib
dastehen habe, dann verschwinden zumindest diese Fehlermeldungen:1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall sf::Clock::Clock(void)" (??0Clock@sf@@QAE@XZ)" in Funktion ""public: __thiscall sf::Window::Window(void)" (??0Window@sf@@QAE@XZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall sf::Clock::Reset(void)" (?Reset@Clock@sf@@QAEXXZ)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl sf::Sleep(float)" (?Sleep@sf@@YAXM@Z)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 1>sfml-window-s-d.lib(Window.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: float __thiscall sf::Clock::GetElapsedTime(void)const " (?GetElapsedTime@Clock@sf@@QBEMXZ)" in Funktion ""public: void __thiscall sf::Window::Display(void)" (?Display@Window@sf@@QAEXXZ)". 4 nicht aufgelöste externe Verweise.
Dennoch habe ich noch 22 Fehlermeldungen der folgenden Art:
1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) ist bereits in libcpmtd.lib(stdthrow.obj) definiert. 1>msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "public: void __thiscall std::_Container_base_secure::_Orphan_all(void)const " (?_Orphan_all@_Container_base_secure@std@@QBEXXZ) ist bereits in main.obj definiert.
Sowie diese Warnung:
1>LINK : warning LNK4098: Standardbibliothek "MSVCRTD" steht in Konflikt mit anderen Bibliotheken; /NODEFAULTLIB:Bibliothek verwenden.
Wenn ich mich an dieser Warnung orientiere und bei
Linker -> Eingabe -> Standardbibliotheken ignorieren Ja(/NODEFAULTLIB)
einstelle, dann werden aus den rund 20 Fehlermeldungen plötzlich über 200 Fehlermeldungen :(.
-
Ehm, war nicht auch
sfml-main-d.lib
etwas, was man immer drin haben sollte? Bin mir da jetzt nicht mehr sicher.
Die restlichen 22 Fehler ähneln aber wieder verdammt stark denen, welche du vorhin eliminiert hast. Also /MDd richtig eingestellt? Es muss immer für alle Bibliotheken, welche du linkst, die gleiche CRT verlinkt sein. Also wenn /MDd, dann alle /MDd, wenn /MTd, dann alle /MTd, wenn /MD, dann alle /MD und wenn /MT dann alle /MT.Edit:
Die Warnung ruhig ignorierenGrüssli
-
Ok, wenn ich auf /MDd umstelle dann kompiliert das ganze. Zwar gibt der Debugger 11 Warnungen aus, aber es kompiliert und lässt sich auch ausführen. Wenn ich noch die sfml-main-d.lib hinzufüge sind es sogar nur noch 8 Warnungen :). Also das klappt schonmal.
Was ich mich jetzt noch frage ist folgendes:
Wenn ich die EXE-Datei des Codes auf einem anderen Rechner ausführen möchte, müsste ich dann noch weitere Dateien der EXE-Datei "beilegen" oder sollte allein die EXE-Datei reichen? Weil ich dachte immer das ich /MTd (bzw. /MT für die Releaseversion) bei der Laufzeitbibliothek einstellen muss, damit sich die EXE-Datei auf einem anderem Rechner ausführen lässt.
-
Zu den Warnungen:
Wenn du die zeigen würdest, könnte man dir vielleicht auch bei denen noch weiterhelfen.Zum ausliefern der *.exe:
Wenn man auf /MD eingestellt hat, dann muss man ein vcredist mitgeben. Für Visual 2008 findet man dieses hier:
http://www.microsoft.com/downloads/details.aspx?FamilyID=9b2da534-3e03-4391-8a4d-074b9f2bc1bf&displaylang=enDiese Installation muss ausgeführt werden, bevor man dein Programm ausführen kann. Mit einem Setup geht das auch ganz leicht, dann wird einfach der Installation deines Programmes noch diese Datei gestartet, aus einem tempöreren Ordner heraus. Mit Inno Setup kann man sich sollche Installationsprogramme einfach und gratis erstellen lassen.
Wenn du die CRT lieber auch statisch linken und dadurch vielleicht ganz auf das Setup verzichten willst, dann musst du die SFML Bibliotheken entsprechend auf /MT umstellen und neu kompilieren. Dann kannst du auch in deinem Projekt /MT verwenden.
Wie ich eben sagte, es muss immer alles gleich sein. Alles MT oder alles MD.Grüssli
-
Dravere schrieb:
Zu den Warnungen:
Wenn du die zeigen würdest, könnte man dir vielleicht auch bei denen noch weiterhelfen.Diese Warnungen erscheinen bei mir im Debugger:
1>sfml-window-s-d.lib(Joystick.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(VideoModeSupport.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(WindowImplWin32.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(Context.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(Input.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(VideoMode.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(Window.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären. 1>sfml-window-s-d.lib(WindowImpl.obj) : warning LNK4099: PDB "vc90.pdb" wurde nicht mit "XXX\SFML-1.4-sdk-windows\SFML-1.4\lib\vc2008\sfml-window-s-d.lib" oder an "XXX\Documents\Visual Studio 2008\Projects\SFML-Windowtutorial\Debug\vc90.pdb" gefunden; Objekt wird verknüpft, als ob keine Debuginformationen vorhanden wären.
Dravere schrieb:
Wenn du die CRT lieber auch statisch linken und dadurch vielleicht ganz auf das Setup verzichten willst, dann musst du die SFML Bibliotheken entsprechend auf /MT umstellen und neu kompilieren. Dann kannst du auch in deinem Projekt /MT verwenden.
Wie ich eben sagte, es muss immer alles gleich sein. Alles MT oder alles MD.Grüssli
Hmmm... Also den Teil "SFML Bibliotheken auf /MT umstellen" verstehe ich nicht so ganz. Heißt das, dass ich die SFML Header dafür neukompilieren muss, aber beim neukompilieren die Laufzeitbibliothek auf /MT (bzw. /MTd bei den Debugversionen) umstellen muss, oder meintest du das ganz anders?
Edit: Statts SFML Header meinte ich natürlich SFML Bibliotheken ;).
-
Mizar schrieb:
Hmmm... Also den Teil "SFML Bibliotheken auf /MT umstellen" verstehe ich nicht so ganz. Heißt das, dass ich die SFML Header dafür neukompilieren muss, aber beim neukompilieren die Laufzeitbibliothek auf /MT (bzw. /MTd bei den Debugversionen) umstellen muss, oder meintest du das ganz anders?
Edit: Statts SFML Header meinte ich natürlich SFML Bibliotheken ;).
Genau. Geh im SFML Verzeichnis unter Build/VC2008 dort hast du entsprechende Projekte für VC2008, bzw. einfach die *.sln. Dann alle Bibliotheken von SFML auf /MT, bzw. /MTd umstellen und neu kompilieren.
Durch das kompilieren werden dann auch pdb Dateien erstellt, was dann auch diese Warnungen eliminiert. Laurent verschickt diese irgendwie nie mit, ka wieso, müsste man ihn mal drauf ansprechen.
Grüssli
-
Alles klar, dann habe ich also schonmal gar nicht so verkehrt gelegen. Vielen lieben dank Dravere für deine Mühen :). Jetzt bin ich erstmal restlos aufgeklärt ;).
Edit: So, ich habe jetzt gleich mal alle SFML Bibliotheken mit /MT bzw. /MTd neukompiliert und wieder den eingangs geposteten Code mit der Laufzeitbibliothekseinstellung /MTd kompiliert und siehe da, es sind nun auch alle Warnungen spurlos verschwunden. Danke nochmal Dravere :).