在 `lib_LTLIBRARIES` 中使用配置替换

Use a configure substitution in `lib_LTLIBRARIES`

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

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

4.3. Multiple libraries versions

While libtool was designed to handle the presence of multiple libraries implementing the same API (and even ABI) on the system, distributions made that necessity moot. On the other hand, it is not uncommon for multiple versions of a library to be installed, with multiple API implemented, allowing consumers to pick their supported version. This is the case, for instance, of Gtk+ and Glib.

The first reaction would be to combine the two options, -release and -version-info; this would, though, be wrong. When using -release the static archive, the one with .a extension, the libtool archive (see Section 6, “Libtool Archives”) and the .so file used by the link editor would not have a revision appended, which means that two different version of the library can't be installed at the same time.

In this situation, the best option is to append part of the library's version information to the library's name, which is exemplified by Glib's libglib-2.0.so.0 soname. To do so, the declaration in the Makefile.am has to be like this:

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, #7, #8, #9, #10, #11). I have found also this similar question on Whosebug, but the answers do not help much. I have even found an article in the official guide of Automake 提出了一个与我想做的非常相似的示例,但是如果我尝试复制并逐字粘贴我仍然收到相同的错误消息。

另一方面this other article from the same guide指出

You can’t put a configure substitution (e.g., ‘@FOO@’ or ‘$(FOO)’ where FOO is defined via AC_SUBST) into a _SOURCES variable. The reason for this is a bit hard to explain, but suffice to say that it simply won’t work. Automake will give an error if you try to do this.

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

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

我找到了问题的答案。如果我对 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 =

...

我不明白为什么 -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 时,我看到了相同的警告;它可以构建库。

But, for some reason, as soon as I use two different configure substitutions, even when they contain the same text, I get the errors above

您好,我刚刚找到了解决此问题的方法,似乎可行。如果变量被定义为 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)