Linked не может найти символы, но библиотеки читаются и символы существуют

Я пытаюсь скомпилировать свой проект и получаю undefined reference ошибки. например.:

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'
...

Моя командная строка:

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 показывает, что символы находятся в файле .so. например.:

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

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

strace показывает, что файлы библиотеки открываются и читаются компоновщиком:

...
[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
...

Все задействованные файлы ориентированы на x86-64, а заголовки для библиотек C — extern "C". Я перепробовал все, что мог придумать, и это все еще не свяжется.

Я даже пытался удалить весь код С++ 11 и скомпилировать без переключателя командной строки, но ничего.

Моя система Ubuntu Precise (12.04) 64-разрядная с использованием g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, если это поможет. Все пакеты были установлены из менеджера пакетов и установлены пакеты разработки.

Редактировать (30 мая 2017 г.): Помечено как дубликат https://stackoverflow.com/questions/45135/why-does-the-order-in-what-libraries-re-linked-sometimes -cause-errors-in-gcc
Другой вопрос спрашивает, почему важен порядок аргументов. При задании вопроса не было известно, что порядок аргументов является проблемой.
Кроме того, предыдущий вопрос не содержит какого-либо полезного расширения, тогда как этот вопрос показывает существующую проблему.
Предыдущий вопрос может рассматриваться как полезный расширение ответа на этот вопрос, но не дублирование.


person Ben Jaguar Marshall    schedule 20.06.2012    source источник
comment
Привет, Бэн. Не могли бы вы показать мне, как использовать strace для проверки процесса. Моя основная трудность заключается в том, как получить PID, так как процесс компиляции умирает очень быстро. Я использую только ps aux | grep, чтобы получить PID, но процесс уже мертв.   -  person William    schedule 31.08.2015
comment
@XingWang, нет проблем. Вам просто нужно добавить strace -f -e trace=all в командную строку. В зависимости от вашей системы вам также может понадобиться добавить sudo. Итак, из моего примера: strace -f -e trace=all g++ -o installertest ContractData.o installertest.o ...   -  person Ben Jaguar Marshall    schedule 31.08.2015


Ответы (1)


Вы должны поместить флаги компоновщика библиотек после объектных файлов. Итак, вместо

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

использовать

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
person Community    schedule 20.06.2012
comment
Только что попробовал как следует, сработало. Действительно!? Не могу поверить, что это было так просто. - person Ben Jaguar Marshall; 20.06.2012
comment
Для всех, кто сталкивается с этой проблемой, вот рассуждение. Кажется, что теперь gcc отправляет флаг компоновщика --as-needed в ld. Это приводит к отбрасыванию любых указанных библиотек, которые не имеют символов, необходимых для компоновки. В первом случае все библиотеки отбрасывались из-за отсутствия неразрешенных символов, а затем на этапе компоновки символы не могли быть найдены. Во втором случае ld собрала список неразрешенных символов, а затем нашла их в указанных библиотеках и, следовательно, сохранила их, когда дело дошло до этапа фактической компоновки. - person Ben Jaguar Marshall; 20.06.2012