2012-04-06 117 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.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浏览。

回答

2

首先,链接顺序的确很重要,至少在g ++中。如果A使用符号从B,然后B应该A后提到:g++ ... -lA -lB

我还看到一个undefined reference to vtable for XExitApp。此错误表示您在XExitApp中有一个未定义的虚拟功能。如果您不想定义功能,使其纯虚加= 0

+0

我知道排序评论会进来,这就是为什么我花了这么多时间在这个问题上 - 你可以看到,之前订购常见基地没有纠正这个问题。 – 2012-04-06 10:06:54

+0

连接顺序除非库使用ld的'--no-as-needed'选项链接。 – 2012-04-06 10:14:52

+0

我不是说链接顺序无关紧要 - 请阅读我在说什么。我试过改变顺序,但它没有解决问题。这个问题可能不一定是由链接顺序造成的(除非cmake以某种方式改变它)。 – 2012-04-06 22:16:24

0

我发现的唯一的事情是,你错过了“../../lib/synergy”在/synergyd/CMakeLists.txtset(inc...节。这是否与我只能猜到的问题有关。

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

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

+0

我相信这条线是不正确的 - >你错过了“../../lib/synergy” 另外,谢谢,但我明白链接错误,我意识到可能是什么原因......但正如你所看到的,解决方案并不明显(可能为什么你无法解决它)。 – 2012-04-06 22:17:54

+0

请参阅我的答案为实际解决方案。不管怎么说,还是要谢谢你。 – 2012-04-07 00:15:35

3

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

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

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

例如,我可以加...

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

...到的CMakeLists.txt在arch库,arch现在要求在synergy库的东西。但是这是无效的,因为synergy已经调用arch

显然这在Windows上并不重要。

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

更新

万一有人关心;-) - 我认为这是值得做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库造成的。添加以下代码解决了这个为基地的CMakeLists.txt文件:

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

还没确定到底为什么会开始发生,只是很高兴它的固定。

更新3

而这里的承诺:r1354