2012-11-28 11 views
7

Mam projekt autotools, który kompiluje się dobrze na Macu, ale pod Linuksem (Ubuntu 12.04.1 LTS) wiersze poleceń przekazane do gcc mają biblioteki niesprawne względem obiektu akta. Na przykład autotools generuje następujące polecenie, aby skompilować mój kod, pojedynczy plik o nazwie test.c w binarny o nazwie test:Korygowanie zamawiania wiersza poleceń GCC za pomocą Automake

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 

Ten wiersz polecenia nie powiedzie się z:

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

Jednakże, jeśli mogę skompilować z wiersz poleceń i przełączyć go tak, odniesienie biblioteki po pliki obiekt to działa dobrze:

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 

wyzwanie i s nie mogę wymyślić, jak zmusić Autotools do wygenerowania linii poleceń we właściwej kolejności. Ze względu na jasność przedstawiłem tutaj prosty przypadek testowy. Najpierw jest 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 

Dalej jest prosta Makefile.am:

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

Wreszcie, kod źródłowy do tego minimalnego przypadku testowego, test.c:

#include <glib.h> 

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

Kompilacja zostaje osiągnięty za pomocą następująca seria poleceń:

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

Powinienem być jasny, rozumiem, dlaczego mój kod się nie skompiluje, po prostu zastanawiam się, jak uzyskać automake, aby umieścić biblioteki na końcu wiersza poleceń, aby gcc zostało wykonane i poprawnie połączyć. Należy zauważyć, że gcc na Mac OS X Lion wydaje się nie mieć tego problemu.

+1

"gcc na Mac OS X Lion wydaje się nie mieć tego problemu." - nie, ponieważ Apple używa widelca GCC 4.2, podczas gdy to zachowanie zostało wprowadzone w nowszej wersji GCC (IIRC w GCC 4.5). –

Odpowiedz

10

Rozwiązanie okazało się być różnicą między LDFLAGS i LDADD. W skrócie LDFLAGS jest dodawany przed plikami obiektowymi w wierszu poleceń, a następnie dodaje się LDADD. Zatem, zmieniając Makefile.am do dalszej rozwiązać problem:

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

Wystarczyło tropienia programistą GCC w pracy rozwiązać. Podany przeze mnie przykład jest raczej słaby, ponieważ test ma określone znaczenie w niektórych kontekstach autotools.

+2

Należy zauważyć, że dokumentacja automake wyraźnie stwierdza, że ​​LDADD jest niewłaściwym miejscem dla flag '-l'. Chociaż to działa, nie ma dobrego zapachu. –

+3

@William: Doktor Automake mówi, że '' PROG_LDADD' jest niewłaściwe dla przekazywania specyficznych dla programu znaczników linkerów (** except ** dla '-l',' -L', '-dlopen' i' -dlpreopen'). " – adl

+0

@adl Wyjątek w dokumentacji nie występuje w dokumentacji dla 1.11.1 (sekcja 8.1.2). Czy wiesz, dlaczego ten wyjątek stał się akceptowalny? A może zawsze było w porządku, po prostu nieudokumentowane? –

0

Rozwiązałem podobny problem. Skrypt ./configure nie mógł ukończyć sprawdzania obecności funkcji z powodu brakującego symbolu. Jeśli dodałem poprawną bibliotekę do $LDFLAGS lub coś podobnego, została ona dodana przed plikiem .c, a biblioteka została zignorowana.

Nazwy funkcji do sprawdzenia są dodawane pierwszy ac_func_list a następnie jest pętla w korpusie ./configure że dla każdego z nich nazywa ac_fn_c_check_func() a to z kolei wywołuje ac_fn_c_try_link()

ac_fn_c_try_link funkcja sprawdzania() używa polecenia o tym wzorze:

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

$LDADD jest całkowicie ignorowany tutaj. Dlatego jedynym rozwiązaniem jest dodanie flag do zmiennej $LIBS.