2012-04-06 7 views
0

Wir haben ein paar Anwendungen, die zu mehreren unserer eigenen Bibliotheken verlinken. Ich habe kürzlich eine neue Anwendung hinzugefügt, die auf diese Bibliotheken verweist, und dies wird erfolgreich unter Windows kompiliert.Warum "nicht definierte Referenz", wenn die Variable definiert und die Bibliothek verknüpft ist?

Unter Linux sehe ich jedoch eine "undefined Referenz" Fehler auf eine statische Variable, was natürlich bedeutet, dass die Variable nicht definiert war. Der Fehler tritt in einer Bibliothek auf, aber nur, wenn er mit der neuen Anwendung verknüpft ist (die vorhandenen Anwendungen sind immer noch gut verlinkt). Wie Sie sehen können, sagt der Compiler, dass kAppVersion nicht definiert ist. Wenn es tatsächlich in Version.cpp definiert ist, und gemeinsame ist verknüpft (in CMakeLists.txt angegeben). Wir dachten, dass es etwas mit target_link_libraries Bestellung zu tun, aber common zu vor base (wo der Fehler auftritt) hat keine Wirkung scheint es. Außerdem scheint die Reihenfolge in anderen CMakeLists.txt (z. B. für Synergys) irrelevant zu sein, da diese Anwendung erfolgreich kompiliert wird. Diese ähnliche Frage scheint, dass Ordnungsfragen andeuten, aber ich habe keinen Erfolg damit hatte:

qustion: library is linked but reference is undefined

Meine einzige Idee ist, dass es etwas falsch in synergyd.cpp oder CDaemonApp.cpp sein könnte - aber ich kann nichts Offensichtliches sehen, das unter Linux kompiliert, aber nicht unter Windows.

Scanning dependencies of target synergyd 
[ 90%] Building CXX object src/cmd/synergyd/CMakeFiles/synergyd.dir/synergyd.o 
Linking CXX executable ../../../../../bin/debug/synergyd 
../../../../../lib/debug/libarch.a(CArch.o): In function `~XExitApp': 
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/../synergy/XSynergy.h:114: undefined reference to `vtable for XExitApp' 
../../../../../lib/debug/libarch.a(CArch.o): In function `CArchAppUtil::exitApp(int)': 
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtil.h:31: undefined reference to `XExitApp::XExitApp(int)' 
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtil.h:31: undefined reference to `typeinfo for XExitApp' 
../../../../../lib/debug/libarch.a(CArchAppUtilUnix.o): In function `CArchAppUtilUnix::parseArg(int const&, char const* const*, int&)': 
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtilUnix.cpp:32: undefined reference to `CApp::isArg(int, int, char const* const*, char const*, char const*, int)' 
/srv/buildbot/synergy/1.4-linux32/build/src/lib/arch/CArchAppUtilUnix.cpp:37: undefined reference to `CApp::isArg(int, int, char const* const*, char const*, char const*, int)' 
../../../../../lib/debug/libbase.a(CLog.o): In function `CLog::insert(ILogOutputter*, bool)': 
/srv/buildbot/synergy/1.4-linux32/build/src/lib/base/CLog.cpp:213: undefined reference to `kAppVersion' 
collect2: ld returned 1 exit status 
make[2]: *** [../../bin/debug/synergyd] Error 1 
make[1]: *** [src/cmd/synergyd/CMakeFiles/synergyd.dir/all] Error 2 
make: *** [all] Error 2 

Der vollständige Code kann von our repository durchsucht werden.

Antwort

2

Zunächst ist die Reihenfolge der Verknüpfung wichtig, zumindest mit g ++. Wenn A Symbole aus B verwendet, dann B sollte nach A genannt: g++ ... -lA -lB

ich auch eine undefined reference to vtable for XExitApp sehen. Dieser Fehler bedeutet, dass Sie eine virtuelle Funktion in XExitApp haben, die nicht definiert ist. Wenn Sie nicht über diese Funktion definieren wollen, machen es zu virtuellen rein durch Zugabe = 0

+0

Ich habe einen Kommentar zur Bestellung wusste kommen würde, weshalb ich so viel Zeit in der Frage verbracht - wie Sie sehen können, Bestellung gemeinsam vor Base hat das Problem nicht behoben. –

+0

Die Reihenfolge der Verknüpfung ist wichtig, es sei denn, die Bibliothek ist mit der Option '--no-as-needed' von ld verknüpft. –

+0

Ich sage nicht, dass Reihenfolge der Verknüpfung nicht wichtig ist - bitte lesen Sie, was ich sage. Ich habe versucht, die Reihenfolge zu ändern und es hat das Problem nicht gelöst. Das Problem wird möglicherweise nicht durch die Verknüpfungsreihenfolge in diesem Fall verursacht (es sei denn, CMake ändert es irgendwie). –

0

Das einzige, was mir auffiel, war, dass du verpasst „../../lib/synergy“ im set(inc... Abschnitt /synergyd/CMakeLists.txt . Ob das für das Thema relevant ist, kann ich nur raten.

Alle Verbindungsfehler, die Sie bekommen, scheinen zu sein, weil der Linker das gesuchte Symbol nicht findet. Die üblichen Gründe dafür sind, dass die relevante .o-Datei nicht existiert, nicht im Build enthalten ist oder falsch kompiliert wird.

Ich würde mit der Reinigung beginnen und die CMakeList.txt-Datei so ändern, dass sie der bekannten funktionierenden Version entspricht, und alles mit allen aktivierten Compiler/Warnungen neu erstellen. Wenn das nicht funktioniert (entweder die gleichen Fehler oder verschiedene Fehler), würde ich genauer untersuchen, was funktioniert und was nicht. Sie sagten, der Windows-Build funktioniert, aber der Linux-Build funktioniert nicht. Was sind die Unterschiede zwischen den beiden und welche davon könnten das Problem erklären? Ähnlich verhält es sich mit dem einen ähnlichen Projekt, das richtig baut: Was sind die Unterschiede zwischen den beiden Projekten?

+0

Ich glaube, diese Zeile ist falsch -> du vermisst "../../lib/synergy" Auch danke, aber ich verstehe den Linker-Fehler, und ich merke, was * die Ursache sein könnte ... aber wie du sehen kannst, ist die Lösung nicht offensichtlich (wahrscheinlich, warum du es auch nicht lösen kannst). –

+0

Bitte sehen Sie meine Antwort für die tatsächliche Lösung. Danke trotzdem. –

3

Wirkliches Problem in Kürze: Kreisbibliothek Abhängigkeit zwischen arch und synergy. Auch wurde base eigentlich nicht zu common Bibliothek verknüpft (im CMakeLists.txt für base).

Interessanterweise wurde dies durch ein Konfigurationsproblem in den CMakeLists.txt-Dateien für die Bibliotheken verursacht. Dies hatte nichts mit der CMakeLists.txt für die neue synergyd Anwendung zu tun, die ich hinzugefügt hatte.

Das Problem war, dass ich die Bibliotheken nicht miteinander verknüpfte, wo neue Aufrufe zu Klassen in anderen Bibliotheken hinzugefügt wurden. Es scheint jedoch ein Problem mit der zirkulären Verknüpfung zu bestehen.

Zum Beispiel habe ich hinzugefügt ...

if (UNIX) 
    target_link_libraries(arch synergy) 
endif() 

... zu CMakeLists.txt in der arch Bibliothek haben könnte, wie arch jetzt etwas in der synergy Bibliothek aufruft. Aber das ist ungültig, da synergy bereits etwas in arch anruft.

Scheinbar spielt dies unter Windows keine Rolle.

Ich bin nicht ganz sicher, obwohl, was verursacht, dass es zu geschehen beginnt, da es alles alte Code ist, der vorher fein kompiliert worden ist und noch in anderen Anwendungen tut. Ich vermute sehr wahrscheinlich etwas mit der kürzlichen Entfernung der Kesselplatte von CArch zu tun, anstatt etwas, das CDaemonApp macht (oder vielleicht sogar eine Kombination von beiden).

aktualisieren

Für den Fall, jemand kümmert sich ;-) - Ich denke, es ist etwas, mit dem Verhältnis zwischen der lausigen Kreis Bibliothek Abhängigkeit zwischen arch und synergy, kombiniert mit der Tatsache zu tun, dass CDaemonApp.cpp war nicht inklusive CApp.h - was bedeutet, dass es an einem anderen Punkt eingefügt wurde, was die seltsamen undefinierten Referenzfehler verursacht.

Um dies richtig zu lösen, habe ich die zirkuläre Abhängigkeit entfernt, die den Kern des Problems zu sein schien.

Update 2

Der Code jetzt kompiliert voll, hurra!

ich noch sah einen letzten Fehler (das Thema dieser Frage):

[ 90%] Building CXX object src/cmd/synergyd/CMakeFiles/synergyd.dir/synergyd.o 
Linking CXX executable ../../../../../bin/debug/synergyd 
../../../../../lib/debug/libbase.a(CLog.o): In function `CLog::insert(ILogOutputter*, bool)': 
/home/nick/Projects/synergy/branches/1.4/src/lib/base/CLog.cpp:213: undefined reference to `kAppVersion' 
collect2: ld returned 1 exit status 
make[2]: *** [../../bin/debug/synergyd] Error 1 
make[1]: *** [src/cmd/synergyd/CMakeFiles/synergyd.dir/all] Error 2 
make: *** [all] Error 2 

Dies wurde einfach durch die base Bibliothek nicht auf die Verknüpfung common Bibliothek. Das Hinzufügen des folgenden Code in die Datei CMakeLists.txt für Basis befestigt diese:

if (UNIX) 
    target_link_libraries(base common) 
endif() 

Immer noch nicht ganz sicher, warum dies geschieht begonnen, nur froh, es behoben ist.

Update 3

Und hier ist der commit: r1354

Verwandte Themen