Search code examples
ubuntumakefileautotoolsautomakelibtool

How to build static and shared library with autotools?


I'm learning use the Autotools. I am writing my first program with these tools, but I havve a problem. I am trying to make program that uses two libraries: one static and one shared. I configured Makefile.am and configure.ac, but I don't know whether they are as they should be. When I run command make, it returns an error:

code.c:37: undefined reference to `function1'.

It gives such an error for every function. It seems that the program can't find headers or source files?

All my files are in one folder.

configure.ac

AC_PREREQ([2.69])
AC_INIT([code], [1.0])
LT_INIT
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([code.c])
AC_CONFIG_MACRO_DIRS([m4])
AC_PROG_CC 
AC_CHECK_HEADERS([stdio.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Makefile.am

ACLOCAL_AMFLAGS = -I m4

bin_PROGRAMS = code
code_SOURCES = code.c libcodes.la libcode.a libo.h libp.h

lib_LIBRARIES = libcode.a
libcode_a_SOURCES = functionsp.c

code_DEPENDENCIES = libcodes.la
lib_LTLIBRARIES = libcodes.la
libcodes_la_SOURCES = functionso.c
libcodes_la_LDFLAGS = -version-info 1:0:0
code_LDFLAGS = -rpath /usr/local/lib

Solution

  • It seems that the program can't find headers or source files?

    No, "undefined reference" is a link error. It means that the linker is trying to resolve a function call, but it doesn't see any implementation of the function. This usually implicates a problem with the libraries specified on the link command line.

    And indeed, the link-related settings in your Makefile.am are all wrong, and there are other, less-impactful issues, too.

    First, the libraries needed for linking a program but not located via configure should be specified in Makefile.am via the LDADD variable or a program-specific foo_LDADD variable. A foo_DEPENDENCIES variable does not serve this purpose -- its contents appear in the generated makefile as dependencies of the program target, but nowhere else. In particular, they are not included on the link command line. In practice, foo_DEPENDENCIES variables are rarely used.

    Libraries especially should not be specified as program sources. They aren't sources, and specifying them as such has no useful effect.

    Speaking of libraries, hardcoding an assumed library installation directory into your Makefile.am is poor form and setting yourself up for problems, as that directory can be specified by the user at configure and / or make time. Fortunately, each configurable installation directory has a corresponding variable the you can reference. In the case of the lib it is libdir.

    Also, as a matter of style, you seem to have organized your Makefile.am around build stages, but that is unusual, and I, at least, find it difficult to follow. Makefile.am files are more often organized around the targets named, often with all those targets specified first.

    Overall, then, you probably want something more like this:

    ACLOCAL_AMFLAGS = -I m4
    
    bin_PROGRAMS = code
    lib_LIBRARIES = libcode.a
    lib_LTLIBRARIES = libcodes.la
    
    code_SOURCES = code.c libo.h libp.h
    code_LDFLAGS = -rpath $(libdir)
    code_LDADD = libcodes.la libcode.a
    # or LDADD = libcodes.la libcode.a
    
    libcode_a_SOURCES = functionsp.c
    
    libcodes_la_SOURCES = functionso.c
    libcodes_la_LDFLAGS = -version-info 1:0:0