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.
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With