4

我在 ubuntu lucid 上使用 libtool 2.2.6b,在 ubuntu 上使用 libtool 2.4.2。在清醒时,我的项目将正确链接。准确地说,它无法链接。这是演示我的问题的示例代码;

配置.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

生成文件.am

SUBDIRS = foo bar wah
ACLOCAL_AMFLAGS = -I .m4

富/富.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 =

酒吧/酒吧.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

酒吧/酒吧.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 链接上,在 Precise 上,它失败了:

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

我可以通过添加-L../foo -lfooto来解决这个问题wah_LDADD,但实际上,libtool 不应该自动为我做这件事吗?`Linking executables' 的 libtool 手册部分似乎表明这正是它应该做的。

4

3 回答 3

5

在我用于开发的任何 Debian 机器上,我都必须手动编译和安装 Libtool,因为 Debian 提供的版本已打补丁并忽略依赖关系,从而破坏了我的构建。

如果 Ubuntu 的版本相似,您可能也想从源代码安装 Libtool 。

于 2012-08-13T10:07:10.360 回答
2

我想你可以说这更像是哲学上的不同。Debian 更改的重点是鼓励用户明确他们所依赖的内容,这减少了当树深处的依赖项升级时不必要的流失量

link_all_deplibs=yes(未修改的 libtool)时,如果您的程序wah依赖barbar依赖于foo,则暗示wah依赖foo于。

link_all_deplibs=no(Debian 修改后的 libtool)时,如果你的程序wah依赖于bar并且bar依赖于foo,那么并不意味着wah依赖foo于。

因此,从 Debian 的角度来看,这在您的程序中是错误的:wah 确实依赖于foo这一行:

  Bar::Bar( 5 );

在这里,您正在Foo::Foo隐式调用 的构造函数。就 C++ 编译器而言,您的程序实际上更像:

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

因此,不仅间接wah依赖,而且直接依赖。因此,从 Debian 的角度来看,您应该明确链接到via 。foofoo-lfoo

特别是,这libtool 的Linking Executables示例不同。在该示例中,main.o不明确依赖于libm,因此-lm原则上在链接main.o(main.ccos直接调用) 时应该是不必要的。也许 libtool 递归链接的原因是为了解决链接器无法处理间接依赖关系的旧系统?

于 2016-11-15T00:36:48.270 回答
1

在 Ubuntu 12.04 (Precise Pangolin) 32 位、libtool 2.4.2 上为我工作。

我确实必须将您的 Makefile 更改为make dist(更多)正确:

富/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 发行版上创建发行版 tarball 时确实如此。在 Ubuntu 机器上进行 autoreconf 后,我得到了与您相同的错误。显然(根据 adl)Ubuntu 发行版有一个补丁版本,libtool其中设置了 libtool 脚本变量:

link_all_deplibs=no

我修补了configure生成的 libtool 脚本以将所有这些实例替换为:

link_all_deplibs=unknown

一切都按预期链接。我想您可以在调用autoreconf. libtool或者在 Ubuntu 主机上安装未打补丁的版本。或者在 Ubuntu 主机上打补丁的 libtool。所以有一些关于如何修复它的选项。

于 2012-08-18T03:58:28.567 回答