首先,参考别人的文章,如下:
http://hi.baidu.com/9562512/blog/item/ee9af9d39351f73d970a16b8.html
接下来,根据自己的所需,记录下了步骤,以及所遇到的问题和解决方法。
注:本文的ARM交叉编译环境已搭建,这里不再赘述。(arm_v5t_le-gcc)
1. 建立目录,准备安装
q # mkdir /home/armroot
q # cd /home/armroot
q # mkdir tmp (用来存放源文件)
2. 安装glib
1) 下载最新版本:(这里下载了 glib-2.24.1.tar.gz)
http://ftp.gnome.org/pub/gnome/sources/glib/2.24/
2) 移动到tmp目录,进行解压,并进入glib目录:
q # mv glib-2.24.1.tar.gz /home/armroot/tmp
q # cd /home/armroot/tmp
q # tar xzvf glib-2.24.1.tar.gz
q # cd glib-2.24.1
3) 修改config.sub(为下一步作准备)
在运行configure之前,先打开config.sub,把arm_v5t_le加上,位置如下:
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | arm_v5t_le | avr32 /
4) 运行configure
Ø 命令格式如下:
NM=nm CC=arm_v5t_le-gcc ./configure --build=i686-linux --host=arm_v5t_le --prefix=/home/armroot glib_cv_stack_grows=no glib_cv_uscore=no ac_cv_func_posix_getpwuid_r=yes ac_cv_func_posix_getgrgid_r=yes ac_cv_lib_rt_clock_gettime=no glib_cv_monotonic_clock=yes
Ø 参数说明:
a) NM=nm :具体什么意思我也不清楚,好像是因为libtool脚本有一个bug,如果不写这个就会在编译的时候(LINK)报一个奇怪的错误,大概是多了一个 '|' 字符甚么的。(我不用这个也是可以的。。。)
b) CC=arm_v5t_le-gcc :指定使用arm_v5t_le-gcc作为编译器
c) --build=i686-linux :我们是在一台普通的686计算机的linux操作系统上进行编译动作
d) --host=arm_v5t_le :我们编译出来的东西要在arm平台的linux系统下运行
e) --prefix=/home/armroot:把编译出来的东东安装到/home/armroot
f) 下边这些指令,都是直接告诉configure脚本,不用去检测相关的东西。因为要检测这些能力,就需要运行configure脚本临时生成并使用指定编译器编译出来的程序,但是我们是要cross-compile,所以编译器编译出来的程序肯定是没法运行的,然后configure脚本就会报错。所以只好直接告诉configure脚本,别干这多余的事情了。至于什么应该是yes(目标系统支持)甚么应该是no(目标系统不支持),就要看经验了。。。
² glib_cv_stack_grows=no :目标编译器是否支持堆栈增长
² glib_cv_uscore=no :目标编译器是否支持下划线(别问,我也不明白)
² ac_cv_func_posix_getpwuid_r=yes :目标系统是否可以调用函数getpwuid_r
² ac_cv_func_posix_getgrgid_r=yes :目标系统是否支持API getgrgid_r
² ac_cv_lib_rt_clock_gettime=no :目标系统是否支持API clock_gettime
² glib_cv_monotonic_clock=yes :目标系统是否支持API monotonic_clock
5) 此时,可能会出现错误
q 错误提示:
checking for pkg-config... /opt/mv_pro_5.0/montavista/pro/bin/pkg-config
configure: error: *** pkg-config too old; version 0.16 or better required.
错误pkg-config版本太旧,提示使用0.16版本以上。
q 分析:
# cd /usr/bin/
# ls pkg*
pkg-config
# ./pkg-config --version
0.20
说明是pkg-config的路径没有弄好,查看环境变量:
# echo $PATH
/opt/mv_pro_5.0/montavista/pro/devkit/arm/v5t_le/bin:/opt/mv_pro_5.0/montavista/pro/bin:/opt/mv_pro_5.0/montavista/common/bin:/sbin:/usr/sbin:/usr/local/sbin:/opt/gnome/sbin:/root/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/games:/opt/gnome/bin:/opt/kde3/bin:/usr/lib/jvm/jre/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin
所以目前pkg-config的路径是/opt/mv_pro_5.0/montavista/pro/bin/pkg-config,查看版本确实是0.15.0
q 解决:
所以这里不需要去下载一个新的版本来进行安装,只需要重新配置环境变量即可。
由于本人是新手,对环境变量的理解和设置不是很熟悉,而上面的环境变量是设置arm交叉编译时设置的,所以这里有一种简单的方法就是在上面那个路径下,建立一个软连接即可,具体操作如下:
# cd /opt/mv_pro_5.0/montavista/pro/bin/
# ls pkg*
pkg-config
# mv pkg-config pkg-config-0.15
# ln -sf /usr/bin/pkg-config ./
# ls pkg*
pkg-config pkg-config-0.15
q 再次查看版本
# pkg-config --version
0.20
6) # make
7) # make install
3. 安装libxml2
1) 下载最新版本:(这里下载了 libxml2-2.7.4.tar.gz)
http://download.chinaunix.net/download/0007000/6095.shtml
2) 移动到tmp目录,进行解压,并进入glib目录:
q # mv glib-2.24.1.tar.gz /home/armroot/tmp
q # cd /home/armroot/tmp
q # tar xzvf libxml2-2.7.4.tar.gz
q # cd libxml2-2.7.4
3) 修改config.sub
在运行configure之前,先打开config.sub,把arm_v5t_le加上,位置如下:
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | arm_v5t_le | avr32 /
4) 运行configure,命令格式如下:
NM=nm CC=arm_v5t_le-gcc ./configure --build=i686-linux --host=arm_v5t_le --prefix=/home/armroot
5) # make
6) # make install
4. 安装gstreamer
1) 下载最新版本:(这里下载了 gstreamer-0.10.29.tar.gz)
http://gstreamer.freedesktop.org/src/
2) 移动到tmp目录,进行解压,并进入glib目录:
q # mv glib-2.24.1.tar.gz /home/armroot/tmp
q # cd /home/armroot/tmp
q # tar xzvf gstreamer-0.10.29.tar.gz
q # cd gstreamer-0.10.29
3) 修改config.sub
在运行configure之前,先打开config.sub,把arm_v5t_le加上,位置如下:
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | arm_v5t_le | avr32 /
4) 运行configure:
Ø 命令格式如下:
NM=nm CC=arm_v5t_le-gcc PKG_CONFIG_PATH=/home/armroot/lib/pkgconfig ./configure --build=i686-linux --host=arm_v5t_le --prefix=/home/armroot CFLAGS=-I/home/armroot/include --disable-registry --disable-loadsave --disable-gtk-doc ac_cv_func_register_printf_function=no --disable-tests --disable-valgrind --disable-debug --disable-gst-debug
Ø 参数说明:
根据gstreamer的文档,挂壁了registry和loadsave(--disable-registry,--disable-loadsave)以后,就不需要使用libxml2了,但是到底要不要用libxml2呢?如果不用会不会有什么问题呢???我就不知道了。
5) make
6) make install
5. 关于库文件的简单说明
按照上述步骤下来,是不会生成*.so(动态链接库),只生成/home/armroot/lib/下面的*.a(静态链接库)。
6. 写测试程序,进行测试
1) 写一个helloworld.c程序
[code=C/C++]
#include <gst/gst.h>
int main(int argc, char *argv[])
{
const gchar *nano_str;
guint major, minor, micro, nano;
gst_init(NULL, NULL);
gst_version(&major, &minor, µ, &nano);
if (nano == 1)
nano_str = "(CVS)";
else if (nano == 2)
nano_str = "(Prerelease)";
else
nano_str = "";
printf ("This program is linked against GStreamer %d.%d.%d %s/n", major, minor, micro, nano_str);
return 0;
}
[/code]
2) 编译
a) 根据开头所说的参考文章,其命令格式如下:
arm_v5t_le-gcc helloworld.c -I /home/armroot/include/glib-2.0 -I /home/armroot/lib/glib-2.0/include -I /home/armroot/include/gstreamer-0.10 -L /home/armroot/lib -l gstreamer-0.10 -l glib-2.0 -l gmodule-2.0 -l gobject-2.0 -l gthread-2.0 -o helloworld
b) 编译出错,错误如下:
/home/armroot/lib/libgstreamer-0.10.a(libgstreamer_0.10_la-gstsystemclock.o)(.text+0xb90): In function `gst_system_clock_get_internal_time': gstsystemclock.c: undefined reference to `clock_gettime' /home/armroot/lib/libgstreamer-0.10.a(libgstreamer_0.10_la-gstsystemclock.o)(.text+0xc74): In function `gst_system_clock_get_resolution': gstsystemclock.c: undefined reference to `clock_getres' /home/armroot/lib/libgstreamer-0.10.a(libgstreamer_0.10_la-gstutils.o)(.text+0x812c): In function `gst_util_get_timestamp': gstutils.c: undefined reference to `clock_gettime' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x8): In function `fetch_dlerror': /home/armroot/tmp/glib-2.24.1/gmodule/gmodule-dl.c:81: undefined reference to `dlerror' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x48): In function `_g_module_close': /home/armroot/tmp/glib-2.24.1/gmodule/gmodule-dl.c:134: undefined reference to `dlclose' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x178): In function `g_module_symbol': /home/armroot/tmp/glib-2.24.1/gmodule/gmodule-dl.c:147: undefined reference to `dlsym' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x604): In function `g_module_open': /home/armroot/tmp/glib-2.24.1/gmodule/gmodule-dl.c:99: undefined reference to `dlopen' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x6d0):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule-dl.c:116: undefined reference to `dlopen' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x960): In function `g_module_open': /home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:227: undefined reference to `g_scanner_new' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x96c):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:228: undefined reference to `g_scanner_input_file' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x994):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:230: undefined reference to `g_scanner_scope_add_symbol' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x9a8):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:232: undefined reference to `g_scanner_scope_add_symbol' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x9c0):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:234: undefined reference to `g_scanner_scope_add_symbol' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x9c8):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:271: undefined reference to `g_scanner_eof' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x9d8):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:238: undefined reference to `g_scanner_get_next_token' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0x9f4):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:242: undefined reference to `g_scanner_get_next_token' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0xa04):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:242: undefined reference to `g_scanner_get_next_token' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0xaf8):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:289: undefined reference to `g_scanner_destroy' /home/armroot/lib/libgmodule-2.0.a(gmodule.o)(.text+0xb78):/home/armroot/tmp/glib-2.24.1/gmodule/gmodule.c:253: undefined reference to `g_scanner_destroy' /home/armroot/lib/libgobject-2.0.a(gboxed.o)(.text+0x378): In function `IA__g_variant_get_gtype': /home/armroot/tmp/glib-2.24.1/gobject/gboxed.c:300: undefined reference to `g_variant_ref' /home/armroot/lib/libgobject-2.0.a(gboxed.o)(.text+0x37c):/home/armroot/tmp/glib-2.24.1/gobject/gboxed.c:300: undefined reference to `g_variant_unref' /home/armroot/lib/libgobject-2.0.a(gboxed.o)(.text+0x3c8): In function `IA__g_variant_type_get_gtype': /home/armroot/tmp/glib-2.24.1/gobject/gboxed.c:287: undefined reference to `g_variant_type_copy' /home/armroot/lib/libgobject-2.0.a(gboxed.o)(.text+0x3cc):/home/armroot/tmp/glib-2.24.1/gobject/gboxed.c:287: undefined reference to `g_variant_type_free' /home/armroot/lib/libgobject-2.0.a(gboxed.o)(.text+0x508): In function `IA__g_regex_get_type': /home/armroot/tmp/glib-2.24.1/gobject/gboxed.c:240: undefined reference to `g_regex_ref' /home/armroot/lib/libgobject-2.0.a(gboxed.o)(.text+0x50c):/home/armroot/tmp/glib-2.24.1/gobject/gboxed.c:240: undefined reference to `g_regex_unref' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x12d4): In function `IA__g_signal_add_emission_hook': /home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:932: undefined reference to `g_hook_alloc' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x130c):/home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:939: undefined reference to `g_hook_insert_before' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x1370):/home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:929: undefined reference to `g_hook_list_init' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x1454): In function `IA__g_signal_remove_emission_hook': /home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:967: undefined reference to `g_hook_destroy' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x3934): In function `_g_signals_destroy': /home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:1752: undefined reference to `g_hook_list_clear' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x78a0): In function `signal_emit_unlocked_R': /home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:3202: undefined reference to `g_hook_first_valid' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x78c4):/home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:3221: undefined reference to `g_hook_next_valid' /home/armroot/lib/libgobject-2.0.a(gsignal.o)(.text+0x7980):/home/armroot/tmp/glib-2.24.1/gobject/gsignal.c:3219: undefined reference to `g_hook_destroy_link' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x198): In function `g_mutex_trylock_posix_impl': /home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:187: undefined reference to `pthread_mutex_trylock' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x458): In function `g_private_new_posix_impl': /home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:269: undefined reference to `pthread_key_create' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x4cc): In function `g_private_set_posix_impl': /home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:281: undefined reference to `pthread_setspecific' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x4dc): In function `g_private_get_posix_impl': /home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:290: undefined reference to `pthread_getspecific' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x55c): In function `g_thread_create_posix_impl': /home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:326: undefined reference to `pthread_attr_setstacksize' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x694):/home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:355: undefined reference to `pthread_create' /home/armroot/lib/libgthread-2.0.a(gthread-impl.o)(.text+0x7ec): In function `g_thread_join_posix_impl': /home/armroot/tmp/glib-2.24.1/gthread/gthread-posix.c:385: undefined reference to `pthread_join' collect2: ld returned 1 exit status |
c) 错误分析:
全部都是“undefined reference to”这个错误,baidu或google一下:这类错误是在连接过程中出现的,可能有两种原因∶一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题。一般是在找不到相应的库文件的时候产生的。
难道是.a库没有链接对??
但是无论是头文件路径,还是库文件的搜索路径都是没错的,库也是存在的,不明白ING
。。。
对每个错误去搜索一下,看看情况在说。
d) 解决错误:
n undefined reference to `clock_gettime'
搜索,现成有答案:添加编译选项-lrt
再编译,和clock有关的几个错误都没有了。
n undefined reference to `dlerror'
搜索,现成有答案:添加编译选项-ldl
再编译,和dl有关的几个错误都没有了。
n undefined reference to `g_scanner_new'
搜索,找不到有类似的答案。
n 这里,我先把编译通过的命令格式贴出来,下面再解释:
arm_v5t_le-gcc -lrt -ldl helloworld.c -I /home/armroot/include/glib-2.0 -I /home/armroot/lib/glib-2.0/include -I /home/armroot/include/gstreamer-0.10 -L /home/armroot/lib -lgstreamer-0.10 -lgmodule-2.0 -lgobject-2.0 -lgthread-2.0 -lglib-2.0 -o helloworld
和上面的命令区别:
1) 添加-lrt
2) 添加-ldl
3) 把-lglib-2.0放到了几个库的最后面
编译通过,生成helloworld (哈哈)
7. 解决问题的尝试过程
1) 先在gcc环境,自己生成一个静态库,并使用
a) 创建C源文件和头文件(里面内容简单写一个函数调用即可,这里不贴代码)
mylib.c mylib.h main.c
b) 生成静态库
q # gcc -c mylib.c (生成mylib.o)
q # ar r libtest.a mylib.o (生成libtest.a)
c) 开始编译连接main.c (下面是一个尝试过程)
q # gcc main.c -I /home/armroot/tmp/mytest/ -L /home/armroot/tmp/mytest/ -ltest -o test (成功)
q # gcc main.c -ltest -o test (失败,找不到库文件)
q # gcc main.c -L /home/armroot/tmp/mytest/ -ltest -o test (成功)
q # gcc main.c libtest.a -o test (成功)
q # gcc libtest.a main.c -o test (失败,undefined reference to错误)
q # gcc -L /home/armroot/tmp/mytest/ -ltest main.c -o test (同上)
q 不小心把main.c写在库文件后面,就出现undefined reference to这个错误了,窃喜。即,连接的源文件和库文件之间是存在顺序关系的。
2) 在交叉编译环境(arm_v5t_le-gcc)下,生成并使用静态库
根据上面的经验,编译成功。
3) 返回去继续调试helloworld
在安装gstreamer库的时候,就说过,gstreamer需要依赖glib和xml2,根据上面的测试总结,把-lglib-2.0这个库放到了几个库的最后面,编译,成功了。