8

I've been trying to compile my project and I'm getting undefined reference errors. eg.:

installertest.cpp:(.text+0x9d1): undefined reference to `XmlRpcValue::makeArray()'
...
installertest.cpp:(.text+0xede): undefined reference to `dbcancel'
installertest.cpp:(.text+0xefd): undefined reference to `dbfcmd'
installertest.cpp:(.text+0xf0f): undefined reference to `dbsqlexec'
installertest.cpp:(.text+0xf2d): undefined reference to `SHA1_Init'
...

My command-line is:

g++ -o installertest \
    -lsybdb \
    -lxmlrpc \
    -lxmlrpc_cpp \
    -lxmlrpc_xmlparse \
    -lxmlrpc_xmltok \
    -lxmlrpc_util \
    -lxmlrpc++ \
    -lxmlrpc_server_cgi \
    -lssl \
    -std=c++0x \
    ContractData.o installertest.o

objdump -T shows that the symbols are in the .so file. eg.:

libsybdb.so:
...
0000000000011c30 g    DF .text  0000000000000083  Base        dbcancel
...

/usr/lib/libxmlrpc_cpp.so:
...
0000000000002e78 g    DF .text  0000000000000092  Base        _ZN11XmlRpcValue9makeArrayEv
...

strace shows that the library files are being opened and read by the linker:

...
[pid  5019] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libsybdb.so", {st_mode=S_IFREG|0644, st_size=421608, ...}) = 0
[pid  5019] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libsybdb.so", O_RDONLY) = 7
[pid  5019] fcntl(7, F_GETFD)           = 0
[pid  5019] fcntl(7, F_SETFD, FD_CLOEXEC) = 0
[pid  5019] fstat(7, {st_mode=S_IFREG|0644, st_size=421608, ...}) = 0
[pid  5019] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b16c200c000
[pid  5019] lseek(7, 0, SEEK_SET)       = 0
[pid  5019] read(7, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\0\0\0\0\0\0"..., 4096) = 4096
...
[pid  5019] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib/libxmlrpc.so", {st_mode=S_IFREG|0644, st_size=80936, ...}) = 0
[pid  5019] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib/libxmlrpc.so", O_RDONLY) = 8
[pid  5019] fcntl(8, F_GETFD)           = 0
[pid  5019] fcntl(8, F_SETFD, FD_CLOEXEC) = 0
[pid  5019] fstat(8, {st_mode=S_IFREG|0644, st_size=80936, ...}) = 0
[pid  5019] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b16c200d000
[pid  5019] lseek(8, 0, SEEK_SET)       = 0
[pid  5019] read(8, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300?\0\0\0\0\0\0"..., 4096) = 4096
...

All files involved are targeted to x86-64 and the header for the C libraries are extern "C". I have tried everything I can think of and it still won't link.

I've even tried removing all C++11 code and compiling without the command-line switch, still nothing.

My system is Ubuntu Precise (12.04) 64-bit using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 if that helps. All packages were installed from the package manager and development packages are installed.

Edit (2017-05-30): Marked as duplicate of https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc
Other question asks why order of arguments is important. Argument order was not known to be an issue when question was asked.
Also, previous question does not contain any helpful expansion, whereas this question shows the issue at hand.
Previous question may be seen as a helpful expansion on the answer to this one, but not a duplication.

Megidd
  • 7,089
  • 6
  • 65
  • 142
  • Hi, Ben. Could you please show me how to use the strace to check the process. My main difficulty is about how to get the PID, as the compile process die very quickly. I only use the ps aux | grep to get the PID, but the process is already dead. – William Aug 31 '15 at 05:25
  • @XingWang, no problem. You simply need to prepend "strace -f -e trace=all" to your command line. Depending on your system, you may also need to add "sudo". So, from my example: "strace -f -e trace=all g++ -o installertest ContractData.o installertest.o "... – Ben Jaguar Marshall Aug 31 '15 at 10:40
  • 1
    Possible duplicate of [Why does the order in which libraries are linked sometimes cause errors in GCC?](https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc) – chue x May 29 '17 at 14:27

1 Answers1

14

You have to put the libraries' linker flags after the object files. So, instead of

g++ -o installertest \
-lsybdb \
-lxmlrpc \
-lxmlrpc_cpp \
-lxmlrpc_xmlparse \
-lxmlrpc_xmltok \
-lxmlrpc_util \
-lxmlrpc++ \
-lxmlrpc_server_cgi \
-lssl \
-std=c++0x \
ContractData.o installertest.o

use

g++ -o installertest \
ContractData.o installertest.o \
-lsybdb \
-lxmlrpc \
-lxmlrpc_cpp \
-lxmlrpc_xmlparse \
-lxmlrpc_xmltok \
-lxmlrpc_util \
-lxmlrpc++ \
-lxmlrpc_server_cgi \
-lssl \
-std=c++0x
  • 2
    Just tried properly, worked. Really!? Can't believe it was that simple. – Ben Jaguar Marshall Jun 20 '12 at 04:08
  • 6
    For anyone else who comes upon this issue, here's the reasoning. It seems that gcc now send the linker flag --as-needed to ld. This has the effect of discarding any specified libraries that do not have symbols that are required for linking. In the first instance, all the libraries were being discarded be cause there were no unresolved symbols then in the linking phase, the symbols could not be found. In the second instance, ld had collected the list of unresolved symbols and then found them in the specified libraries and therefore kept them when it came to the actual linking phase. – Ben Jaguar Marshall Jun 20 '12 at 04:39