Где я должен искать, чтобы решить проблему поиска/неопределенного символа с проектом automake/autoconf?

В одном проекте у меня определены два noinst_PROGRAM. Один из них работает нормально, но другой выдает следующее сообщение:

/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar: ошибка поиска символа: /home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar: неопределенный символ: _ZN5gdata7service7ServiceD1Ev

Я просматривал свои файлы Makefile.am и не могу найти ничего, что я пропустил. Приложение компилируется правильно, поэтому я предполагаю, что это означает, что заголовочный файл найден правильно, но по какой-то причине мой gdata::service::Service не включается в библиотеку src/libgdata.la.

Верно ли мое предположение? Другие классы, определенные в библиотеке src/libgdata.la, кажутся пригодными для использования. Вывод «make» показывает, что файл Service.cc компилируется правильно... какие-нибудь указатели, где я должен искать, чтобы убедиться, что он включен в окончательную библиотеку?

ИЗМЕНИТЬ:

Я смог отладить это немного дальше, основываясь на ответах, предоставленных до сих пор.

Деструктор определен в Service.cc. Если я даю деструктору тело в заголовочном файле, все работает нормально.

// In Service.h
~Service() {}

// In Service.cc
// Service::~Service() {}

Теперь, когда деструктор «работает», я столкнулся с другими методами, определенными в Service.cc, но не найденными.

Используя метод @ephemient, мне кажется, что эти символы действительно включены в библиотеку. Или я неправильно читаю вывод?

000000e0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
000000a0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src/.libs/libgdata.a
000240d0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
00024090 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
000240d0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
00024090 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src/.libs/libgdata.so
00000080 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
00000070 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src//gdata/service/libgdata__gdata_service_la-Service.o
000000e0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
000000a0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src//gdata/service/.libs/libgdata__gdata_service.a
000000e0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
000000a0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src//gdata/service/.libs/libgdata__gdata_service_la-Service.o

Мой src/Makefile.am выглядит так:

SUBDIRS = gdata

lib_LTLIBRARIES = libgdata.la

libgdata_la_SOURCES = 

libgdata_la_LIBADD = \
    gdata/client/libgdata_gdata_client.la \
    gdata/data/libgdata_gdata_data.la \
    gdata/data/youtube/libgdata_gdata_data_youtube.la \
    gdata/util/libgdata_gdata_util.la \
    gdata/service/libgdata_gdata_service.la \
    gdata/service/calendar/libgdata_gdata_service_calendar.la

Мой src/gdata/service/Makefile.am выглядит так:

SUBDIRS = calendar

noinst_LTLIBRARIES = libgdata_gdata_service.la

libgdata_gdata_service_ladir = \
    $(includedir)/gdata/service

libgdata_gdata_service_la_SOURCES = \
    Service.cc

libgdata_gdata_service_la_HEADERS = \
    Service.h

Мой тест/Makefile.am выглядит так:

INCLUDES = -I$(top_srcdir)/src/ -I$(top_srcdir)/test/

LDADD = ../src/libgdata.la

TESTS = check_bare

noinst_PROGRAMS = gdatacalendar gdatayoutube $(TESTS)

check_bare_SOURCES = check_bare.cc

gdatacalendar_SOURCES = gdatacalendar.cc

gdatayoutube_SOURCES = gdatayoutube.cc

gdatayoutube работает нормально. Это более старый код, который использует код из каталога клиента вместо службы ( gdata/client/libgdata_gdata_client.la ) ... Я не вижу никакой разницы между тем, как клиент настраивается из службы. :-/

** РЕДАКТИРОВАТЬ № 2: ##

Ну, я не знаю, как это произошло, но я думаю, что нашел свою проблему. Я думаю, что тестовые приложения линковались с установленной версией библиотеки, над которой я работал, а не с локальной версией, встроенной в src/.

Я изучу это больше и, возможно, задам некоторые другие вопросы в другой раз.


person Community    schedule 21.07.2009    source источник
comment
Попробуйте переместить libgdata_gdata_service.la после libgdata_gdata_service_calendar.la в libgdata_la_LIBADD, чтобы увидеть, не связано ли это с порядком в библиотеке, как подозревал Джонатан.   -  person ephemient    schedule 22.07.2009


Ответы (2)


Поскольку c++filt -n -s gnu-v3 _ZN5gdata7service7ServiceD1Ev дает имя:

gdata::service::Service::~Service()

вам нужно внимательно посмотреть, всегда ли определен деструктор для этого класса, или есть ли какой-то способ, которым он может быть оставлен неопределенным (или, действительно, определен ли он когда-либо). Или компилируется ли исходный файл, содержащий деструктор (почему он не Service.cc?). Какой-то файл, использующий код, ожидает найти для него деструктор, даже если Service.cc не считает его необходимым.

Другая возможность — ошибка последовательности библиотек, то есть в строке ссылки библиотеки перечислены в порядке ABC, но они должны быть в порядке BCA или какой-либо другой перестановке, и вы связываетесь со статическими библиотеками. Обычно это приводит к большому количеству неопределенных символов, если вы связываетесь со статическими библиотеками (но использование разделяемых библиотек скрывает проблемы с упорядочением).

@Ephemient дал вам несколько хороших советов о том, как найти объектный файл, который ссылается на деструктор. Вы также должны определить, содержит ли Service.o (Service.lo или .lib/Service.o или другие подобные имена) деструктор - скорее всего, он не содержит деструктор, учитывая ошибку ссылки.

person Jonathan Leffler    schedule 21.07.2009
comment
+1 Круто, я никогда не помню, как распутывать эти чертовы символы C ++ ... @Beau: если у вас есть проблемы с порядком библиотек, библиотеки предоставляют символы для объектов и библиотек, перечисленных перед ними в командной строке (если только -Wl,--startgroup -Wl,--endgroup не в игре). - person ephemient; 21.07.2009
comment
Деструктор был определен в файле Service.cc, но я попытался переместить его в заголовок, чтобы посмотреть, что он будет делать. Переместив его в заголовок, я подтвердил, что, по крайней мере, заголовок работает и что проблема действительно заключается в том, что объект Service.o по какой-то причине не попадает в libgdata. Спасибо за идею, так как я думаю, что это помогло мне сузить круг вопросов. Я обновил свой вопрос, добавив более подробную информацию. - person Beau Simensen; 22.07.2009

(Уже существует проект под названием libgdata, но это, вероятно, не имеет значения.)

$ find -name '*.o' -o -name '*.a' -o -name '*.so' | 
> while read i; do
>     (nm --defined-only $i; nm -D --defined-only $i) 2>/dev/null |
>     grep _ZN5gdata7service7ServiceD1Ev && echo "$i"
> done

Это довольно грубый способ узнать, в каких объектах (если они есть) определен символ _ZN5gdata7service7ServiceD1Ev. (Может быть проще просто найти исходный файл, определяющий gdata::service::Service, если шаблоны не используются.)

$ rm libgdata.la gdatacalendar
$ make

Это грубый способ узнать, что входит в libgdata.la и gdatacalendar. (Но это должно быть довольно очевидно, если посмотреть на (libgdata_la|gdatacalendar)_(SOURCES|LIBADD) в соответствующем Makefile.am.)

Нет ли здесь несоответствия?

person ephemient    schedule 21.07.2009
comment
Спасибо за указатели! Я обновил свой вопрос с более подробной информацией. :) - person Beau Simensen; 22.07.2009