Reputation: 1045
I am using libtool 2.2.6b on ubuntu lucid, and libtool 2.4.2 on ubuntu precise. On lucid my project will link properly. On precise it fails to link. Here's example code that demonstrates my problem;
configure.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
foo/Foo.h
#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 =
bar/Bar.h
#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/Bar.cpp
#include "bar/Bar.h"
namespace Bar
{
Bar::Bar(const Foo::Foo & f) : f(f) { }
}
bar/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
wah/main.cpp
#include "bar/Bar.h"
int main(int argc, char * argv[])
{
Bar::Bar( 5 );
return 0;
}
wah/Makefile.am
bin_PROGRAMS = wah
wah_SOURCES = main.cpp
wah_CPPFLAGS =
wah_LDADD = -L../bar -lbar
On Lucid, wah links, on Precise, it fails with:
wah/main.cpp:5 undefined reference to `Foo::Foo::Foo(long)'
I can fix this by adding -L../foo -lfoo
to wah_LDADD
, but really, isn't libtool supposed to do that for me automagically? The libtool manual section on `Linking executables' seems to indicate that is exactly what it should do.
Upvotes: 5
Views: 3923
Reputation: 8956
I suppose you could say it's more of a difference in philosophy. The point of Debian's change is to encourage users to be explicit about what they depend on, which reduces the amount of unnecessary churn when dependencies deep down the tree get upgraded.
When link_all_deplibs=yes
(unmodified libtool), if your program wah
depends on bar
and bar
depends on foo
, then it is implied that wah
depends foo
as well.
When link_all_deplibs=no
(Debian's modified libtool), if your program wah
depends on bar
and bar
depends on foo
, then it is not implied that wah
depends foo
as well.
So, taking Debian's perspective, this is false in your program: wah
does depend on foo
by virtue of this line:
Bar::Bar( 5 );
Here, you are calling the constructor of Foo::Foo
implicitly. As far as the C++ compiler is concerned, your program is really more like:
Bar::Bar( Foo::Foo( 5 ) );
Therefore, wah
depends on foo
not just indirectly, but directly. Hence, from Debian's perspective, you are should explicitly link to foo
via -lfoo
.
In particular, this is not the same situation as libtool's example for Linking Executables. In that example, main.o
does not explicitly depend on libm
, thus -lm
should, in principle, be unnecessary when linking the main.o
(main.c
does not call cos
directly). Perhaps the reason why libtool links recursively is as a work around for older systems where linkers are unable to handle indirect dependencies?
Upvotes: 2
Reputation: 16305
Works for me on Ubuntu 12.04 (Precise Pangolin) 32-bit, libtool 2.4.2.
I did have to change your Makefiles a bit to make dist
(more) correctly:
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 =
bar/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
wah/Makefile.am
bin_PROGRAMS = wah
wah_SOURCES = main.cpp ../bar/Bar.h
wah_CPPFLAGS =
wah_LDADD = -L../bar -lbar
Here's how it links 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
isn't libtool supposed to do that for me automagically?
Yes, it does, at least when the distribution tarball is created on a non-Ubuntu distribution. After I autoreconf on an Ubuntu box, I get the same error you do.
Apparently (according to adl) the Ubuntu distro has a patched version of libtool
which sets the libtool script variable:
link_all_deplibs=no
I patched the configure
generated libtool script to replace all these instances with:
link_all_deplibs=unknown
and everything linked as expected. I suppose you could do the same in a script that invokes autoreconf
. Or install a non-patched version of libtool
on the Ubuntu host. Or patch the patched libtool on the Ubuntu host. So there's a few options on how to fix it.
Upvotes: 1
Reputation: 16034
On any Debian machine I use for development, I have to compile and install Libtool by hand, because the Debian-supplied version is patched and ignores dependencies in a way that break my builds.
If Ubuntu's version is similar, you might want to install Libtool from source too.
Upvotes: 5