2

我遇到的问题解决了。我发布此内容是为了就解决方案实际有效的原因寻求解释。我以前在这里得到了很好的反馈。

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

src_module1/
src_module2/
...
testc/
testf77/

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

我的第一种方法是分别从每个 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更改为. 同样的问题。然而,这一次,在尝试链接 libmain.a 本身时,注意到错误“ranlib:库警告:libmain.a 目录为空(库中没有目标文件成员定义全局符号)”。.a_LTLIBRARIES_LIBRARIES

我发现的解决方案似乎是一个 hack。我没有为任何 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 --- 那里会发生什么?关于静态和共享库的 Wikipedia 文章对我来说还不够详细。

我非常感谢为理解我冗长的问题所做的一切努力。

4

1 回答 1

2

您首先尝试的应该有效。我一直在使用这种设置(在 C++ 上下文中)。它也被记录在案,并且是 Automake 测试套件的一部分(尽管可能不是 Fortran)。

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

当多个 libtool 便利库被 LIBADDed 到一个可安装的libtool 库(例如您libmain.la的 .

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

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

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

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

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

应该

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

因为该库不是在源目录中创建的。但是我认为这只是一个错字,除非您执行 VPATH build 或 run ,否则您不会看到差异make distcheck


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

于 2011-04-08T15:50:42.540 回答