-1

We have a few applications which link to several of our own libraries. I recently added a new application which links to these libraries, and this compiles successfully on Windows.

However, on Linux, I see an "undefined reference" error to a static variable, which of course means that the variable wasn't defined. The error occurs in a library, but only when linked to the new application (the existing applications still link fine).

As you can see, the compiler says that kAppVersion is undefined. When actually it is defined in Version.cpp, and common is linked (specified in CMakeLists.txt). We thought that it may be something to do with target_link_libraries ordering, but moving common to before base (where the error occurs) has no effect it seems. Besides, in other CMakeLists.txt (e.g. for synergys) the ordering appears to be irrelevant, as this application compiles successfully. This similar question appears to hint that ordering matters, but I haven't had any success with this:

Qustion: library is linked but reference is undefined

My only idea is that it could be something wrong in synergyd.cpp or CDaemonApp.cpp -- but I can't see anything obvious that compiles on Linux but not 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

The full code can be browsed from our repository.

Community
  • 1
  • 1
Nick Bolton
  • 38,276
  • 70
  • 174
  • 242

3 Answers3

4

Real problem in short: Circular library dependency between arch and synergy. Also, base actually wasn't linked to common library (in the CMakeLists.txt for base).

Interestingly, this was caused by a configuration problem in the CMakeLists.txt files for the libraries. This had nothing to do with the CMakeLists.txt for the new synergyd application I had added.

The problem was that I did not link the libraries to each other where new calls were added to classes in other libraries. However, it seems that there is now a problem with circular linking.

For example, I could have added...

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

... to CMakeLists.txt in the arch library, as arch now calls something in the synergy library. But this is invalid, since synergy already calls something in arch.

Apparently this doesn't matter on Windows.

I'm not quite sure though what caused this to start happening, as it's all old code that has been compiling fine before, and still does in other applications. I suspect most likely something to do with the recent removal of boiler plate from CArch, rather than something that CDaemonApp is doing (or maybe even a combination of both).

Update

Just in case anyone cares ;-) -- I think it is something to do with the relation between the lousy circular library dependency between arch and synergy, combined with the fact that CDaemonApp.cpp wasn't including CApp.h -- meaning that it was included at some other point, causing the weird undefined reference errors.

To solve this properly, I have removed the circular dependency, which appeared to be the core of the problem.

Update 2

The code now fully compiles, hurrah!

I was still seeing one last error (the topic of this question):

[ 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

This was simply caused by the base library not linking to the common library. Adding the following code to the CMakeLists.txt file for base fixed this:

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

Still not sure exactly why this started happening, just glad it's fixed.

Update 3

And here's the commit: r1354

Community
  • 1
  • 1
Nick Bolton
  • 38,276
  • 70
  • 174
  • 242
2

First off, the order of linking does matter, at least with g++. If A uses symbols from B, then B should be mentioned after A: g++ ... -lA -lB

I also see an undefined reference to vtable for XExitApp. This error means that you have a virtual function in XExitApp that is not defined. If you don't want to define that function, make it pure virtual by adding = 0

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • I knew a comment about ordering would come in, which is why I spent so much time on the issue -- as you can see, ordering common before base did not correct the issue. – Nick Bolton Apr 06 '12 at 10:06
  • Order of linking matters unless the library is linked using ld's `--no-as-needed` option. – Prasoon Saurav Apr 06 '12 at 10:14
  • I'm not saying that order of linking does not matter -- please read what I'm saying. I have tried changing the order and it has not solved the issue. The issue may not necessarily be caused by linking order in this instance (unless cmake is changing it somehow). – Nick Bolton Apr 06 '12 at 22:16
  • @nbolton, did you solve the "undefined reference to vtable" as I said? – Shahbaz Apr 06 '12 at 22:40
  • I am looking at the your repository, searched for `getWhat` and don't find its implementation (for class `XExitApp`) anywhere. First solve it (by either implementing it, or adding `= 0`), maybe some of the other ones go away also. – Shahbaz Apr 06 '12 at 22:45
  • @Shahbaz, yes indeed, thanks. But the same "undefined reference to `kAppVersion'" error still exists. – Nick Bolton Apr 06 '12 at 22:52
  • @Shahbaz, take a look at `src/lib/synergy/XSynergy.cpp` – Nick Bolton Apr 06 '12 at 22:55
  • @Shahbaz, please see my answer for actual solution. Thanks anyway. – Nick Bolton Apr 07 '12 at 00:15
0

The only thing I noticed was that you're missing "../../lib/synergy" in the set(inc... section of /synergyd/CMakeLists.txt. Whether this is relevant to the issue I can only guess.

All the link errors you're getting appear to be due to the linker not finding the symbol it is looking for. The usual reasons for this is that the relevant .o file doesn't exist, isn't included in the build, or is compiled improperly.

I would start by cleaning, changing the CMakeList.txt file to match the known working version as much as possible, and rebuilding everything with all compiler/warnings turned on. If that doesn't work (either the same errors or different errors) I would look more closely at what does and doesn't work. You said the Windows build works but the Linux one doesn't. What are the differences between the two and which of those could explain the issue. Similarly with the one similar project that does build properly: what are the differences between the two projects.

uesp
  • 6,194
  • 20
  • 15
  • I believe this line is incorrect --> you're missing "../../lib/synergy" Also, thanks but I understand the linker error, and I realise what *might* be the cause... but as you can see, the solution is not obvious (probably why you aren't able to solve it either). – Nick Bolton Apr 06 '12 at 22:17
  • Please see my answer for actual solution. Thanks anyway. – Nick Bolton Apr 07 '12 at 00:15