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.
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.
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.
I'm calling Linux system functions that provide C function prototypes. "pure virtual" does not apply
"virtual methods must either be implemented or defined as pure" does not apply. See 3.
"Non-virtual class members" does not apply. See 3.
"A common mistake is forgetting to qualify the name" does not apply. See 3.
"static data members must be defined outside the class in a single translation unit" does not apply. See 3.
"Template implementations not visible" does not apply. See 3.
"Symbols were defined in a C program and used in C++ code". Does not apply. mqueue.h does have "extern "C"" wrapping function prototypes.
Incorrectly importing/exporting methods/classes across modules/dll (compiler specific) does not apply. I'm working on Linux
"If all else fails, recompile." Have done that...many times.
"Befriending templates...". See 3.
"Inconsistent UNICODE definitions". Does not apply.
"When your include paths are different". See 2.
"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.
"Missing "extern" in const variable declarations/definitions (C++ only)". See 2.
"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.
"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.