Subject: bug#7621: add a way to pass link dependencies

From: Bruno Haible <[email-masked]>
Date: Sun, 12 Dec 2010 15:43:00 +0100

Hi,

When creating an executable or library, sometimes other libraries
have to be mentioned on the link command line as dependencies.

For dependencies inside the build tree, Automake handles this fine,
through the _LDADD variable for executables and the _LIBADD variable
for libraries. See e.g. the node "Linking" in the Automake manual.

But for dependencies on libraries installed on the system, Automake
does not provide a way to specify these link dependencies in a complete,
reliable, and simple way. Please consider adding support for this
to a future version of Automake.

Let's take an example: You want to link with the libiconv library,
which may be installed in /usr/lib, in /usr/local/lib, in /opt/gnu/lib,
or similar. GNU gettext has a macro AM_ICONV which finds the library
and defines Autoconf variables LIBICONV (for use without libtool) and
LTLIBICONV (for use with libtool) that contain the needed linker options
or libtool options, respectively. Similarly for other libraries.
The problem is that is no way to use these with Automake in a reliable
and simple way.

Let me clarify the requirements:

1) I want to use the value of LIBICONV or LTLIBICONV. Typical values
of LIBICONV are

    -liconv
    -Wl,-rpath,/usr/local/lib -L/usr/local/lib -liconv
    /usr/local/lib/libiconv.a
    -Wl,-rpath,/usr/local/lib /usr/local/lib/libiconv.so

Typical values of LTLIBICONV are

    -liconv
    -rpath /usr/local/lib -L/usr/local/lib -liconv
    /usr/local/lib/libiconv.a
    -rpath /usr/local/lib /usr/local/lib/libiconv.so
    /usr/local/lib/libiconv.la

In particular, I can't get away without -rpath options, otherwise
the created programs just won't run.

2) Linking with a static library should work in the same way as
linking with a shared library.

3) I want to be able to specify the link dependencies for every
program and library separately. I don't want to put them into $(LIBS),
because dependencies on unused shared libraries increase the startup
time for programs, and the --as-needed option of the GNU linker is not
portable and carries its own set of problems.[1]

4) I want to use the Automake-provided rules for linking. I don't want
to override them, because that would be a maintenance hassle as Automake
evolves.

Now in which Automake provided variable could I stuff these linker options
or libtool options?

How to reproduce:
In a package that already has a configure.ac that uses Automake but not
Libtool, do "mkdir foo" and save this text as foo/Makefile.am:
=============================== foo/Makefile.am ========================
bin_PROGRAMS = maude
lib_LIBRARIES = library.a

maude_CFLAGS = $(AM_CFLAGS)
maude_LDFLAGS = $(AM_LDFLAGS)
maude_LDADD = $(LDADD)

#library_a_CFLAGS = $(AM_CFLAGS) # not used in linking
#library_a_LDFLAGS = $(AM_LDFLAGS) # yields warning
library_a_LIBADD =
========================================================================
then do "automake foo/Makefile" and look at the generated Makefile.in file.

In a package that already has a configure.ac that uses Automake and Libtool,
do "mkdir foolt" and save this text as foolt/Makefile.am:
============================== foolt/Makefile.am =======================
bin_PROGRAMS = maudelt
lib_LTLIBRARIES = librarylt.la

maudelt_CFLAGS = $(AM_CFLAGS)
maudelt_LDFLAGS = $(AM_LDFLAGS)
maudelt_LDADD = $(LDADD)

librarylt_la_CFLAGS = $(AM_CFLAGS)
librarylt_la_LDFLAGS = $(AM_LDFLAGS)
librarylt_la_LIBADD =
========================================================================
then do "automake foolt/Makefile" and look at the generated Makefile.in file.

The generated link commands are (with expanded *_LINK and *_AR variables):

For maude:
  $(CCLD) $(maude_CFLAGS) $(CFLAGS) \
          $(maude_LDFLAGS) $(LDFLAGS) \
          -o $@ \
          $(maude_OBJECTS) \
          $(maude_LDADD) $(LIBS)

For library.a:
  $(AR) $(ARFLAGS) library.a $(library_a_OBJECTS) $(library_a_LIBADD)
  $(RANLIB) library.a

For maudelt:
  $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
  $(CCLD) $(maudelt_CFLAGS) $(CFLAGS) \
          $(maudelt_LDFLAGS) $(LDFLAGS) \
          -o $@ \
          $(maudelt_OBJECTS) \
          $(maudelt_LDADD) $(LIBS)

For librarylt.la:
  $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
  $(CCLD) $(librarylt_la_CFLAGS) $(CFLAGS) \
          $(librarylt_la_LDFLAGS) $(LDFLAGS) \
          -o $@ \
          -rpath $(libdir) \
          $(librarylt_la_OBJECTS) \
          $(librarylt_la_LIBADD) $(LIBS)

When creating library.a, one can ignore dependencies to libraries not in the
build tree. So we need consider only maude, maudelt, and librarylt.la.
Where could I stuff the linker options or libtool options?

- Can I put them in the *_LDFLAGS variable?

  No, it does not work, because if it's a static library (/somewhere/libiconv.a),
  the linker will not pick any object files from it, because it precedes
  the *_OBJECTS on the link command line. Ralf noticed that in [2].

- Can I put them in the *_LDADD variable for programs or *_LIBADD variable
  for libraries?

  No, because the options contain other things than -l and -L options, and
  these can't go in *_LDADD or *_LIBADD variables, says the Automake doc.
  [3][4][5]
  I understand that the true reason for this requirement is that Automake
  wants to compute a *_DEPENDENCIES variable from *_LDADD or *_LIBADD variables:

    "If `PROG_DEPENDENCIES' is not supplied, it is computed by Automake.
     The automatically-assigned value is the contents of `PROG_LDADD', with
     most configure substitutions, `-l', `-L', `-dlopen' and `-dlpreopen'
     options removed.  The configure substitutions that are left in are only
     `$(LIBOBJS)' and `$(ALLOCA)'; these are left because it is known that
     they will not cause an invalid value for `PROG_DEPENDENCIES' to be
     generated.

    "If `_DEPENDENCIES' is not supplied, it is computed by Automake.
     The automatically-assigned value is the contents of `_LDADD' or
     `_LIBADD', with most configure substitutions, `-l', `-L',
     `-dlopen' and `-dlpreopen' options removed.  The configure
     substitutions that are left in are only `$(LIBOBJS)' and
     `$(ALLOCA)'; these are left because it is known that they will not
     cause an invalid value for `_DEPENDENCIES' to be generated."

  Additionally, for libraries, the description of LIBADD is strict
  about the fact that it "should be used to list extra libtool objects
  (.lo files) or libtool libraries (.la) to add to library."

- Can I put them in LIBS?

  No, I explained above why I don't want this.

Please offer a simple way to use these linker options.

I can see two choices:

 A) Either allow -Wl,-rpath or -rpath options also in *_LDADD variables,
    and allow -Wl,-rpath, -rpath, -l, -L options also in *_LIBADD variables
    of libraries built with libtool.

 B) Or introduce a new set of variables *_LIBS that can contain link options
    for dependencies, like $(LIBICONV) and $(LTLIBICONV) above. Modify the
    link commands to look like this:

    For maude:
      $(CCLD) $(maude_CFLAGS) $(CFLAGS) \
              $(maude_LDFLAGS) $(LDFLAGS) \
              -o $@ \
              $(maude_OBJECTS) \
              $(maude_LDADD) $(maude_LIBS) $(LIBS)

    For maudelt:
      $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
      $(CCLD) $(maudelt_CFLAGS) $(CFLAGS) \
              $(maudelt_LDFLAGS) $(LDFLAGS) \
              -o $@ \
              $(maudelt_OBJECTS) \
              $(maudelt_LDADD) $(maudelt_LIBS) $(LIBS)

    For librarylt.la:
      $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
      $(CCLD) $(librarylt_la_CFLAGS) $(CFLAGS) \
              $(librarylt_la_LDFLAGS) $(LDFLAGS) \
              -o $@ \
              -rpath $(libdir) \
              $(librarylt_la_OBJECTS) \
              $(librarylt_la_LIBADD) $(librarylt_la_LIBS) $(LIBS)

Note that solution A) would have the drawback of an inconsistency between
library_a_LIBADD and librarylt_la_LIBADD: library_a_LIBADD must not contain
link dependencies (see [6]).

Bruno

[1] http://www.gentoo.org/proj/en/qa/asneeded.xml
[2] http://lists.gnu.org/archive/html/bug-gnulib/2006-09/msg00146.html
[3] http://lists.gnu.org/archive/html/bug-gnulib/2006-09/msg00141.html
[4] http://www.gnu.org/software/automake/manual/html_node/Linking.html
[5] http://www.gnu.org/software/automake/manual/html_node/A-Library.html
[6] http://lists.gnu.org/archive/html/bug-gnulib/2006-09/msg00054.html