基于FS4412嵌入式系统移植(6) glib库的交叉编译与移植

今天和大家分享一下glib库的交叉编译过程和如何对程序进行编译以及运行。

glib库的移植资料比较少,比较零散,这里我就写一下亲自移植的过程,和大家分享一下。按照我的过程移植应该是不会有问题,如果遇到了问题可以留言联系我,一起讨论研究。

这里需要强调一下:libc、glibc、glib是不同的库!


glibc和 libc 都是 Linux 下的 C 函数库,而glib是GTK+的基础库 
libc 是 Linux 下的 ANSI C 函数库;glibc 是 Linux 下的 GUN C 函数库。 


具体的区分与概念可以参考:http://user.qzone.qq.com/452215612/2


先说一下我的上位机环境:

PC:XP sp3,深度完美 纯净标准版
虚拟机: VMware® Workstation,版本:9.0.2 build-1031769
ubuntu:12.04

在之前我已经在ubuntu上安装过glib2.0.6,并做了一些数据结构相关的教程,有兴趣的可以参考以下博文:http://blog.csdn.net/andylauren/article/category/6219334

开发板环境:

FS4412开发板:采用三星ARM Exynos 4412四核处理器,Linux3.14内核版本Uboot 2013.03gcc-4.6.4交叉编译链

我们最终目的是在我们的开发板上能够执行使用了glib库的可执行文件。

要达到这个目的我们需要几个步骤:

1、需要使用交叉编译链交叉编译glib库;

2、将生成的动态库加入到文件系统的lib目录中;

3、使用交叉编译出来的glib库,交叉编译.c文件,然后在开发板中执行文件;


安装前准备:

glib源码包下载地址:http://ftp.gnome.org/pub/gnome/sources/glib/2.24/

这里我们使用的是glib-2.22.5.tar.gz 

libffi源码包下载地址:https://www.sourceware.org/libffi/

libffi是glib的依赖库,所以需要先交叉编译这个库,我们使用的是libffi-3.2.1.tar.gz 

pkg的安装:
pkg-config是一个很好的文本替换命令,主要用于编译命令上,用法下文会详细介绍
安装:apt-getinstall pkg-config


第一步:交叉编译glib库

在交叉编译glib前我们需要先交叉编译glib的依赖库libffi

1、libffi的安装
ffi是glib依赖的一个库,在交叉编译以前需要先交叉编译libffi
首先安装pc上的开发使用命令libffi-dev
键入:apt-getinstall libffi-dev    这一步为了解决configure时出现的问题,后文有介绍。
将libffi-3.2.1.tar.gz甩入ubuntu中
解压缩源码,并建立安装路径
这个没什么好看的,直接开始配置操作
键入:CC=arm-linux-gcc ./configure --prefix=/home/linux/glib/ffi/ --host=arm-linux
应该不会遇到任何问题,然后就会生成我们需要的Makefile文件。
然后就是三部曲中的
make
make insall
为了更好地在编译时使用自定义安装路径里的库,我们使用pkg-config来辅助我们编译glib,但要运行pkg-config,首先需要制作xx.pc文件:
我们先来到安装目录下的lib/pkgconfig目录下,里面有一个libffi.pc文件,由于这个库是给arm用的,所以我习惯在文件名后加上-arm:cp libffi.pc libffi-arm.pc
然后将libffi-arm.pc拷贝到/usr/local/lib/pkgconfig/下:cp libffi-arm.pc /usr/local/lib/pkgconfig/
这样pkg-config命令就可以识别到这个文件,大家可以先键入pkg-config --cflags libffi-arm看看会打印出什么呢?
-I/home/linux/glib/ffi/lib/libffi-3.2.1/include 
这就是我们在交叉编译时需要用到的头文件路径。

2、交叉编译glib库

跟一般的安装一样,开始使用configure生成Makefile:
解压glib-2.22.5.tar.gz得到glib-2.22.5源码包目录。
先在glib-2.22.5目录下创建cache文件:gedit arm-linux.cache
然后在文件中输入:
glib_cv_stack_grows=no
glib_cv_uscore=no
ac_cv_func_posix_getpwuid_r=yes
ac_cv_func_posix_getgrgid_r=yes
glib_cv_have_qsort_r=no


运行configure的时候会从cache文件中读入配置,再将配置的log写入此文件
键入命令:CC=arm-linux-gcc ./configure --prefix=/home/linux/glib/glib-2.22/ --host=arm-linux --cache-file=arm-linux.cache

应该不会遇到任何问题,并生成了Makefile文件。

然后在glib目录下创建glib-2.22文件夹,用于保存生成的glib库文件。

然后就是三部曲中的
make
make insall

这个时候就会在glib-2.22文件夹下看到交叉编译好的glib库文件。里面会有bin,include,lib,share四个文件夹,分别有我们编译和运行时的文件和库。

第二步:将生成的动态库加入到文件系统的lib目录中

现在我们需要将编译好的glib动态库放到nfs文件系统的lib目录下,这样我们的程序在开发板上执行的时候就可以调用glib动态库了。

我们输入命令cp /home/linux/glib/glib-2.22/lib/libglib-2.0* /nfs/rootfs/lib/
这里我们将glib的所有库都拷贝到了nfs中,包括静态库,这是不必要的,我们只需要拷贝动态库就可以了。

其中文件libglib-2.0.so是一个硬链接,所以我们直接拷贝这个文件就会在nfs中得到一个库的副本文件。正确的做法是拷贝libglib-2.0.so.0.2200.5文件,并做两个硬链接到这个文件,连接文件分别是libglib-2.0.so.0和libglib-2.0.so。

其实正确的做法是使用cp -a命令,其中的-a参数相当于-dpR,保持文件的连接(d),保持原文件的属性(p)并作递归处理(R),所以应该输入:
cp -a /home/linux/glib/glib-2.22/lib/libglib-2.0* /nfs/rootfs/lib/
然后在删除静态编译库文件 libglib-2.0.la
rm  /home/linux/glib/glib-2.22/lib/libglib-2.0.la

第三步:使用交叉编译出来的glib库,交叉编译.c文件,然后在开发板中执行文件

我们现在拥有了glib的交叉编译库,而且在nfs文件系统中也有了动态库,我们需要使用一下这个库编译一个有glib函数的.C文件,并在开发板上运行起来。

我们从http://blog.csdn.net/andylauren/article/category/6219334中选择一个.c文件来作为我们的源程序,然后我们需要知道一些编译时的参数,比如头文件路径的设置,库文件路径的设置,在编译时使用 -I加上路径来表示头文件的路径,-L表示库文件的路径。

在ubuntu上我们编译glib库文件时使用的方法是gcc xxx.c -o xxx -lglib-2.0 这里的-o后面是生成的目标文件名,不是必须要的,如果不加会生成a.out文件,-l后面是我门使用的库文件名,是去掉了lib开头的库文件名,这里为什么我们没有使用-I -L呢,因为我们已经把这些文件放到了系统默认路径中,编译的时候会自动去默认路径下找相应的文件。交叉编译的时候我们也需要对应的书写编译命令,这里我先把命令写出来,然后在讲解,编译命令如下:

arm-linux-gcc GTree.c -o gtree-arm -I/home/linux/glib/glib-2.22/include/glib-2.0 -I/home/linux/glib/glib-2.22/lib/glib-2.0/include -L/home/linux/glib/glib-2.22/lib -lglib-2.0

其中arm-linux-gcc是交叉编译用的gcc,还有一个arm-none-linux-gnueabi-gcc命令,其实和它一模一样的,后边我们会对他进行讲解;

GTree.c 是我们要编译的源码文件,-o gtree-arm我们要生成的目标文件;

-I/home/linux/glib/glib-2.22/include/glib-2.0 -I/home/linux/glib/glib-2.22/lib/glib-2.0/include我们头文件路径;

-L/home/linux/glib/glib-2.22/lib我们库文件路径;

  -lglib-2.0我们调用的库文件;

然后我们将生成的gtree-arm文件复制到nfs文件系统目录中,cp gtree-arm /nfs/rootfs

将开发板设置为nfs挂载,然后我们启动开发板,运行./gtree-arm,哈哈看到运行结果了,和电脑上的运行结果一样,表示我们移植成功了。

[root@farsight ]# ls
a.out              fs4412_led_app     mnt                sys
bin                fs4412_led_drv.ko  proc               tmp
dev                lib                root               usr
etc                linuxrc            sbin               var
[root@farsight ]# ./a.out 
12345
[root@farsight ]# ls
a.out              fs4412_led_drv.ko  proc               usr
bin                gtree-arm          root               var
dev                lib                sbin
etc                linuxrc            sys
fs4412_led_app     mnt                tmp
[root@farsight ]# ./gtree-arm 
BEGIN:
************************************************************
Now the tree:
Key:    0               Vaule:  zero
Key:    1               Vaule:  one
Key:    2               Vaule:  two
Key:    3               Vaule:  three
Key:    4               Vaule:  four
Key:    5               Vaule:  five
Key:    6               Vaule:  six
Key:    7               Vaule:  seven
Key:    8               Vaule:  eight
Key:    9               Vaule:  nine
The tree should have '10' items now.            Result: 10.
The height of tree is '4' now.
Now the vaule of '3' should be '3333' now.
Key:    0               Vaule:  zero
Key:    1               Vaule:  one
Key:    2               Vaule:  two
Key:    3               Vaule:  3333
Key:    4               Vaule:  four
Key:    5               Vaule:  five
Key:    6               Vaule:  six
Key:    7               Vaule:  seven
Key:    8               Vaule:  eight
Key:    9               Vaule:  nine
Now the vaule of '3' should be '3333' now[lookup].
The key '3' has been found and removed now.
Now the vaule which should be removed of '3' should be '(null)' now[search].
Now the tree look like:
Key:    0               Vaule:  zero
Key:    1               Vaule:  one
Key:    2               Vaule:  two
Key:    4               Vaule:  four
Key:    5               Vaule:  five
Key:    6               Vaule:  six
Key:    7               Vaule:  seven
Key:    8               Vaule:  eight
Key:    9               Vaule:  nine

************************************************************
DONE
[root@farsight ]# 


第一次移植血泪史:
下面我来讲一下我这次移植的过程中遇到的问题,可以说是一步一个砍,十步一个坑,坑里还有水,水里还有丁,进去就没影。感觉就像是体验了一次西天取经的99,81难一样。

首先在网上根本就找不到一个完整的glib移植的教程,有的也只是只言片语,我就这里摸索着前进。

第一劫:版本选择

首先我想我的ubuntu上安装的是glib2.0.6,那么我也是用这个进行移植吧,然后我就开始解压,配置./configure,然后遇到了根本找不到答案的问题,

checking for extra flags to get ANSI library prototypes... configure: error: cannot run test program while cross compiling

在网上根本找不到相应的解决办法,甚至于帖子都没有,没办法,我就换了版本,glib2.0.7,glib2.12,都是这样,都来我试着读了一下,意思是某个测试文件不能在交叉编译环境中运行,真的不知道是什么情况,我觉得应该,glib低版本和交叉编译链或者编译环境不匹配,或者低版本不支持交叉编译。

好,我换了最新版的glib2.48,报错缺少zlib的lib和头文件,换了多个版本,从glib2.32到glib2.28都是这样,最后我在网上找到一个帖子说glib-2.23开始就需要zlib,也就是我还需要交叉编译zlib,我想了想,这个zlib还不知道会遇到什么险阻,放弃最新版,反正我不是处女座,只要有个好用的库就可以了,不需要是最新的。然后就在2.23之后的版本选择了2.22.5版本。

这里我只是写了不到100字,但是应该能想象到我在做的时候一次次地下载,然后倒入ubuntu虚拟机,然后xvf解压,然后./configure,然后看着各种错误是的心情,我下载实验的版本不少于20个,很是崩溃。

第二劫:下载网址与autoconf

在开始的时候我通过他们提供的官方下载网址下载源码包,但是有的源码包中有configure文件,而有的只有configure.ac文件,这个configure.ac文件是需要autoconf工具去生成configure的,我怕我选择的版本有问题,所有特意安装了autoconf工具去生成configure。

这个时候问题又来了,autoconf工具生成configure过程中有报错,我的天啊,真是一波未平一波又起,但是我不打算进行问题嵌套处理,我就放弃了使用autoconf,然后我去找其他的下载源码包网站,终于我找到了一个网站,提供所有都带有configure文件的源码包,也就是我上面贴出来的那个网址。

当我遇到为了解决一个问题而去解决另一个问题的时候,我在想cpu进行中断嵌套的时候是一种什么心情呢?一定很崩溃,怪不得A9以后就不支持中断嵌套了呢。

第三劫:交叉编译参数

其实我也只是一个初学者,在学习的时候就使用的都是老师给配置好的环境,只要一个gcc都搞定,哪里用自己去找头文件,库文件。接触到了交叉编译之后这是一个过不去的坎,必须要能够自己指定头文件和库文件路径,这一劫还算是比较好过的,毕竟是基础知识,网上资料教程很多。


最后我在补充一个我自己发现的知识,那就是arm-linux-gcc和arm-none-linux-guneabi-gcc其实是同一个东西。

我们使用which arm-linux-gcc

看到/home/linux/sys/gcc-4.6.4/bin/arm-linux-gcc

说明arm-linux-gcc指向交叉编译链里的bin文件夹下的arm-linux-gcc

然后我们使用arm-linux-gcc -v

linux@ubuntu:~/16021/glibDemo$ arm-linux-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gcc
COLLECT_LTO_WRAPPER=/home/linux/sys/gcc-4.6.4/bin/../libexec/gcc/arm-arm1176jzfssf-linux-gnueabi/4.6.4/lto-wrapper
Target: arm-arm1176jzfssf-linux-gnueabi
Configured with: /work/builddir/src/gcc-4.6.4/configure 
--build=i686-build_pc-linux-gnu 
--host=i686-build_pc-linux-gnu 
--target=arm-arm1176jzfssf-linux-gnueabi 
--prefix=/opt/TuxamitoSoftToolchains/arm-arm1176jzfssf-linux-gnueabi/gcc-4.6.4 
--with-sysroot=/opt/TuxamitoSoftToolchains/arm-arm1176jzfssf-linux-gnueabi/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/sysroot 
--enable-languages=c,c++ 
--with-arch=armv6zk 
--with-cpu=arm1176jzf-s 
--with-tune=arm1176jzf-s 
--with-fpu=vfp 
--with-float=softfp 
--with-pkgversion='crosstool-NG hg+default-2685dfa9de14 - tc0002' 
--disable-sjlj-exceptions 
--enable-__cxa_atexit 
--disable-libmudflap 
--disable-libgomp 
--disable-libssp 
--disable-libquadmath 
--disable-libquadmath-support 
--with-gmp=/work/builddir/arm-arm1176jzfssf-linux-gnueabi/buildtools 
--with-mpfr=/work/builddir/arm-arm1176jzfssf-linux-gnueabi/buildtools 
--with-mpc=/work/builddir/arm-arm1176jzfssf-linux-gnueabi/buildtools 
--with-ppl=/work/builddir/arm-arm1176jzfssf-linux-gnueabi/buildtools 
--with-cloog=/work/builddir/arm-arm1176jzfssf-linux-gnueabi/buildtools 
--with-libelf=/work/builddir/arm-arm1176jzfssf-linux-gnueabi/buildtools 
--with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' 
--enable-threads=posix 
--enable-target-optspace 
--without-long-double-128 
--disable-nls 
--disable-multilib 
--with-local-prefix=/opt/TuxamitoSoftToolchains/arm-arm1176jzfssf-linux-gnueabi/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/sysroot 
--enable-c99 
--enable-long-long
Thread model: posix
gcc version 4.6.4 (crosstool-NG hg+default-2685dfa9de14 - tc0002) 

好了我们使用arm-none-linux-guneabi-gcc -v

与上面的返回一样,所有的路径都是一样的,最主要的是Target: arm-arm1176jzfssf-linux-gnueabi,目标都是一模一样的,所以以后我们在需要使用arm-none-linux-guneabi-的时候我们只需要使用arm-linux-就可以。





  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值