Search code examples
cshared-librariesautotoolsautomake

How to handle library dependencies with automake?


Let's assume the following project structure composed of one executable in src and two libraries, lib1 and its dependency lib1_dep:

  +--src/
  |   |
  |   +--Makefile.am
  |   +--main.c
  |
  +--lib/
  |   |
  |   +--Makefile.am
  |   +--library1.c
  |   +--library1.h
  +--lib_dep/
  |   |
  |   +--Makefile.am
  |   +--library1_dep.c
  |   +--library1_dep.h
  +--Makefile.am
  +--configure.ac

The contents of the files are

configure.ac

# Add libraries dependance
AC_CONFIG_SUBDIRS([lib_dep])
AC_CONFIG_SUBDIRS([lib])

# Add src files
AC_CONFIG_FILES([Makefile
     lib_dep/Makefile
     lib/Makefile
     src/Makefile
     ])

Makefile.am

SUBDIRS = lib_dep lib src

lib1_dep/Makefile.am

lib_LTLIBRARIES = lib_libdep.la
# Dynamic library
lib_libdep_la_SOURCES = library1_dep.c library1_dep.h
lib_libdep_la_LIBADD = 
# Compiler options.
lib_libdep_la_CPPFLAGS = $(AM_CPPFLAGS) 

lib1/Makefile.am

lib_LTLIBRARIES = lib_lib.la

# Dynamic library
lib_lib_la_SOURCES = library1.c library1.h
lib_lib_la_LIBADD = $(top_builddir)/lib_dep/lib_libdep.la
# Compiler options.
lib_lib_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib_dep/lib_dep.h

src/Makefile.am

bin_PROGRAMS = main

main_SOURCES = main.c

main_LDADD = $(AM_LDADD) $(top_builddir)/lib/lib_lib.la  $(top_builddir)/lib_dep/lib_libdep.la
# Compiler options.
main_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib_dep/lib_dep.h -I$(top_srcdir)/lib/lib_lib.h

Observation

The build and install work well but I doubt I do it properly. The main program only uses functions defined in lib (not in lib_dep), so it looks strange that I have to also diretly link the main program to lib_dep. I would like your feedbacks on this please.

Question

Is there a way to build/compile lib so that I don't have to add the LDAPP and CPPFLAGS related to lib_dep when I build y main program (src/Makefile.am) ?

Thanks


Solution

  • The build and install work well but I doubt I do it properly. The main program only uses functions defined in lib (not in lib_dep), so it looks strange that I have to also diretly link the main program to lib_dep. I would like your feedbacks on this please.

    It is system-dependent whether indirect shared-library dependencies need to be included in the link. On Linux, they do. Compare to the situation with static library dependencies, which absolutely need to be included in the final link, on any system.

    However, since you are using libtool, in a context where you can rely on its generated .la files to be available, you shouldn't need to provide explicitly for linking indirect dependencies. Libtool can handle that for you.

    Is there a way to build/compile lib so that I don't have to add the LDAPP and CPPFLAGS related to lib_dep when I build y main program (src/Makefile.am) ?

    That's actually two separate questions, one for LDADD and one for CPPFLAGS.

    1. The CPPFLAGS are relevant only for compilation, not linking. Roughly speaking, if the main program's sources #include any headers from lib_dep/, whether directly or indirectly, then it is necessary for its CPPFLAGS to contain an -I flag for that directory. Otherwise, not.

      An indirect inclusion would be if main.c includes library1.h and library1.h includes library1_dep.h.

    2. Since you are using libtool to build both libraries, and consistently declaring link dependencies by putting the appropriate libtool archives in the LIBADD / LDADD variables, you do not need to specify the indirect library dependency in the main program's LDADD. libtool can and will figure out the indirect library dependency and add it to the main program's link if needed, and at the correct location in the link command.

    Thus, if the main program has neither a compile-time dependency nor a direct link dependency on libdep, then its Makefile.am could look like this:

    bin_PROGRAMS = main
    
    main_SOURCES = main.c
    
    main_LDADD = $(top_builddir)/lib/lib_lib.la
    main_CPPFLAGS = -I$(top_srcdir)/lib
    

    NOTE: it is not wrong to add $(AM_LDADD) to main_LDADD or to add $(AM_CPPFLAGS) to main_CPPFLAGS, as in the version of this Makefile.am presented in the question, but that is useful only if you've actually defined values for those AM_* variables.

    NOTE2: Your -I flags should specify directories to search for header files, not the names of specific header files.