0

我们有一些应用程序链接到我们自己的几个库。我最近添加了一个链接到这些库的新应用程序,并且可以在 Windows 上成功编译。

但是,在 Linux 上,我看到一个静态变量的“未定义引用”错误,这当然意味着该变量没有定义。错误发生在库中,但仅在链接到新应用程序时(现有应用程序仍然可以正常链接)。

如您所见,编译器说这kAppVersion是未定义的。实际上它是在Version.cpp中定义的,并且 common 是链接的(在CMakeLists.txt中指定)。我们认为这可能与target_link_libraries排序有关,但移到common之前base(发生错误的地方)似乎没有效果。此外,在其他CMakeLists.txt(例如 synergys)中,排序似乎无关紧要,因为此应用程序编译成功。这个类似的问题似乎暗示订购很重要,但我对此没有任何成功:

Qustion:库已链接,但引用未定义

我唯一的想法是它在synergyd.cppCDaemonApp.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

完整的代码可以从我们的存储库中浏览。

4

3 回答 3

4

简而言之,真正的问题是:arch和之间的循环库依赖synergy。此外, base实际上没有链接到common库(在 CMakeLists.txt 中base)。

有趣的是,这是由库的 CMakeLists.txt 文件中的配置问题引起的。synergyd这与我添加的新应用程序的 CMakeLists.txt 无关。

问题是我没有将库相互链接,新调用被添加到其他库中的类。但是,现在循环链接似乎存在问题。

例如,我可以添加...

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

...到arch库中的 CMakeLists.txt,因为arch现在调用synergy库中的某些内容。但这是无效的,因为synergy已经在arch.

显然这在 Windows 上无关紧要。

我不太确定是什么导致了这种情况开始发生,因为它是以前编译好的所有旧代码,并且在其他应用程序中仍然如此。我怀疑很可能与最近从 CArch 中删除样板有关,而不是 CDaemonApp 正在做的事情(或者甚至可能是两者的结合)。

更新

以防万一有人关心;-)——我认为这与 and 之间糟糕的循环库依赖关系之间的关系有关archsynergy再加上CDaemonApp.cpp不包括的事实CApp.h——这意味着它被包含在其他一些点上,导致奇怪的未定义参考错误。

为了正确解决这个问题,我删除了循环依赖,这似乎是问题的核心。

更新 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库引起的。将以下代码添加到 base 的 CMakeLists.txt 文件中修复了此问题:

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

仍然不确定为什么会发生这种情况,只是很高兴它已修复。

更新 3

这是提交:r1354

于 2012-04-06T23:12:02.950 回答
2

首先,链接的顺序确实很重要,至少在 g++ 中是这样。如果A使用来自 的符号BB则应在 之后提及Ag++ ... -lA -lB

我还看到一个undefined reference to vtable for XExitApp. 此错误意味着您有一个XExitApp未定义的虚函数。如果您不想定义该函数,请通过添加使其成为纯虚拟函数= 0

于 2012-04-06T10:05:11.037 回答
0

我注意到的唯一一件事是您set(inc.../synergyd/CMakeLists.txt. 这是否与我只能猜测的问题有关。

您遇到的所有链接错误似乎都是由于链接器没有找到它正在寻找的符号。造成这种情况的通常原因是相关的 .o 文件不存在、未包含在构建中或编译不正确。

我将首先清理,更改 CMakeList.txt 文件以尽可能匹配已知的工作版本,并在所有编译器/警告打开的情况下重建所有内容。如果这不起作用(相同的错误或不同的错误),我会更仔细地研究什么起作用和不起作用。您说 Windows 构建有效,但 Linux 构建无效。两者之间有什么区别,哪些可以解释这个问题。与正确构建的一个类似项目类似:这两个项目之间有什么区别。

于 2012-04-06T13:29:32.820 回答