2012-11-28 19 views
7

私はMac上でうまくコンパイルされるautotoolsプロジェクトを持っていますが、Linux(Ubuntu 12.04.1 LTS)ではコマンドラインにgccが渡され、ファイル。私はからコンパイルする場合は、しかし、Automakeを使用してGCCコマンドラインの順序を修正する

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

:たとえば、autotoolsのは、私のコードをコンパイルするには、次のコマンドを生成し、testという名前のバイナリにtest.cという名前の単一のファイル:

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 

は、このコマンドラインはで失敗しますコマンドラインを開き、ライブラリ参照がオブジェクトファイルの後にあるようにしてください。

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 

チャレンジi Autotoolsに正しい順序でコマンドラインを生成させる方法を理解することはできません。わかりやすくするために、ここでは簡単なテストケースを再現しました。最初に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 

次に簡単Makefile.amある:

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

最後に、ソースコードのこの最小のテストケース、test.cに:

#include <glib.h> 

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

コンパイルがその後使用して達成されます次の一連のコマンド:

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

私はコードがコンパイルされない理由を理解していますが、automakeにコマンドラインの最後にライブラリを置く方法が不思議です。gccが正しく実行されてリンクされます。 Mac OS X Lionのgccにこの問題はないようです。

+1

"Mac OS X Lionのgccではこの問題はないようです。"これは、アップル社がGCC 4.2のフォークを使用しているのに対し、この動作は新しいバージョンのGCC(GCC 4.5のIIRC)で導入されたためです。 –

答えて

10

溶液は、LDFLAGSLDADDの間の差であることが判明した。つまり、コマンドラインのオブジェクトファイルの前にLDFLAGSが追加され、後でLDADDが追加されます。したがって、次のようにMakefile.amを変更すると、問題を解決:

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

それだけで解決するために、職場でGCCの開発者を追跡しました。また、私が提供したこの例は、ある程度の自動ツールの文脈で定義された意味を持っているので、やや貧弱です。

+2

automakeのドキュメントには、LDADDが '-l'フラグの間違った場所であることが明確に記載されています。これは機能しますが、正しいにおいはしません。 –

+3

@William: "PROG_LDADD"は、プログラム固有のリンカフラグ(**は '-l'、' -L'、 '-dlopen'、および' -dlpreopen'には**を除く)を渡すのには不適切です。 – adl

+0

@adl 1.11.1(8.1.2項)のマニュアルには、ドキュメント内の例外はありません。なぜこの例外が受け入れられるようになったのか知っていますか?それとも、それはいつも大丈夫ですか? –

0

私は同様の問題を解決しました。問題の./configureスクリプトは、シンボルの欠落による関数の存在のチェックを完了できませんでした。 $LDFLAGSなどに正しいライブラリを追加した場合は、.cファイルの前にライブラリが追加され、ライブラリは無視されます。

関数の名前をチェックする最初ac_func_listに添加し、それらの各々についてac_fn_c_check_func()を呼び出し、交互にそのチェック機能ac_fn_c_try_link(ac_fn_c_try_link()

を呼び出すこと./configureの体内のループが存在している)をこのパターンのコマンドを使用しています。

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

$LDADDは完全にここでは無視されます。したがって、ここでの唯一の解決策は、変数$LIBS-lフラグを追加することです。

関連する問題