LINUX.ORG.RU

undefined reference in shared library


0

1

После обновления дистрибтива Ubuntu с 11.04 на 11.10 перестали собираться мои приложения использующие мои разделяемые библиотеки. Сами библиотеки собираются. С предыдущей системой все собиралось и работало. В 10.10 так же никаких проблем нее было. Подскажите, куда копать. Может быть в моих Makefile есть ошибки которых я не вижу. Прочитал что стало нового в gcc - ответа не нашел. Спасибо.

$uname -a
Linux u32 3.0.0-12-generic-pae #20-Ubuntu SMP Fri Oct 7 16:37:17 UTC 2011 i686 i686 i386 GNU/Linux

$gcc --version
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

########################################################
# Makefile fo shared library
########################################################

BASENAME := libtest.so
SONAME := $(BASENAME).0
LIBNAME := $(BASENAME).0.0

all: $(LIBNAME)

LIBDIR := $(shell pwd)

INC := $(addprefix -I, . ..)
SRC := $(wildcard *.cpp)
OBJ := $(SRC:.cpp=.o)

CFLAGS := -O2 -fPIC $(INC)

CC := $(CTOOLS_PREFIX)g++
LD := $(CTOOLS_PREFIX)g++

$(LIBNAME): $(OBJ)
$(LD) -shared -Wl,-soname,$(SONAME) -o $(LIBNAME) $(notdir $(OBJ)) -ldl -lrt -lc
chmod 666 $(LIBNAME)
ln -sf $(LIBDIR)/$(LIBNAME) $(LIBDIR)/$(SONAME)
ln -sf $(LIBDIR)/$(SONAME) $(LIBDIR)/$(BASENAME)

%.o: %.cpp
$(CC) $(CFLAGS) -c -MD $<

clean:
rm -fv *.o *.d *.so*

########################################################
# Makefile for application
########################################################

TARGET_NAME := test

all: $(TARGET_NAME)

ROOT_DIR := $(shell pwd)
LIBPATH := $(HOME)/shlibtest/shlib

CC := g++
LD := g++

CFLAGS := -g -Wall
LFLAGS := -Wl,-rpath,$(LIBPATH) -L"$(LIBPATH)" -ltest

$(TARGET_NAME): $(patsubst %.cpp,%.o, $(wildcard *.cpp))
$(LD) $(LFLAGS) $^ -o $(TARGET_NAME)
rm -f *.o *~ core

%.o: %.cpp
$(CC) $(CFLAGS) -c -MD $<

include $(wildcard *.d)

distclean:
clean:
rm -f *.o *~ core
rm -f *.d *~ core
rm -f $(TARGET_NAME)


Во-первых давай полный вывод ошибки, во-вторых давай вывод ld твоя-нелинкующаяся библиотека.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Сборка библиотеки:

karak@u32:~/shlibtest/shlib$ make
g++ -O2 -fPIC -I. -I.. -c -MD libfile.cpp
g++ -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0 libfile.o -ldl -lrt -lc
chmod 666 libtest.so.0.0
ln -sf /home/karak/shlibtest/shlib/libtest.so.0.0 /home/karak/shlibtest/shlib/libtest.so.0
ln -sf /home/karak/shlibtest/shlib/libtest.so.0 /home/karak/shlibtest/shlib/libtest.so

Сборка приложения:

karak@u32:~/shlibtest/test$ make
g++ -g -Wall -c -MD test.cpp
g++ -Wl,-rpath,/home/karak/shlibtest/shlib -L"/home/karak/shlibtest/shlib" -ltest test.o -o test
test.o: In function `main':
/home/karak/shlibtest/test/test.cpp:23: undefined reference to `lib_fprintf'
collect2: ld returned 1 exit status
make: *** [test] Error 1

Тестовая библиотека с одной функцией:

#include <stdio.h>
extern «C» {
void lib_fprintf(void)
{
fprintf(stderr, «%s, %d: %s(): Hello World!\n», __FILE__, __LINE__, __FUNCTION__);
}
}

Тестовое приложение с одной функцией:

#include <stdio.h>
#include <stdlib.h>

extern «C» void lib_fprintf(void);

int<--->main( int argc, char *argv[] )
{
lib_fprintf();
return 0;
}

karak
() автор топика
Ответ на: комментарий от yoghurt

Cmake тогда уж. Зачем всякое говно мамонта человеку предлагаешь.

Reset ★★★★★
()
Ответ на: комментарий от yoghurt

Ниасилил. Порядок линковки только для статических библиотек важен.

Reset ★★★★★
()
Ответ на: комментарий от yoghurt

Это если libtool использовать, а здесь должно собираться без него. Я перечитал еще раз про *.so библиотеки там такого файла нет.

karak
() автор топика
Ответ на: комментарий от karak

Хм, странно. В общем, у меня всё работает

/tmp/pewpew/lib $ make
g++ -O2 -fPIC -I. -I.. -c -MD lib.cpp
g++ -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0 lib.o -ldl -lrt -lc
chmod 666 libtest.so.0.0
ln -sf /tmp/pewpew/lib/libtest.so.0.0 /tmp/pewpew/lib/libtest.so.0
ln -sf /tmp/pewpew/lib/libtest.so.0 /tmp/pewpew/lib/libtest.so
/tmp/pewpew/lib $ ls
Makefile  lib.cpp  lib.d  lib.o  libtest.so  libtest.so.0  libtest.so.0.0
/tmp/pewpew/lib $ cd ..
/tmp/pewpew $ ls
app  lib
/tmp/pewpew $ cd app/
/tmp/pewpew/app $ make
g++ -g -Wall -c -MD app.cpp
g++ -Wl,-rpath,/tmp/pewpew/lib -L"/tmp/pewpew/lib" -ltest app.o -o test
rm -f *.o *~ core
/tmp/pewpew/app $ ./test 
lib.cpp, 5: lib_fprintf(): Hello World!
/tmp/pewpew/app $ uname -a
Linux ion 3.0.0-1-686-pae #1 SMP Wed Aug 17 04:28:34 UTC 2011 i686 GNU/Linux
/tmp/pewpew/app $ 
yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

А gcc --version что выдает? Кстати на чистой системе Ubuntu 11.10 установленной с диска, а не через обновление - тот же эффект.

karak
() автор топика
Ответ на: комментарий от karak

Попробуй сделать для начала всё руками, без makefile'ов, шаманств со страшными ключами типа -soname и создания ссылок. Просто и тупо:

g++ -shared libtest.cpp -o libtest.so
g++ main.cpp -L. -ltest -o test

Если заработает, то добавляй свои шаманства по одному и смотри где перестанет работать.

Reset ★★★★★
()

Скорее всего какая-то из функций, используемая в твоих разделяемых библиотеках, в 11.10 переехала в другую системную разделяемую библиотеку. При линковке разделяемой библиотеки линкер не ругается на неопределённые символы, поэтому ты и не получаешь ошибок при линковке. А вот при запуске динамический линкер ругается на неопределённые символы (найденные в твоей разделяемой библиотеке).

iliyap ★★★★★
()
Ответ на: комментарий от Eddy_Em

Потому что ты компилировал из них либо статические либы либы обычные исполняемые файлы. so без -fPIC на x86_64 работать не будет.

Reset ★★★★★
()
Ответ на: комментарий от iliyap

ога, а проверить это можно командой ld. только судя по коду, в so'шке всего лишь одна функция, которая использует libc, который и так линкуется по умолчанию.

Reset ★★★★★
()
Ответ на: комментарий от karak

У меня работает.

Попробуй такие команды для диагностики:

$ nm shlib/libtest.so.0 | grep lib_fprintf
000000000000b208 r _ZZ11lib_fprintfE12__FUNCTION__
0000000000004c10 T lib_fprintf

$ ldd shlib/libtest.so.0
	linux-vdso.so.1 =>  (0x00007fff32bff000)
	libdl.so.2 => /lib/libdl.so.2 (0x00007f2829012000)
	librt.so.1 => /lib/librt.so.1 (0x00007f2828e0a000)
	libm.so.6 => /lib/libm.so.6 (0x00007f2828b87000)
	libc.so.6 => /lib/libc.so.6 (0x00007f2828826000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2829453000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f2828610000)
	libpthread.so.0 => /lib/libpthread.so.0 (0x00007f28283f3000)
ringill
()
Ответ на: комментарий от Reset

Вы наверное имеете ввиду ldd, а не ld. Но ldd не показывает неопределённые символы, он показывает только загрузку динамических библиотек (из NEEDED). Вобщем, ldd не поможет найти неопределённые символы, которые не будут определены в рантайме при загрузке всех указанные в NEEDED.

iliyap ★★★★★
()
Ответ на: комментарий от ringill


Вот вывод этих команд у меня на системе:

karak@u32:~/shlibtest$ nm ./shlib/libtest.so.0 | grep lib_fprintf
0000058a r _ZZ11lib_fprintfE12__FUNCTION__
000004b0 T lib_fprintf
karak@u32:~/shlibtest$ ldd ./shlib/libtest.so.0
linux-gate.so.1 => (0xb7753000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75bc000)
/lib/ld-linux.so.2 (0xb7754000)
karak@u32:~/shlibtest$

karak
() автор топика
Ответ на: комментарий от Reset

При сборке библиотеки и приложения в одном каталоге все собралось. Пища для размышления. Однако.

karak
() автор топика
Ответ на: комментарий от karak

Сделай таки ld плохая-библиотека.so и напиши вывод сюда (именно ld, а не ldd!). Может там будут unreferenced символы.

Reset ★★★★★
()
Ответ на: комментарий от karak

При сборке библиотеки и приложения в одном каталоге все собралось. Пища для размышления. Однако.

Методом тыка получается поряд всё таки имеет значение. Вот это:

g++ -Wl,-rpath,/home/alexeys/src/shlibtest/shlib -L"/home/alexeys/src/shlibtest/shlib" -ltest test.o -o test

не работает, а так:

g++ -Wl,-rpath,/home/alexeys/src/shlibtest/shlib -L"/home/alexeys/src/shlibtest/shlib" test.o -o test -ltest

- работает.

Чудо Убунты :)

abacaba
()
Ответ на: комментарий от abacaba

Только не убунты, а линковщика. Вообще странно, порядок обычно имел значение только при статической линковки. -ltest точно линкует .so, а не .a ?

Reset ★★★★★
()
Ответ на: комментарий от abacaba

Действительно работает. Спасибо :)

karak
() автор топика
Ответ на: комментарий от karak

В примерах действительно указан такой порядок флагов как и использовал abacaba:

gcc -g -o demo_use demo_use.o -L. -lhello

Нужно перечитать еще разок.

karak
() автор топика
Ответ на: комментарий от Reset

Только не убунты, а линковщика. Вообще странно, порядок обычно имел значение только при статической линковки. -ltest точно линкует .so, а не .a ?

Короче, в убунте добавляется флаг --as-needed по-умолчанию к collect2, а в Дебиане по-видимому нет. Если посмотреть, как collect2 запускается и запустить так же без --as-needed - проходит с любым порядком библиотек.

abacaba
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.