Search code examples
autotoolsconfigureautomakelibtoolmultiple-versions

Use a configure substitution in `lib_LTLIBRARIES`


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@[email protected]

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?


Solution

  • 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@[email protected]
    
    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@[email protected]
    
    lib@ANOTHER_NAME@_la_SOURCES = \
        foo.c
    
    lib@ANOTHER_NAME@_la_LDFLAGS = \
        -version-info "2:0:0"
    
    lib@ANOTHER_NAME@_la_LIBADD =
    
    ...