我有一个autotools项目可以在Mac上编译得很好,但在Linux(Ubuntu 12.04.1 LTS)下,传递给gcc
的命令行使得库相对于目标文件无序。例如,autotools生成以下命令来编译我的代码,将名为test.c
的单个文件编译为名为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
此命令行失败并显示:
/home/user/glib-test/test.c:4: undefined reference to `g_malloc`
/home/user/glib-test/test.c:5: undefined reference to `g_free`
但是,如果我从命令行编译并将其切换,以便库引用位于目标文件之后,它可以正常工作:
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
挑战在于我无法弄清楚如何强制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
似乎没有这个问题。
答案 0 :(得分:14)
解决方案是LDFLAGS
和LDADD
之间的区别。简而言之,在命令行上的目标文件之前添加LDFLAGS
,然后添加LDADD
。因此,将Makefile.am
更改为以下内容可解决问题:
CFLAGS=-Wall
bin_PROGRAMS=test
test_CFLAGS=$(GLIB_CFLAGS)
test_LDADD=$(GLIB_LIBS)
test_SOURCES=test.c
只需跟踪GCC开发人员的工作即可解决。另外,我提供的这个例子相当差,因为test
在autotools的某些上下文中具有已定义的含义。
答案 1 :(得分:0)
我解决了类似的问题。由于缺少符号,有问题的./configure脚本无法检查是否存在函数。如果我将正确的库添加到$LDFLAGS
等,则会在.c
文件之前添加它,并忽略库。
要检查的函数的名称首先添加到ac_func_list
,然后./configure
的正文中有一个循环,每个循环调用ac_fn_c_check_func ()
,然后轮流调用ac_fn_c_try_link ()
检查功能ac_fn_c_try_link()使用此模式的命令:
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS \
$LDFLAGS conftest.$ac_ext $LIBS >&5'
这里完全忽略了 $LDADD
。因此,此处唯一的解决方案是将-l
标志添加到变量$LIBS
。