在 `lib_LTLIBRARIES` 中使用配置替换

Posted

技术标签:

【中文标题】在 `lib_LTLIBRARIES` 中使用配置替换【英文标题】:Use a configure substitution in `lib_LTLIBRARIES` 【发布时间】:2019-08-14 11:08:09 【问题描述】:

我正在尝试使用 Autotools 为我的共享库实现“多版本选项”:如果用户启用它,该库必须能够与自身的其他版本共存。这意味着二进制文件的名称必须包含版本字符串,或者至少包含任何将其与其他版本区分开来的字符串。

libtool 有一个选项,-release,正是这样做的。但是,正如here 所解释的那样,这对我的目的不起作用,因为至少一个文件不会附加任何后缀,这会与包的其他版本产生冲突:

4.3。多个库版本

虽然 libtool 旨在处理多个 在系统上实现相同 API(甚至 ABI)的库, 分发使这种必要性变得毫无意义。另一方面,它不是 要安装多个版本的库是不常见的, 实现了多个 API,允许消费者选择他们支持的 版本。例如,Gtk+ 和 Glib 就是这种情况。

第一反应是将-release-release 这两个选项结合起来 -version-info;但是,这是错误的。当使用-release 静态存档,带有.a 扩展名的文件,libtool 存档(参见 Section 6, “Libtool Archives”) 和 .so 使用的文件 链接编辑器不会附加修订,这意味着两个 不同版本的库不能同时安装。

在这种情况下,最好的选择是附加库的一部分 版本信息到库的名称,例如 油嘴滑舌的libglib-2.0.so.0 soname。为此,声明中的 Makefile.am 必须是这样的:

lib_LTLIBRARIES = libtest-1.0.la

libtest_1_0_la_LDFLAGS = -version-info 0:0:0

我刚才引用的那段也包含了这个问题的通用解决方案,就是手动给二进制文件的名字加上后缀。但是,如果库经常更改版本,这可能是一项很累人的任务,并且肯定不适合我的情况,其中必须附加后缀只有在用户启用选项时

我已经能够在configure.ac 中准备环境,以便在禁用“多版本选项”时将以下两个变量替换设置为空字符串,并在启用时将它们设置为:

AC_SUBST([LIBRARY_SUFFIX_1], [-1.2])
AC_SUBST([LIBRARY_SUFFIX_2], [_1_2])

但是当我尝试将这些替换导出到src/Makefile.am 时,如下例所示,

lib_LTLIBRARIES = libfoo@LIBRARY_SUFFIX_1@.la

libfoo@LIBRARY_SUFFIX_2@_la_SOURCES = \
    foo.c

libfoo@LIBRARY_SUFFIX_2@_la_LDFLAGS = \
    -version-info "2:0:0"

libfoo@LIBRARY_SUFFIX_2@_la_LIBADD = 

我从configure 收到以下错误消息:

src/Makefile.am:17: warning: variable 'libfoo@LIBRARY_SUFFIX_2@_la_SOURCES' is defined but no program or library has 'libfoo@LIBRARY_SUFFIX_2@_la' as canonical name (possible typo)
src/Makefile.am:23: warning: variable 'libfoo@LIBRARY_SUFFIX_2@_la_LIBADD' is defined but no program or library has 'libfoo@LIBRARY_SUFFIX_2@_la' as canonical name (possible typo)
src/Makefile.am:20: warning: variable 'libfoo@LIBRARY_SUFFIX_2@_la_LDFLAGS' is defined but no program or library has 'libfoo@LIBRARY_SUFFIX_2@_la' as canonical name (possible typo)

在做了一些研究之后,我发现了几个包,它们完全符合我的要求(#1、#2、#3、#4、#5、#6、@987654329 @、#8、#9、#10、#11)。我在 *** 上也找到了this similar question,但答案并没有多大帮助。我什至找到了一个article in the official guide of Automake,它提出了一个与我想要做的非常相似的示例,但是如果我尝试逐字复制并粘贴它,我仍然会收到相同的错误消息。

另一方面,this other article from the same guide 声明

您不能进行配置替换(例如,“@FOO@”或“$(FOO)” 其中FOO 通过AC_SUBST) 定义为_SOURCES 变量。这 原因有点难以解释,但足以说明 根本行不通。如果您尝试这样做,Automake 会报错。

但是我没有将配置替换放入_SOURCES 变量中,我想做的是从配置替换中获取_SOURCES 变量的名称本身。而且我发现至少有 11 个包可以做到这一点。

所以问题是:我做错了什么?有没有人能够生成一个最小的工作示例,其中lib_LTLIBRARIES 的内容来自配置替换?

【问题讨论】:

首先,我认为这是一个坏主意。然而,其次,您提供的诊断消息是警告,而不是错误,它们似乎来自 Automake(可能通过autoreconf),而不是来自configure。那么您是否尝试过忽略警告(这是正确的)并配置和构建您的项目?它可能会起作用。 @JohnBollinger 是的,我当然试图忽略警告:替换被简单地忽略,“at 符号”内的字符串逐字保留。我不知道你为什么认为这是一个坏主意,配置替换就是为做这些事情而生的。 配置替换是针对相关事物,但不是针对this事物。构建目标的名称应该对 Automake 可用,而不是在构建时确定。但这也是一个坏主意,因为库名称应该一致。如果您将版本号放入项目的库基名称中,那么您应该始终为该项目的库执行此操作。这不是在构建时应该选择的东西。 @JohnBollinger 我找到了the answer to my question。但是,关于您的问题是否是一个坏主意,我发现它很容易解决如何命名库的.so 文件的难题,并且很多包都使用上面的替换。如果您想了解我是如何实现“多版本选项”的,您可以查看my library(有关更多信息,请参阅INSTALL)。 【参考方案1】:

我不明白为什么 -release 对你不起作用,所以我将把这个解决方案从这个答案中排除。过程类似,但会创建不同的.so 文件名(例如libfoo-1.2.solibfoo.so)但.a 名称相同。

configure.ac

AC_INIT([myproject],[0.1],[project@example.com])
AC_PREREQ([2.69])
AC_CONFIG_SRCDIR([src/foo.c])
AC_PROG_CC
AC_ARG_ENABLE([multi], AS_HELP_STRING([--enable-multi], [Enable multi]))
AM_INIT_AUTOMAKE([1.15 foreign])
AM_PROG_LIBTOOL
AM_CONDITIONAL([MULTI_NAME], [test "x$enable_multi" = "xyes"])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Makefile.am

SRCS=src/foo.c
lib_LTLIBRARIES=
if MULTI_NAME
lib_LTLIBRARIES+=libfoo-1.2.la
libfoo_1_2_la_SOURCES=$(SRCS)
else
lib_LTLIBRARIES+=libfoo.la
libfoo_la_SOURCES=$(SRCS)
endif

./configure ; make 创建 libfoo.so.0.0.0(在 Linux 上默认启用版本控制)。 ./configure --enable-multi ; make 创建 libfoo-1.2.so.0.0.0

这并没有给我你看到的警告。当我尝试使用AC_SUBST 时,我看到了相同的警告;它可以构建库。

【讨论】:

谢谢你,ldav1s。我找到了警告背后的原因(您可以在my answer 中找到解释)。您的解决方案将起作用。但是最后我选择使用环境变量传递给autoconf,而不是./configure。通过这种方式,我可以获得要在AC_INIT() 中使用的包名称的文字(有关更多信息,请参阅我的项目的INSTALL 文件)。【参考方案2】:

我找到了问题的答案。如果我对lib_LTLIBRARIES内容libXXX_la_SOURCES libXXX_la_LDFLAGS libXXX_la_LIBADD名称 使用相同的配置替换,一切似乎都正常,因为在以下场景中:

configure.ac的内容:

...

AC_SUBST([CUSTOM_NAME], [foo])

...

src/Makefile.am的内容:

...

lib_LTLIBRARIES = lib@CUSTOM_NAME@.la

lib@CUSTOM_NAME@_la_SOURCES = \
    foo.c

lib@CUSTOM_NAME@_la_LDFLAGS = \
    -version-info "2:0:0"

lib@CUSTOM_NAME@_la_LIBADD = 

...

但是,由于某种原因,一旦我使用两个不同的配置替换,即使它们包含相同的文本,我也会收到上述错误。因此,不接受以下场景:

configure.ac的内容:

...

AC_SUBST([CUSTOM_NAME], [foo])
AC_SUBST([ANOTHER_NAME], [foo])

...

src/Makefile.am的内容:

...

lib_LTLIBRARIES = lib@CUSTOM_NAME@.la

lib@ANOTHER_NAME@_la_SOURCES = \
    foo.c

lib@ANOTHER_NAME@_la_LDFLAGS = \
    -version-info "2:0:0"

lib@ANOTHER_NAME@_la_LIBADD =

...

【讨论】:

【参考方案3】:

但是,由于某种原因,一旦我使用两个不同的配置替换,即使它们包含相同的文本,我也会收到上述错误

您好,我刚刚找到了解决此问题的方法,它似乎有效。如果变量被定义为 AC_SUBST 的替换,它可以在 Makefile.am 中的行之间重新分配

configure.ac:

  AC_SUBST(CAN, "whatever")
  AC_SUBST(SUFFIX1, ".foo")
  AC_SUBST(SUFFIX2, "_foo")

...

Makefile.am

CAN=@SUFFIX1@
lib_LTLIBRARIES = libmylib@CAN@.la
CAN=@SUFFIX2@
libmylib@CAN@_la_SOURCES=$(lib_la_SOURCES)
libmylib@CAN@_la_LDFLAGS=$(lib_la_LDFLAGS)
libmylib@CAN@_la_CFLAGS=$(lib_la_CFLAGS)
libmylib@CAN@_la_LIBADD=$(lib_la_LIBADD)

【讨论】:

以上是关于在 `lib_LTLIBRARIES` 中使用配置替换的主要内容,如果未能解决你的问题,请参考以下文章

Automake:如何在不安装的情况下构建共享库

设置自动工具库文件名并稍后引用

Automake + libtool:每个对象 CFLAGS 的模式规则?

LIBADD 不会在 ubuntu 上将一个 libtool 库添加到另一个库?

在 Sapera ++ 中使用相机配置文件

如何使用 PnP 配置引擎在 SharePoint Online 中配置发布页面?