2012-04-06 2 views
0

У нас есть несколько приложений, которые ссылаются на несколько наших собственных библиотек. Недавно я добавил новое приложение, которое ссылается на эти библиотеки, и это успешно компилируется в Windows.Почему «неопределенная ссылка», когда переменная определена и связана с библиотекой?

Однако в Linux я вижу ошибку «неопределенной ссылки» для статической переменной, что, конечно, означает, что переменная не была определена. Ошибка возникает в библиотеке, но только при подключении к новому приложению (существующие приложения по-прежнему привязываются отлично).

Как вы можете видеть, компилятор говорит, что kAppVersion не определен. Фактически это определено в Version.cpp, а общее связано (указано в CMakeLists.txt). Мы думали, что это может быть связано с заказом target_link_libraries, но перемещение common до base (где происходит ошибка) не оказывает никакого эффекта. Кроме того, в другом CMakeLists.txt (например, для синергии) упорядочение, по-видимому, не имеет значения, так как это приложение успешно компилируется. Это аналогичный вопрос, как представляется, намекают, что вопросы упорядочения, но я не имел никакого успеха с этим:

Qustion: library is linked but reference is undefined

Моя единственная идея заключается в том, что это может быть что-то неправильно в synergyd.cpp или CDaemonApp.cpp - но я не может видеть ничего очевидного, что компилируется в Linux, но не в 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 

Полный код может быть просмотрен от our repository.

ответ

2

Прежде всего, порядок связывания имеет значение, по крайней мере, с g ++. Если A использует символы из B, то B следует упомянуть после A: g++ ... -lA -lB

Я также вижу undefined reference to vtable for XExitApp. Эта ошибка означает, что у вас есть виртуальная функция в XExitApp, которая не определена. Если вы не хотите, чтобы определить эту функцию, сделать его чисто виртуальным путем добавления = 0

+0

Я знал, что комментарий о упорядочении приходил, поэтому я провел так много времени на вопрос - как вы можете увидеть, заказав общий перед тем база не исправила проблему. –

+0

Порядок связывания вопросов, если библиотека не связана с помощью параметра ld '-no-as-needed'. –

+0

Я не говорю, что порядок ссылок не имеет значения - прочитайте, что я говорю. Я попытался изменить порядок и не решил проблему. Проблема может быть не обязательно вызвана привязкой порядка в этом случае (если cmake ее каким-то образом меняет). –

0

Единственное, что я заметил, что вы пропали без вести «../../lib/synergy» в set(inc... разделе /synergyd/CMakeLists.txt , Неважно, относится ли это к проблеме, я могу только догадываться.

Все ошибки ссылок, которые вы получаете, по-видимому, связаны с тем, что компоновщик не находит символ, который он ищет. Обычными причинами этого является то, что соответствующий .o-файл не существует, не включен в сборку или не скомпилирован неправильно.

Я бы начал с очистки, изменив файл CMakeList.txt, чтобы как можно больше соответствовать известной рабочей версии и перестраивать все с включенным всеми компиляторами/предупреждениями. Если это не сработает (одинаковые ошибки или разные ошибки), я бы посмотрел более внимательно на то, что работает и не работает. Вы сказали, что Windows build работает, но Linux нет. Каковы различия между ними и какие из них могут объяснить проблему. Аналогично одному подобному проекту, который работает правильно: каковы различия между этими двумя проектами.

+0

Я считаю, что эта строка неверна -> вам не хватает "../../lib/synergy" Кроме того, спасибо, но я понимаю ошибку компоновщика, и я понять, что * может быть причиной ... но, как вы можете видеть, решение не очевидно (вероятно, почему вы не можете его решить). –

+0

Пожалуйста, см. Мой ответ для фактического решения. Спасибо, в любом случае. –

3

Реальная проблема в общем: Циклическая зависимость между arch и synergy. Кроме того, base фактически не был связан с библиотекой common (в CMakeLists.txt для base).

Интересно, что это вызвано проблемой конфигурации в файлах CMakeLists.txt для библиотек. Это не имело никакого отношения к CMakeLists.txt для нового приложения synergyd, которое я добавил.

Проблема была в том, что я не связывал библиотеки друг с другом, где новые вызовы были добавлены в классы в других библиотеках. Однако, похоже, что теперь существует проблема с круговой связью.

Например, я мог бы добавить ...

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

... к CMakeLists.txt в arch библиотеки, а arch теперь называют что-то в synergy библиотеки. Но это неверно, так как synergy уже звонит что-то в arch.

Видимо, это не имеет значения для Windows.

Я не совсем уверен, но почему это произошло, поскольку все это старый код, который раньше компилировался и до сих пор работает в других приложениях. Я подозреваю, что, скорее всего, что-то связано с недавним удалением плиты котла из CArch, а не с тем, что делает CDaemonApp (или, может быть, даже комбинацией того и другого).

Update

Только в случае, если кто-то заботится ;-) - Я думаю, что это что-то делать с отношениями между паршивой круговой зависимости между библиотекой arch и synergy, в сочетании с тем, что CDaemonApp.cpp не включая CApp.h - это означает, что он был включен в какой-то другой момент, вызывая странные неопределенные эталонные ошибки.

Чтобы решить эту проблему, я удалил круговую зависимость, которая, по-видимому, была ядром проблемы.

Update 2

код теперь полностью компилирует, ура!

я все еще видим одну последнюю ошибку (тема этого вопроса):

[ 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 

Это было просто, вызванное base библиотека не ссылки на common библиотеки. Добавление следующий код в файл CMakeLists.txt для базы исправил:

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

Все еще не уверены, почему именно это начало происходить, только рад, что это исправлено.

Update 3

И вот коммита: r1354

Смежные вопросы