2

I have a system, written in C++, that build a bunch of shared libraries and executables that link against these shared libraries (and system libraries). None of the code uses c++11, just ol' school C++ The whole mess was being maintained on an old SUSE Linux 3.0.13, 32 bit machine, with GCC 4.3.4. It comes complete with makefile that build everything. I am in the process of moving the entire system over to Ubuntu 16.04 on a 64 bit processor with gcc 4.8. I have had a few compiler issues to sort out but I'm having a heck of time getting things to link.

All the shares libraries build but when I try to build the executable, I'm getting a lot of "undefined reference" errors. I have verified that the methods and typeinfo from these errors do exist in libraries that are included in the link command (-l), and that the path to these libraries is also included in the link command (-L). I've even created linker maps and verified that the classes and methods showing as "undefined" do exist in the shared libraries.

I manage to sort out some of the "undefined reference" issues by reordering the list of share libraries in the link command but I don't know why that would make a difference since the same makefiles worked fine on SUSE Linux without any need to worry about library order. However, I'm still stuck on a couple of projects. Here's one example:

I have an executable that uses a shared library (called MQWrapper) to provide a wrapper around Linux Message Queues. The project has a single .cpp file that is compiled with the following command:

g++ -DZTRACE -DZDEV -I"." -I"../AppIncludes"  -I"../ZediCommon" \
    -I"../NetworkManagerCommon" -I"../TelitModemDriver" -I"../MQWrapper" \
    -I"../Hardware" -I"../WatchdogLib" -I"../BaseClasses" -O0 -g3 -Wall \
    -c -fmessage-length=0 -fPIC -MMD -MP -MF"Debug/NetworkProcess.d" \
    -o "Debug/NetworkProcess.o" "NetworkProcess.cpp"

It depends on other shared libraries that part of my system. Their location is specified in the link command by a relative path:

g++ -o Debug/networkmanager.1.2.0-DEV  ./Debug/NetworkProcess.o \
   -L../sharedlibs/Debug -lZediCommon -lMQWrapper -lBaseClasses \
   -lorm -lHardware -lWatchdogLib -llog4cplus-1.1 -lNetworkManagerCommon \
   -lpthread -lTelitModemDriver -ldl -lrt 

As you can see, "-lrt" is in the command. Yet, when I try to link, I get these linker errors:

../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_unlink'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_close'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_getattr'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_receive'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_open'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_setattr'
../sharedlibs/Debug/libMQWrapper.so: undefined reference to `mq_send'

I have verify that the librt.so shared library exists and is in the linker's search path. I even built a small test program that uses these function, compiled and linked it and it built fine.

As I said, this is only a sample of some of the "undefined reference" errors but I thought I would use these since they are system and probably easiest to sort out.

Does anyone have any idea why this might be happening? Can someone suggest some debugging tips? Are there difference between SUSE's linker and Ubuntu's linker that might be causing these problems?


Update

The referenced post does give a good explanation of the compiling and linking process and states possible causes, none of which apply to my problem. I've covered all the suggestions.

  1. I am linking against the correct libraries. Specifically, Linux Message Queue functions are implemented in librt.so (or at least they should be) and I have -lrt in my linker command.

  2. These are Linux system provided function so the "Declared but did not define a variable or function" does not apply. No compiler errors so function prototype match from SUSE Linux to Ubuntu Linux.

  3. I'm calling Linux system functions that provide C function prototypes. "pure virtual" does not apply

  4. "virtual methods must either be implemented or defined as pure" does not apply. See 3.

  5. "Non-virtual class members" does not apply. See 3.

  6. "A common mistake is forgetting to qualify the name" does not apply. See 3.

  7. "static data members must be defined outside the class in a single translation unit" does not apply. See 3.

  8. "Template implementations not visible" does not apply. See 3.

  9. "Symbols were defined in a C program and used in C++ code". Does not apply. mqueue.h does have "extern "C"" wrapping function prototypes.

  10. Incorrectly importing/exporting methods/classes across modules/dll (compiler specific) does not apply. I'm working on Linux

  11. "If all else fails, recompile." Have done that...many times.

  12. "Befriending templates...". See 3.

  13. "Inconsistent UNICODE definitions". Does not apply.

  14. "When your include paths are different". See 2.

  15. "Your linkage consumes libraries before the object files that refer to them". Not the case. Command line shows the order things are loaded. I've also tried changing the order.

  16. "Missing "extern" in const variable declarations/definitions (C++ only)". See 2.

  17. "Different versions of libraries". I'm not linking any files that were not built on the system in question. Since I'm compiling and linking against a system library, this isn't the issue.

  18. "When linking against shared libraries, make sure that the used symbols are not hidden". I'm not using "-fvisibility=hidden" anywhere.

The only post that that did help was the one @Lawrence suggested. Using -v -Wl,-verbose. It verified that the linker is finding librt.so and loading it. Now if someone might suggest why the linker won't find the mq_* symbols.

DaveR
  • 1,295
  • 1
  • 13
  • 35
  • 2
    Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Matthieu Brucher Dec 06 '18 at 21:40
  • Obviously mqwrapper is built differently and you need to link against mq. – Matthieu Brucher Dec 06 '18 at 21:46
  • 2
    You can inspect what libraries the linker is finding by passing in `-Wl,-verbose` to gcc and following that chain – Lawrence Dec 06 '18 at 21:53
  • Link against mq? mq what? MQWrapper isn't linked any different than any other shared library. They are all linked the same way. I have other executable that link against the exact same MQWrapper and I don't get the errors. – DaveR Dec 06 '18 at 21:55
  • Not a duplicate. I've ventured down all the roads described in that post. – DaveR Dec 06 '18 at 21:56
  • Order of libraries is important. IIRC there may be a "rescan" flag (Ill go look) to get round that or you can duplicate `-lmylib` flags to fix mutual references (I think?) – Galik Dec 06 '18 at 21:57
  • One thing you can try is putting this flag *before* you list of library flags `-Wl,--start-group` and this flag at the *end* of your library flags `-Wl,--end-group`. That should fix any ordering issues if that's what is causing this. – Galik Dec 06 '18 at 22:07
  • @Lawrence, your suggestion helped. I tried -Wl,-verbose and discovered: "attempt to open /usr/lib/gcc/x86_64-linux-gnu/../../../x86_64-linux/gnu/librt.so succeeded". Now, why isn't it finding mq_* functions?? – DaveR Dec 06 '18 at 22:18
  • Not sure if it makes a difference, but I recently needed to add both libraries to gcc-9 experimental. I used `-lrt -ldl` instead of `-ldl -lrt`. And maybe related: [message queue makefile error: undefined reference to `mq_open'](https://stackoverflow.com/q/19423567/608639), [Weird posix message queue linking issue - sometimes it doesn't link correctly](https://stackoverflow.com/q/19964206/608639) – jww Dec 07 '18 at 00:40
  • Why are you posting 20 steps describing your problem? Why don't you simply provide a [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). that duplicates it??? – jww Dec 07 '18 at 02:12
  • 1
    @jww: Because people tried to mark it as a duplicate of a question with 20 steps in the answers? This is the right way to post a question that on first glance appears to be a duplicate. – Ben Voigt Dec 07 '18 at 02:27
  • @BenVoigt - I think you are incorrect. As the answer and the comment to the answer shows, OP described the problem incorrectly and did *not* provide a MCVE. A MCVE would have revealed the problem. – jww Dec 07 '18 at 02:45
  • @jww: The accurate quote of linker errors revealed the problem, since it references an object file not named on the command line. – Ben Voigt Dec 07 '18 at 02:47
  • @BenVoigt, I don't think the quote is accurate as it relates to my post. It was a shared library (librt.so) that was named in the command line (-lrt). If anything, the referenced post should have something like "check differences between linkers". – DaveR Dec 07 '18 at 02:58
  • 1
    @DaveR: I don't mean the answer in the other question, I mean when you put your exact entire linker error in this question. Too many people take just the error explanation, with no file name. Or even worse, they paraphrase the error message. – Ben Voigt Dec 07 '18 at 03:07
  • If you were using cmake, you would add `target_link_library(exeName rt)` to your CMakeLists.txt to link. – Sinux1 Sep 20 '20 at 23:14

1 Answers1

3

"Your linkage consumes libraries before the object files that refer to them". Not the case. Command line shows the order things are loaded. I've also tried changing the order.

This is likely still your problem. Your case is complicated by the fact that it's your libraries, not your object files, that depend on the system libraries.

You may need to mention -lrt in more than one place in your linker command line.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Thanks @Ben! I figured it out and was returning to post an update. You are correct. The MQWrapper project compiled fine but the command to build the SO did not include a reference to librt.so (-lrt). There were no errors when I built so I never suspected this. I found the problem by taking a closer look at the linker map for MQWrapper.so and notice librt.so was missing from the list of library dependencies. I never suspected this to be a problem because these same makefile work on SUSE Linux. Obviously, the linker on Ubuntu isn't as forgiving. – DaveR Dec 07 '18 at 02:14