libtool не предоставляет библиотечные зависимости для ссылки

Я использую libtool 2.2.6b на Ubuntu Lucid и libtool 2.4.2 на Ubuntu Точность. В lucid мой проект будет правильно связан. На точном не удается связать. Вот пример кода, демонстрирующий мою проблему;

настроить.ac

AC_INIT([ltp], [0.0.1], [someone])
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([.m4])
AC_CONFIG_FILES([Makefile foo/Makefile bar/Makefile wah/Makefile])
AC_PROG_CXX
AC_PROG_LIBTOOL
AM_SANITY_CHECK
AC_LANG_CPLUSPLUS
AC_OUTPUT

Makefile.am

SUBDIRS = foo bar wah
ACLOCAL_AMFLAGS = -I .m4

фу/фу.ч

#ifndef FOO_FOO_H_
#define FOO_FOO_H_
namespace Foo
{
  class Foo
  {
  public:
    Foo(long l);
  private:
    long l;
  };
}
#endif

foo/Foo.cpp

#include "foo/Foo.h"
namespace Foo
{
  Foo::Foo(long l) : l(l) {}
}

foo/Makefile.am

lib_LTLIBRARIES = libfoo.la
libfoo_la_SOURCES = Foo.cpp
libfoo_la_CPPFLAGS =
libfoo_la_LDFLAGS = -release 0.0.1
libfoo_la_LIBADD =

бар/бар.ч

#ifndef BAR_BAR_H_
#define BAR_BAR_H_
#include "foo/Foo.h"
namespace Bar
{
  class Bar
  {
  public:
    Bar(const Foo::Foo & f);
  private:
    Foo::Foo f;
  };
}
#endif

бар/Bar.cpp

#include "bar/Bar.h"
namespace Bar
{
  Bar::Bar(const Foo::Foo & f) : f(f) { }
}

бар/Makefile.am

lib_LTLIBRARIES = libbar.la
libbar_la_SOURCES = Bar.cpp
libbar_la_CPPFLAGS =
libbar_la_LDFLAGS = -release 0.0.1
libbar_la_LIBADD = -L../foo -lfoo

вау/main.cpp

#include "bar/Bar.h"
int main(int argc, char * argv[])
{
  Bar::Bar( 5 );
  return 0;
}

вах/Makefile.am

bin_PROGRAMS = wah
wah_SOURCES = main.cpp
wah_CPPFLAGS =
wah_LDADD = -L../bar -lbar

На Lucid, wah links, на Precise происходит сбой с:

wah/main.cpp:5 undefined reference to `Foo::Foo::Foo(long)'

Я могу исправить это, добавив -L../foo -lfoo к wah_LDADD, но разве libtool не должен делать это автоматически? В разделе руководства libtool "Связывание исполняемых файлов", кажется, указано, что это именно то, что он должен делать.


person CAB    schedule 03.08.2012    source источник
comment
Как выглядят libfoo_LIBADD, libbar_LIBADD, libfoo_LDFLAGS, libbar_LDFLAGS? Флаги «–ldl –lboost_filesystem –lboost_system» являются зависимостями соответствующих библиотек, а не тестового исполняемого файла. Поскольку это общие библиотеки (не статические), почему вы думаете, что вторая строка неверна?   -  person ldav1s    schedule 09.08.2012
comment
libfoo_la_LDFLAGS = -release $(PACKAGE_VERSION) libfoo_la_LIBADD = -L$(libdir) -lboost_filesystem -ldl libbar_la_LDFLAGS = -release $(PACKAGE_VERSION) libbar_la_LIBADD = -L$(libdir) -lfoo -lboost_system   -  person CAB    schedule 10.08.2012
comment
исполняемый файл, который связывается с exe_LDADD -lbar и работает без ошибок. Надо будет повнимательнее посмотреть, что там происходит. Итак, я думаю, что исполняемый модуль модульного теста будет аналогичным. Хотя AM_LDADD нет. Но из руководства по libtool; Это выглядит слишком просто, чтобы быть правдой. Все, что сделал libtool, это преобразовал libhello.la в ./.libs/libhello.a, ... Обратите внимание, что Libtool также помнит, что libhello.la зависит от -lm, поэтому, хотя мы не указали -lm в командной строке libtool3 Libtool добавил его в строку ссылок gcc для нас. Так что же происходит с исполняемым файлом, но не с модульным тестом?   -  person CAB    schedule 10.08.2012
comment
Что не так с исполняемым файлом теста?   -  person ldav1s    schedule 11.08.2012
comment
С 2.2.6b на lucid ничего. С 2.4.2 на точных, неразрешенных символах из-за отсутствующих транзитивных зависимостей (библиотеки нужны libfoo). Возможно, это связано с изменением ссылки DSO в Ubuntu natty? Как я уже упоминал, exe с использованием exe_LDADD, ссылка в порядке. Это модульные тесты, основанные на AM_LDFLAGS, которые терпят неудачу.   -  person CAB    schedule 13.08.2012
comment
@ ldav1s - я отредактировал свой исходный пост, включив пример кода для своей проблемы. Не могли бы вы еще раз взглянуть на это для меня? Спасибо.   -  person CAB    schedule 18.08.2012


Ответы (3)


На любой машине Debian, которую я использую для разработки, мне приходится компилировать и устанавливать Libtool вручную, потому что версия, поставляемая Debian, исправлена ​​и игнорирует зависимости, что нарушает мои сборки.

Если версия Ubuntu аналогична, вы можете также установить Libtool из исходного кода.

person adl    schedule 13.08.2012
comment
Можете ли вы дать больше информации/ссылки на патч? Я хотел бы понять, что движет изменениями, и посмотреть, смогу ли я найти решение, более похожее на автоинструменты. - person CAB; 13.08.2012
comment
Я думаю, что проблемный патч — link_all_deplibs.patch, потому что он устанавливает $link_all_deplibs в no. Почта lists.gnu.org/archive/html/libtool/ 2007-09/msg00017.html дает пример того, что это ломает. - person adl; 13.08.2012
comment
Да, использование vanilla libtoolize также устраняет мои проблемы со сборкой. У меня появилось много проблем с косвенными зависимостями библиотек после того, как я запустил libtoolize в Ubuntu 12.04. В частности, библиотечные зависимости, которые не отражались в бинарных файлах библиотек (а только через встроенные функции в заголовочных файлах). Я не понимаю, как разработчики Debian/Ubuntu могли решить, что можно так сильно сломать Libtool. - person Kristian Spangsege; 08.03.2013
comment
С тех пор я нашел способ отменить эффект исправления Debian в моем собственном проекте, чтобы разработчикам не нужно было переустанавливать libtool на каждой машине с Debian, с которой они работают. git.lrde.epita.fr/ - person adl; 08.04.2013
comment
Долгое время мои приложения работали без каких-либо изменений, а юнит-тесты отошли на второй план, поэтому я не возвращался к этой проблеме. Но совсем недавно, по непонятным мне причинам, 4 из 24+ приложений также начали давать сбой. Что тем более озадачивает, потому что все 24+ приложения используют общую базовую структуру приложений. Итак, я использовал исправление configure.ac от @adl из ссылки на git выше, и оно работает как шарм. Спасибо! - person CAB; 04.10.2013

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

Когда link_all_deplibs=yes (немодифицированный libtool), если ваша программа wah зависит от bar, а bar зависит от foo, то подразумевается, что wah также зависит от foo.

Когда link_all_deplibs=no (модифицированный libtool Debian), если ваша программа wah зависит от bar, а bar зависит от foo, то не подразумевается, что wah также зависит от foo.

Итак, с точки зрения Debian, это false в вашей программе: wah зависит от foo на основании этой строки:

  Bar::Bar( 5 );

Здесь вы неявно вызываете конструктор Foo::Foo. Что касается компилятора С++, ваша программа действительно больше похожа на:

  Bar::Bar( Foo::Foo( 5 ) );

Следовательно, wah зависит от foo не просто косвенно, а напрямую. Следовательно, с точки зрения Debian, вы должны явно ссылаться на foo через -lfoo.

В частности, это отличается от примера с libtool для Связывание исполняемых файлов. В этом примере main.o не зависит явно от libm, поэтому -lm в принципе не должно быть необходимым при связывании main.o (main.c не вызывает cos напрямую). Возможно, причина, по которой libtool рекурсивно связывается, заключается в том, что это обходной путь для старых систем, где компоновщики не могут обрабатывать косвенные зависимости?

person Rufflewind    schedule 15.11.2016

У меня работает на Ubuntu 12.04 (Precise Pangolin) 32-бит, libtool 2.4.2.

Мне пришлось немного изменить ваши Makefiles на make dist (больше) правильно:

foo/Makefile.am:

lib_LTLIBRARIES = libfoo.la
libfoo_la_SOURCES = Foo.cpp Foo.h
libfoo_la_CPPFLAGS =
libfoo_la_LDFLAGS = -release 0.0.1
libfoo_la_LIBADD =

бар/Makefile.am:

lib_LTLIBRARIES = libbar.la
libbar_la_SOURCES = Bar.cpp Bar.h
libbar_la_CPPFLAGS =
libbar_la_LDFLAGS = -release 0.0.1
libbar_la_LIBADD = -L../foo -lfoo

вах/Makefile.am

bin_PROGRAMS = wah
wah_SOURCES = main.cpp ../bar/Bar.h
wah_CPPFLAGS =
wah_LDADD = -L../bar -lbar

Вот как это связывает main.cpp:

make[2]: Entering directory `/xxx/ltp-0.0.1/wah'
g++ -DHAVE_CONFIG_H -I. -I..     -g -O2 -MT wah-main.o -MD -MP -MF .deps/wah-main.Tpo -c -o wah-main.o `test -f 'main.cpp' || echo './'`main.cpp
mv -f .deps/wah-main.Tpo .deps/wah-main.Po
/bin/bash ../libtool --tag=CXX   --mode=link g++  -g -O2   -o wah wah-main.o -L../bar -lbar 
libtool: link: g++ -g -O2 -o .libs/wah wah-main.o  -L../bar /xxx/ltp-0.0.1/bar/.libs/libbar.so -L../foo /xxx/ltp-0.0.1/foo/.libs/libfoo.so

Разве libtool не должен делать это автоматически?

Да, это так, по крайней мере, когда архив дистрибутива создается в дистрибутиве, отличном от Ubuntu. После того, как я выполнил автореконфигурацию на компьютере с Ubuntu, я получаю ту же ошибку, что и вы. По-видимому (согласно adl) дистрибутив Ubuntu имеет исправленную версию libtool, которая устанавливает переменную сценария libtool:

link_all_deplibs=no

Я исправил сгенерированный configure скрипт libtool, чтобы заменить все эти экземпляры на:

link_all_deplibs=unknown

и все связано, как и ожидалось. Я полагаю, вы могли бы сделать то же самое в скрипте, который вызывает autoreconf. Или установите неисправленную версию libtool на хост Ubuntu. Или исправьте пропатченный libtool на хосте Ubuntu. Так что есть несколько вариантов, как это исправить.

person ldav1s    schedule 18.08.2012