0

I am trying to implement with Autotools a “multiversion option” for my shared library: in case the user enables it, the library must be able to cohabitate with other versions of itself. That means that the name of the binary must contain the version string, or at least any string that distinguishes it from other versions.

libtool has an option, -release, which does exactly that. However, as explained here, this will not work for my purpose, because at least one file will not have any suffix appended and this will create conflicts with other versions of the package:

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

The paragraph I just quoted contains also a general solution for this problem, which is to manually append a suffix to the name of the binary file. However this can be a tiring task to do if the library changes version often, and for sure does not suit my case, where a suffix must be appended only if the user enables an option.

I have been able to prepare the environment in configure.ac so that the following two variable substitutions are set to an empty string if the “multiversion option” is disabled, and when it is enabled they are set as:

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

But when I try to export these substitutions to src/Makefile.am, as in the following example,

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 = 

I get the following error messages from 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)

After doing a bit of research I have found several packages that do exactly what I have tried to do (#1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11). I have found also this similar question on stackoverflow, but the answers do not help much. I have even found an article in the official guide of Automake that proposes an example very similar to what I want to do, but if I try to copy and paste it verbatim I still get the same error messages.

On the other hand this other article from the same guide states that

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.

However I am not putting a configure substitution into a _SOURCES variable, what I am trying to do is to get the name itself of a _SOURCES variable from a configure substitution. And I have found at least eleven packages that do exactly that.

So the question is: what am I doing wrong? Is anyone able to produce a minimal working example where the content of lib_LTLIBRARIES is taken from a configure substitution?

madmurphy
  • 1,451
  • 11
  • 20
  • In the first place, I think this is a bad idea. In the second place, however, the diagnostic messages you present are *warnings*, not errors, and they appear to have come from Automake (perhaps via `autoreconf`), not from `configure`. So have you tried ignoring the warnings (which are correct) and configuring and building your project anyway? It just might work. – John Bollinger Mar 24 '19 at 03:41
  • @JohnBollinger Yes, I have tried to ignore the warnings of course: the substitutions are simply ignored and the strings inside the ‘at signs’ left verbatim. I don't know why you think it is a bad idea, configure substitutions are born exactly for doing these kind of things. – madmurphy Mar 24 '19 at 05:03
  • 1
    Configure substitutions are for related things, but they are not for *this* thing. The names of build targets ought to be available to Automake, not determined at build time. But it is a bad idea moreso because library names should be *consistent*. if you put version numbers into a project's library base names then you should always do it for that project's libraries. This is not something that should be selectable at build time. – John Bollinger Mar 24 '19 at 17:18
  • @JohnBollinger I have found [the answer to my question](https://stackoverflow.com/questions/55316957/use-a-configure-substitution-in-lib-ltlibraries/55349592#55349592). However, concerning your question if it is a bad idea or not, I find it solves easily the dilemma of how to name the `.so` files of a library, and plenty of packages use the substitution above. If you want to see how I have implemented my “multiversion option” you can have a look at [my library](https://github.com/madmurphy/libconfini/) (see [INSTALL](https://github.com/madmurphy/libconfini/blob/master/INSTALL) for more info). – madmurphy Mar 26 '19 at 04:00

3 Answers3

1

I don't understand why -release won't work for you, so I'll just leave that solution out of this answer. The procedure is similar, but will create different .so file names (e.g. libfoo-1.2.so and libfoo.so) but the same .a name.

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 creates libfoo.so.0.0.0 (on Linux where versioning is on by default). ./configure --enable-multi ; make creates libfoo-1.2.so.0.0.0

This doesn't give me the warnings you were seeing. When I try using AC_SUBST I see the same warnings; it builds the libraries OK.

ldav1s
  • 15,885
  • 2
  • 53
  • 56
  • Thank you, ldav1s. I have found the reason behind the warnings (you can find the explanation in [my answer](https://stackoverflow.com/questions/55316957/use-a-configure-substitution-in-lib-ltlibraries/55349592#55349592)). Your solution will work. However in the end I have opted for using an environment variable to be passed to `autoconf` rather than to `./configure`. In this way I can obtain a literal for the package name to use in `AC_INIT()` (see my project's [INSTALL](https://github.com/madmurphy/libconfini/blob/master/INSTALL) file for more info). – madmurphy Apr 19 '19 at 05:38
0

I have found the answer to my question. If I use the same configure substitution for both the content of lib_LTLIBRARIES and the names of libXXX_la_SOURCES libXXX_la_LDFLAGS libXXX_la_LIBADD, everything seems to work fine, as in the following scenario:

Content of configure.ac:

...

AC_SUBST([CUSTOM_NAME], [foo])

...

Content of 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 = 

...

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. So, the following scenario is not accepted:

Content of configure.ac:

...

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

...

Content of 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 =

...
madmurphy
  • 1,451
  • 11
  • 20
0

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

Hi, I've just found how to resolve this issue, it seems to work. If variable is defined as a substitution with AC_SUBST, it can be reassigned between lines in 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)
Алр
  • 11
  • 3