编译Linux下的库是一件痛苦的事情,这里主要阐述glib和wpa_supplicant库的编译,因各自的依赖关系,另外一些库要事先编译。glib依赖libffi和zlib,而wpa_supplicant依赖dbus和openssl。
总结下交叉编译几个常见的逻辑:
1. 指定CC为交叉编译器
2. 指定--prefix,如果不指定,会将宿主机PC上相应的库给覆盖了,如果是系统关键的库文件,那就会造成系统启动失败。解决办法只有一个一个找到被覆盖的文件,再从一台好的PC机上拷贝回来。注意这里要找到被修改的文件不是那么容易,也许只有看文件的修改日期,另要找到一台相同系统的机器也不是那么简单的。
3. 编译依赖其他库的package的时候(这里就是glib,它依赖libffi和zlib),要将依赖库的lib和include路径指定清楚,让编译器能够找到这些文件,如果头文件include找不到的话,那就会编译出错,报not found file or directory之类的错误;如果是库文件lib找不到的话,那就会在ld链接的时候出错,报undefined function之类的错误。
4. pkg-config和PKG_CONFIG_PATH的使用,网上已经有很详细的介绍了,这里不再细数。只是说明尽量用pkgconfig方式来指定依赖库和头文件的路径,在*.pc文件里面已经有很详细的定义,就不用在configure或者make的时候指定一串串长长的CFLAGS,LDFLAGS,-I,-L。
5. 在定义CFLAGS或者LDFLAGS的时候,尽量不要指定PC系统的目录,像/usr/lib,/usr/include之类。因为系统一般都是x86的库,如果被交叉编译的库链接的话会报错。
编译历程:
1. 需定义LIBFFI_LIBS, LIBFFI_CFLAGS, ZLIB_LIBS和ZLIB_CFLAGS这几个宏,否则会出现一下的错误。
make[4]: Entering directory `/home/joe/Downloads/glib-2.32.4/gobject'CCLD gobject-query./.libs/libgobject-2.0.so: undefined reference to `ffi_type_pointer'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_float'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_void'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_sint64'./.libs/libgobject-2.0.so: undefined reference to `ffi_prep_cif'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_uint32'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_double'./.libs/libgobject-2.0.so: undefined reference to `ffi_call'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_sint32'./.libs/libgobject-2.0.so: undefined reference to `ffi_type_uint64'collect2: ld returned 1 exit statusmake[4]: *** [gobject-query] Error 1make[4]: Leaving directory `/home/joe/Downloads/glib-2.32.4/gobject'make[3]: *** [all-recursive] Error 1make[3]: Leaving directory `/home/joe/Downloads/glib-2.32.4/gobject'make[2]: *** [all] Error 2make[2]: Leaving directory `/home/joe/Downloads/glib-2.32.4/gobject'make[1]: *** [all-recursive] Error 1make[1]: Leaving directory `/home/joe/Downloads/glib-2.32.4'make: *** [all] Error 2
2. 需编译安装libffi,否则会出现一下的错误:
configure: error: Package requirements (libffi >= 3.0.0) were not met:
No package 'libffi' foundConsider adjusting the PKG_CONFIG_PATH environment variable if youinstalled software in a non-standard prefix.
./configure: glib-compile-schemas not found这个问题挺奇怪,既然要编译glib,竟然还要先在PC上编译一个glib,然后编第二次使用第一次边出来的bin文件。 这个patch在这里做一个记录。
4. 定义linux-arm.cache文件作为参数--cache-file的值,手工指定:不能为交叉编译检查glib_cv_stack_grow, 应为交叉编译在PC上,不在板子里。类似其他一些值写进去,否则会有类似下面的错误:
checking for growing stack pointer...configure: error: cannot run test program while cross compiling
修改内容如下:
echo ac_cv_type_long_long=yes>$ARCH-linux.cacheecho glib_cv_stack_grows=no>>$ARCH-linux.cacheecho glib_cv_uscore=no>>$ARCH-linux.cacheecho ac_cv_func_posix_getpwuid_r=yes>>$ARCH-linux.cache
5. 在CFLAGS中指定-Wl,-rpath $(DESTDIR)/../obj/external/glib/gmodule/.libs/,否则会出现找不到gmodule.so的库文件的错误:
gmodule.so not foundglib编译过程中会引用先前编译出来的库文件,然而竟然没有找到,find了一下发现在make install之前这个库的位置,故而用-Wl -rpath在指定。
6. 编译openssl需要定义no-asm和shared,去掉-m64,否则会出现编译汇编失败和编译器不识别-m64的错误。
7. 编译wpa_supplicant需要禁止掉nl80211的编译,否则会提示错误:
netlink/genl/genl.h: No such file or directory如果指定系统/usr/include目录给CFLAGS,以提示genl.h的位置,这个问题是没有了,会出现其他问题,提示__asm__错误,原来定义/usr/include之后,有些头文件就到这个目录下去找,也就是找x86的头文件,这和arm的不兼容,故出现问题。也就是上面描述的总结5。
总结:
有时候编译UNIX库并没有想象中的那么简单,configure&make&make install永远不会是所有的过程,不同PC不同编译器会碰到不同的问题,在此做记录,与大家共勉。