Autoconf: ошибка компоновщика при связывании с пользовательской библиотекой

1) У меня есть проект, содержащий разделяемую библиотеку, которая ссылается на некоторые сторонние библиотеки (а именно gcrypt, gpg-error, z и ssh2). Назовем это "mylib". Эта библиотека отлично строится, и я вижу, что libtool правильно связывает зависимости.

libtool: link: ppc-linux-gcc -shared  -fPIC -DPIC  .libs/mylib1.o .libs/mylib2.o .libs/mylib3.o
     -Wl,-rpath -Wl,/opt/ELDK/ppc_8xx/lib -Wl,-rpath \
     -Wl,/opt/ELDK/ppc_8xx/lib /opt/ELDK/ppc_8xx/lib/libssh2.so \
     -L/opt/ELDK/ppc_8xx/lib -lz /opt/ELDK/ppc_8xx/lib/libgcrypt.so \
     /opt/ELDK/ppc_8xx/lib/libgpg-error.so -lpthread  -O2 \
     -Wl,-soname -Wl,mylib.so.0 -o .libs/mylib.so.0.0.0

2) В этом же проекте есть несколько программ, ссылающихся на "mylib". Однако, когда я пытаюсь связать их, я получаю ошибки компоновщика о тех же предыдущих библиотеках:

/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
     warning: libssh2.so.1, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
     warning: libz.so.1, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
     warning: libgcrypt.so.11, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
     warning: libgpg-error.so.0, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
./../myLib/.libs/mylib.so: undefined reference to `libssh2_channel_process_startup'
./../myLib/.libs/mylib.so: undefined reference to `libssh2_scp_send_ex'

В "mylib" configure.ac я явно ищу библиотеки:

AC_SEARCH_LIBS(gpg_err_set_errno,[gpg-error])
AC_SEARCH_LIBS(gcry_check_version,[gcrypt])
AC_SEARCH_LIBS(deflate,[z])
AC_SEARCH_LIBS(libssh2_init,[ssh2])

Должен ли я также явно включать все эти библиотеки в каждый проект, используя «mylib»? Разве это не должно быть уже решено, когда я впервые связываю их в «mylib»?

Есть ли лучший способ сделать это?

Спасибо.

P.S.: Я не очень разбираюсь в autoconf вопросе, извините.

ПРИМЕЧАНИЕ. Я выполняю кросс-компиляцию для PowerPC, используя (еще старый) ELDK 3.1.


person j4x    schedule 24.02.2012    source источник
comment
Вы переопределяете какие-либо директивы для своей программы в Makefile.am?   -  person William Pursell    schedule 26.02.2012
comment
У меня есть что-то вроде program1_CPPFLAGS = -I$(top_srcdir) $(MYLIB_CFLAGS), где MYLIB_CFLAGS и MYLIB_LIBS определены с помощью AC_ARG_WITH в configure.ac программы1, чтобы я мог ссылаться на локальную mylib вместо установленной в системе (пожалуйста, скажите мне, если это лучший способ сделать это).   -  person j4x    schedule 27.02.2012
comment
CPPFLAGS не должен иметь значения, но как вы используете MYLIB_LIBS в Makefile.am? В вашем окончательном Makefile должна быть цель для программы1$(EXEEXT), которая содержит команду $(LINK), и эта команда должна иметь $(LIBS), которая должна содержать библиотеки, если AC_SEARCH_LIBS успешно нашла данную библиотеку.   -  person William Pursell    schedule 27.02.2012
comment
Вывод запуска ldd на mylib.so был бы полезен, хотя я не уверен, насколько легко это сделать при кросс-компиляции. Также было бы интересно проверить с помощью readelf -a, чтобы убедиться, что RPATH действительно добавлен, как вы просили.   -  person rra    schedule 17.03.2013


Ответы (2)


ПРИМЕЧАНИЕ: Поскольку я получил ответ спустя 2 года, и это не решило мою проблему, я думаю, что лучше поделиться со всеми тем, что я сделал.


ОТВЕТ:

Я обнаружил, что лучшим способом автоматического включения зависимостей компоновщика в проект на основе autoconf было добавление информации pkg-config в мою библиотеку.

Изменения в configure.ac:

export PKG_CONFIG_PATH=../MyLibPath:${PKG_CONFIG_PATH}
PKG_CHECK_MODULES([DEPS], [libssh2 >= 1.3.0])

# Output configuration files.
AC_CONFIG_FILES([Makefile libMyLib-1.0.pc libMyLib-1.0-uninstalled.pc])

Второй выходной файл libMyLib-1.0-uninstalled.pc позволяет мне продолжить разработку моего проекта с неустановленной версией MyLib.

Изменения в Makefile.am:

libMyLib_la_CPPFLAGS  = $(DEPS_CPPFLAGS)
libMyLib_la_CFLAGS    = $(DEPS_CFLAGS)
libMyLib_la_CXXFLAGS  = $(DEPS_CXXFLAGS)
libMyLib_la_LIBADD    = $(DEPS_LIBS)

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libMyLib-1.0.pc

Добавить в проект libMyLib-1.0.pc:

prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@

Name: MyLib
Description: My library.
Requires: libssh2
Requires.private:
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lMyLib -lstdc++ -lm -lslog -lpthread
Libs.private:
Cflags: -I${includedir}/libMyLib-1.0

и libMyLib-1.0-uninstalled.pc:

prefix=@abs_builddir@
exec_prefix=@exec_prefix@
libdir=${prefix}/.libs
includedir=${prefix}

Name: MyLib
Description: My library.
Requires: libssh2
Requires.private:
Version: @PACKAGE_VERSION@
Libs: -Wl,-rpath-link,${libdir} -L${libdir} -lMyLib -lstdc++ -lm -lslog -lpthread
Libs.private:
Cflags: -I${includedir}/

В каждом зависимом проекте:

configure.ac:

export PKG_CONFIG_PATH=../MyLibPath:${PKG_CONFIG_PATH}
PKG_CHECK_MODULES([MYLIB], [libMyLib-1.0 >= 1.0.0])

Makefile.am:

dependent_CPPFLAGS  = $(MYLIB_CPPFLAGS)
dependent_CFLAGS    = $(MYLIB_CFLAGS)
dependent_CXXFLAGS  = $(MYLIB_CXXFLAGS)
dependent_LIBADD    = $(MYLIB_LIBS)
person j4x    schedule 24.07.2014
comment
Вам не нужно -rpath-link в записи Libs, если libslog или стандартные библиотеки также не находятся в разных путях. - person Diego Elio Pettenò; 25.07.2014
comment
Да, он находится по другому пути в профиле uninstalled. Спасибо! - person j4x; 28.07.2014

Трудно точно сказать, что вы делаете, не зная, что находится в вашем Makefile.am или configure.ac, но поскольку я вижу, что вы используете -Wl,-rpath, я предполагаю, что вы передаете его как LDFLAGS извне, когда вызываете ./configure.

Что происходит, так это то, что libtool обычно не хранит значения -rpath, но хранит -L; поэтому я обычно предлагаю передать как -L, так и -rpath, чтобы файлы .la содержали путь, по которому можно найти библиотеки для ссылки на него.

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

person Diego Elio Pettenò    schedule 23.07.2014
comment
Действительно спасибо за ответ Диего. В итоге я поставил pkgconfig на воспроизведение, и это решило мою проблему. Теперь мне не нужно повторять связанные библиотеки для каждой зависимости. Однако разочаровывает, что autoconf не может автоматически каскадировать эти зависимости... - person j4x; 24.07.2014
comment
Вы можете каскадировать только зависимости общих объектов, но не статические архивы, но в этом случае мне кажется, что у вас есть какая-то дополнительная зависимость, которая находится на другом пути, и это сложнее, потому что пути ее поиска меняются. - person Diego Elio Pettenò; 25.07.2014
comment
Раздражает мысль о том, что мне приходилось повторять зависимые (общие) библиотеки в общих проектах. Несмотря на то, что MyLib уже был динамически связан, окончательная программа/библиотека выдавала ошибки компоновщика, если я опускал зависимости (уже связанные в MyLib). - person j4x; 28.07.2014
comment
Являются ли они частью системных библиотек или находятся в отдельном пути? Похоже, редактор ссылок не знает, где их искать. - person Diego Elio Pettenò; 29.07.2014