寻求解释:libtool,automake,共享库(和Fortran)

时间:2011-04-07 09:32:10

标签: shared-libraries automake libtool

我遇到的问题已经解决了。我发布这个是为了解释为什么解决方案实际工作的解释。我之前得到了很好的反馈。

我有一个使用非常简单的构建系统的遗留代码库,我的项目是将其迁移到Autotools进行自定义,特别是构建共享库。主库是用C语言编写的,但也必须可以从Fortran链接(用于遗留目的),并在F77中与一些测试代码一起分发。作者将源代码组织成模块......

src_module1/
src_module2/
...
testc/
testf77/

他们通过编译src _ * /目录中的代码并使用ranlib归档对象来构建库lib/libmain.a

我的第一种方法是分别从每个src _ * /构建一个共享库,并将所有这些共享库“链接”到一个共享库中。使用Autotools,src_module1/Makefile.am将包含

noinst_LTLIBRARIES = libmodule1.la
libmodule1_la_SOURCES = ...

等其他模块,最后lib/Makefile.am只需要:

lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES =
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la ...

这似乎完美无缺。但是,当testc /中的代码被编译并链接到libmain.la时,会发出“找不到符号”错误。

认为这是libtool或共享库的问题,我尝试仅构建静态,基本上将所有.la更改为.a,将所有_LTLIBRARIES更改为_LIBRARIES。同样的问题。但是,这一次,当尝试链接libmain.a本身时,注意到错误“ranlib:warning for library:libmain.a目录是空的(库中没有对象文件成员定义全局符号)”。

我找到的解决方案似乎是一个黑客攻击。我没有为任何src _ * /目录构建Makefile,而只是用于lib /目录,而它的Makefile.am有这些行:

lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES = [all sources from all ../src_modules/ ]

这很有用。 testc中编译的程序/链接libmain.la没有问题。其中一个“模块”是一组Fortran绑定,它们包含库中的其他C函数。甚至testf77中的Fortran代码也正确地链接到了libmain.la。

有人可以仔细解释当libtool构建共享库时会发生什么吗?甚至在构建静态库时?为什么几个静态库无法链接在一起构成一个静态库?为什么符号仅在libtool / ranlib“从源”构建库时可用?那么安装一个共享/静态库,比如将它移到/ usr / local / lib那里会发生什么呢?关于静态和共享库的维基百科文章对我来说不够详细。

我非常感谢所有努力来理解我的长篇大论。

1 个答案:

答案 0 :(得分:2)

你最初尝试过的应该是什么。我一直在使用这种设置(在C ++上下文中)。它也被记录下来,并且是Automake测试套件的一部分(尽管可能不是Fortran)。

无法安装的libtool库,即使用noinst_LTLIBRARIES声明的库,称为libtool convenience librarynoinst_对构建的内容产生重大影响。即使Libtool配置为构建共享库,libtool便利库实际上也不是共享库:它只是一组目标文件(编译为PIC,以便后者可以在共享库中使用)存储在档案中。您可以在任何地方使用libtool便利库,使用这组对象是有意义的,例如,构建共享库。

当多个libtool便利库被LIBADDed到可安装的 libtool库(例如你的libmain.la)时,Libtool必须解压缩包含每个便利库对象的存档并将它们链接到最后的图书馆。

这里有一个值得注意的陷阱:构建共享库时 便捷库,如果_SOURCES变量为空,Automake不知道使用哪个链接器,默认为C链接器。如果您想欺骗Automake使用某些特定语言的链接规则,您可以声明一个不必存在的nodist_EXTRA_..._SOURCES源文件。 (有关示例,请参阅Automake手册的Libtool Convenience Libraries部分。)

也许那是你的问题?如果您的某些模块的源代码中有一些Fortran文件(您的描述建议这些文件只是C文件),只有在声明的源文件中出现Fortran文件时,Fortran链接器才会用于构建libmain.la。那个libtool库。当libmain_la_SOURCES为空时,将使用C链接器。

否则,我不知道它为什么不起作用。

您的示例中有一个小错误:

libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la

应该是

libmain_la_LIBADD = $(top_builddir)/src_module1/libmodule1.la

因为未在源目录中创建库。但是我认为这只是一个错字,除非你做VPATH构建或运行make distcheck,否则你不会看到差异。


你的第二次尝试,使用不带Libtool的_LIBRARIES预计不起作用 _LIBRARIES只能用于声明静态存档,在这种情况下,_LIBADD可能只包含目标文件,而不包含其他静态存档。解压缩存档以将其对象重用到另一个存档中可能很难移植。 Automake对此问题的回答一直是:安装Libtool并使用_LTLIBRARIES (Libtool可以配置为仅构建静态库)。