Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correcting the GCC command line ordering using Automake

I have an autotools project that compiles just fine on the Mac, but under Linux (Ubuntu 12.04.1 LTS) the command lines passed to gcc have the libraries out of order relative to the object files. For example, autotools generates the following command to compile my code, a single file named test.c into a binary named test:

gcc -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -lglib-2.0 -o test test-test.o

This command line fails with:

/home/user/glib-test/test.c:4: undefined reference to `g_malloc`
/home/user/glib-test/test.c:5: undefined reference to `g_free`

However, if I compile from the command line and switch it up so the library reference is after the object files it works just fine:

gcc -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -o test test-test.o -lglib-2.0

The challenge is that I can't figure out how to force Autotools to generate the command line in the right order. For the sake of clarity, I've reproduced the simple test case here. First up is configure.ac:

dnl Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT(glib-test, 1.0)

AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()

AC_PROG_CC
AM_PROG_CC_C_O
PKG_CHECK_MODULES(GLIB, glib-2.0 > 2.0)
AC_CONFIG_FILES(Makefile)
AC_OUTPUT

Next is the simple Makefile.am:

CFLAGS=-Wall
bin_PROGRAMS=test
test_CFLAGS=$(GLIB_CFLAGS)
test_LDFLAGS=$(GLIB_LIBS)
test_SOURCES=test.c

Finally, the source code to this minimal test case, test.c:

#include <glib.h>

int main(int argc, char **argv) {
    gchar *foo = g_malloc(100);
    g_free(foo);
    return 0;
}

Compilation is then achieved using the following series of commands:

touch NEWS README AUTHORS ChangeLog
aclocal
autoconf
automake --add-missing
./configure
make

I should be clear, I understand why my code won't compile, I'm just wondering how to get automake to put the libraries at the end of the command line so gcc will execute and link properly. It should be noted that gcc on Mac OS X Lion doesn't seem to have this problem.

like image 246
Pridkett Avatar asked Nov 28 '12 17:11

Pridkett


2 Answers

The solution turned out to be the difference between LDFLAGS and LDADD. In short LDFLAGS is added before the object files on the command line and LDADD is added afterwards. Thus, changing Makefile.am to the following solved the problem:

CFLAGS=-Wall
bin_PROGRAMS=test
test_CFLAGS=$(GLIB_CFLAGS)
test_LDADD=$(GLIB_LIBS)
test_SOURCES=test.c

It only took tracking down a GCC developer at work to solve. Also, this example I provided is rather poor because test has a defined meaning in some contexts of autotools.

like image 77
Pridkett Avatar answered Nov 07 '22 12:11

Pridkett


I solved a similar problem. The ./configure script in question was unable to complete a check for presence of a function due to a missing symbol. If I added the correct library to $LDFLAGS or such like, it was added before the .c file and the library was ignored.

The names of functions to check are first added to ac_func_list and then there is a loop in the body of the ./configure that for each of them calls ac_fn_c_check_func () and that in turns calls ac_fn_c_try_link ()

the checking function ac_fn_c_try_link () uses a command of this pattern:

ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS \
         $LDFLAGS conftest.$ac_ext $LIBS >&5'

$LDADD is completely ignored here. Therefore the only solution here is to add the -l flags to variable $LIBS.

like image 45
user7610 Avatar answered Nov 07 '22 13:11

user7610