为什么在定义变量并链接库时“未定义引用”?

时间:2012-04-06 09:55:34

标签: c++ compiler-errors cmake

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

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

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

Qustion:library is linked but reference is undefined

我唯一的想法是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

可以从our repository浏览完整代码。

3 个答案:

答案 0 :(得分:3)

真正的问题: archsynergy之间的循环库依赖关系。另外,base实际上没有链接到common库(在base的CMakeLists.txt中)。

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

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

例如,我本可以添加...

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

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

显然这在Windows上无关紧要。

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

更新

以防万一有人关心;-) - 我认为这与archsynergy之间糟糕的循环库依赖关系之间的关系,以及{{1 }}不包括CDaemonApp.cpp - 意味着它包含在其他某个点,导致奇怪的未定义引用错误。

为了妥善解决这个问题,我已经删除了循环依赖,这似乎是问题的核心。

更新2

代码现在完全编译,欢呼!

我仍然看到最后一个错误(这个问题的主题):

CApp.h

这只是由[ 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库引起的。将以下代码添加到CMakeLists.txt文件中以修复此问题:

common

仍然不确定为什么会这样开始发生,只是很高兴它已经修好了。

更新3

这是提交:r1354

答案 1 :(得分:2)

首先,链接的顺序确实很重要,至少与g ++有关。如果A使用B中的符号,则应在B之后提及Ag++ ... -lA -lB

我也看到undefined reference to vtable for XExitApp。此错误表示您在XExitApp中有一个未定义的虚函数。如果您不想定义该功能,请通过添加= 0

使其成为纯虚拟

答案 2 :(得分:0)

我唯一注意到的是你在set(inc...的{​​{1}}部分中遗漏了“../../lib/synergy”。这是否与问题相关我只能猜测。

您获得的所有链接错误似乎是由于链接器未找到它正在查找的符号。通常的原因是相关的.o文件不存在,未包含在构建中,或者编译不正确。

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