Search code examples
autotoolsglibautomakegobject

Automake config cannot compile my unit test


I'm new to C and Automake development. So this could be a stupid question.

I'm recently working on a C library that links to GLib and GObject. I've got my Makefile.am and configure.ac working through the compilation. However, when I tried to compile the unit test, a series of error occurs. The errors are similar to this:

src/.libs/libfoobar.so: undefined reference to `g_intern_static_string'
src/.libs/libfoobar.so: undefined reference to `g_once_init_enter'
src/.libs/libfoobar.so: undefined reference to `g_free'
src/.libs/libfoobar.so: undefined reference to `g_once_init_leave'
src/.libs/libfoobar.so: undefined reference to `g_type_name'
src/.libs/libfoobar.so: undefined reference to `g_value_set_string'
src/.libs/libfoobar.so: undefined reference to `g_type_class_adjust_private_offset'
src/.libs/libfoobar.so: undefined reference to `g_return_if_fail_warning'
src/.libs/libfoobar.so: undefined reference to `g_object_new'
src/.libs/libfoobar.so: undefined reference to `g_type_class_peek_parent'
src/.libs/libfoobar.so: undefined reference to `g_param_spec_string'
src/.libs/libfoobar.so: undefined reference to `g_type_check_class_cast'
src/.libs/libfoobar.so: undefined reference to `g_type_class_add_private'
src/.libs/libfoobar.so: undefined reference to `g_type_register_static_simple'
src/.libs/libfoobar.so: undefined reference to `g_log'
src/.libs/libfoobar.so: undefined reference to `g_value_dup_string'
src/.libs/libfoobar.so: undefined reference to `g_type_instance_get_private'
src/.libs/libfoobar.so: undefined reference to `g_object_class_install_properties'
collect2: error: ld returned 1 exit status

Where should I start looking to solve this?

Further information of my project:

Directory structure


  • /
    • src/
      • foobar-hello.c
      • foobar-hello.h
    • tests/
      • test-foobar-hello.c
    • Makefile.am
    • configure.ac
    • autogen.sh
    • README.md

Autotools related files

Makefile.am

ACLOCAL_AMFLAGS  = -I m4 ${ACLOCAL_FLAGS}
AUTOMAKE_OPTIONS = subdir-objects

# -- Common build flags --------------
AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)/src


# -- Library -------------------------
lib_LTLIBRARIES = src/libfoobar.la

src_libfoobar_la_SOURCES = \
        src/foobar-hello.c \
        $(NULL)

src_libfoobar_la_include_HEADERS = \
        src/foobar-hello.h \
        $(NULL)

src_libfoobar_la_includedir = $(includedir)/foobar


# -- Tests ---------------------------
check_PROGRAMS = \
        tests/test_foobar_hello \
        $(NULL)

tests_test_foobar_hello_SOURCES = tests/test-foobar-hello.c
tests_test_foobar_hello_LDADD = src/libfoobar.la

TESTS = $(check_PROGRAMS)


# -- Common --------------------------
CLEANFILES = \
        $(NULL)

EXTRA_DIST = \
        autogen.sh \
        README.md \
        $(NULL)

configure.ac

AC_PREREQ(2.63)
AC_INIT([libfoobar], [0.1], [https://github.com/foobar/libfoobar/issues], [libfoobar], [https://github.com/foobar/libfoobar])

AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar foreign])
AC_PROG_MKDIR_P

m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])

# Check library versions
# then substitute the revelant cflag with actual library information
PKG_CHECK_MODULES([GLIB],[glib-2.0 > 2.19.0])
AC_SUBST(GLIB_CFLAGS)

# Initialize libtool
LT_INIT([disable-static])

# OUTPUT files
AC_CONFIG_FILES([
  Makefile
])


AC_OUTPUT

Edited:

Solution

After reading ldavis's helpful answer, here is what I done:

  1. I've added these 2 lines in configure.ac:

    PKG_CHECK_MODULES([GOBJECT],[gobject-2.0])
    AC_SUBST(GOBJECT_CFLAGS)
    
  2. I changed the AM_CFLAGS line in Makefile.am:

    AM_CFLAGS = $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) -I$(top_srcdir)/src
    
  3. I added this line to Makefile.am:

    src_libfoobar_la_LIBADD = $(GLIB_LIBS) $(GOBJECT_LIBS)
    

It works like a charm.


Solution

  • You should start by looking at the error carefully:

    collect2: error: ld returned 1 exit status

    This tells you it's a linker error (ld is the linker).

    src/.libs/libfoobar.so: undefined reference to `g_intern_static_string'

    The linker cannot find a symbol in src/.libs/libfoobar.so (a shared library) which you are linking to your test program. So src/.libs/libfoobar.so is probably missing at least one dependent library, but probably two dependent libraries (the aformentioned libglib and libgobject). They need to be linked to libfoobar.so.

    Modern versions of the PKG_CHECK_MODULES macro are supposed to AC_SUBST foo_LIBS and foo_CFLAGS variables, (e.g. GLIB_LIBS and GLIB_CFLAGS). This needs to be added to the Makefile to link libglib:

    Makefile.am

    src_libfoobar_la_LDADD = $(GLIB_LIBS)
    

    This still won't link your test code, but you should have fewer errors. You'll need to PKG_CHECK_MODULES for libgobject in configure.ac, and plug in the corresponding GOBJECT_CFLAGS and GOBJECT_LIBS in the right places in Makefile.am.