2009-07-21 7 views
2

В одном проекте у меня есть два noinst_PROGRAM. Один из них работает просто отлично, а другой дает мне следующее сообщение:Где я должен искать решение символьного поиска/неопределенного символа с проектом automake/autoconf?

/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar: symbol lookup error: /home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar: undefined symbol: _ZN5gdata7service7ServiceD1Ev

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

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

EDIT:

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

Деструктор определяется в 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 

Мой ЦСИ/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 

My SRC/GData/сервис/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. выглядит следующим образом:

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 

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

** EDIT # 2: ##

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

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

+0

Попробуйте переместить 'libgdata_gdata_service.la' после' libgdata_gdata_service_calendar.la' в 'libgdata_la_LIBADD', чтобы узнать, связано ли это с заказом библиотеки, как подозревал Джонатан. – ephemient

ответ

2

(Там в существующий проект под названием 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.)

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

+0

Спасибо за указатели! Я обновил свой вопрос более подробно. :) –

7

С c++filt -n -s gnu-v3 _ZN5gdata7service7ServiceD1Ev дает имя:

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

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

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

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

+1

+1 Удивительно, я никогда не помню, как развязать эти черты символов C++ ... @Beau: если у вас проблемы с упорядочением библиотеки, библиотеки предоставляют символы для объектов и библиотек, перечисленных впереди в командной строке (если только '-Wl , - startgroup -Wl, - endgroup' находятся в игре). – ephemient

+0

Деструктор ** был определен в файле Service.cc, но я попытался переместить его в заголовок, чтобы посмотреть, что это будет делать. Переместив его в заголовок, я подтвердил, что, по крайней мере, заголовок работает и что проблема действительно заключается в том, что объект Service.o по какой-то причине не попадает в libgdata. Спасибо за идею, так как я думаю, что это помогло мне сузить, я обновил свой вопрос более подробно. –