初尝linux——arm-linux移植之动态库问题

     我一直在做zigbee的项目,因为这次zigbee主机方案需要用到arm,之前花了几个月的时间在PC linux上将主机程序调通了,现在的问题是将程序移植到arm linux。因为之前完全没有嵌入式linux了,更没有移植的经验,于是便从实际问题出发,从基础知识开始,从网上找资料慢慢地解决问题,最终问题还是得到解决,写篇文章梳理一下最近学习的经验,使不至于下次再碰到类似问题时又手足无措,也给像我一样的小白稍稍指引点方向,如有不足的地方还请各位多多指出!!

首先了解一些概念:

交叉编译

  移植就牵涉到交叉编译,那么什么叫交叉编译?交叉编译是与本地编译相对的,首先要弄清两个概念:运行环境与编译环境,这里的环境是指平台架构,如PC的x86架构,arm的arm架构。那么运行环境就是这个程序是在什么平台后架构上运行的,而编译环境指的是编译这个程序用的平台架构。如果运行环境和编译环境是相同的这叫本地编译,如果不同那么就叫交叉编译。以我这次的项目为例,我编写和编译都是在PC-linux下进行的,但是我需要这个程序最终是在arm中的linux运行的,这就是说编译环境是x86架构,而运行环境是arm架构,那么我就需要交叉编译。相关参考:交叉编译详解

交叉编译器

  如果要进行交叉编译就必须要用交叉编译器才行,那么交叉编译器究竟是个什么东东?我知道在PC-linux中有个叫gcc的东西,它就是一个编译器,你用c语言写的程序经过gcc编译后就能在PC上运行了(gcc使用参考:如何使用gcc编译器)。那么这个gcc编译器与交叉编译器有什么关系呢?实际上用gcc编译出生成的可执行文件在arm-linux上是不能运行的他只能在PC-linux下运行。为什么呢?因为编译的过程是这样的:源文件(C语言)--》中间目标文件(汇编语言)--》可执行文件(二进制代码),我们知道汇编语言是比较底层或者说比较低级的语言,在不同架构下是不同的。比如前文说的x86架构和linux架构,那么它们的汇编语言是不同的。而gcc针对的是x86架构也就是PC,所以它编译使用的是x86架构下的汇编语言,那么它编译出来的东西要在arm上运行当然是不行的,语言不同呀!就好比将一篇英文文章交给一个只懂中文的人看,当然是看不懂的。交叉编译器就是能够以你运行平台架构的汇编语言来编译源文件,如果要运行在arm上就需要arm的交叉编译器arm-linux-gcc。事实上你可以通过gcc -v来查看gcc信息(如下):

ubuntu@ubuntu:~$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5.1' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)

可以看到红色标记部分:target:i486-linux-gun说明他针对的是x86架构的。(ps:当然也有可能显示的是 i686-linux-gnu等都表示x86系统)再看看arm-linux-gcc:

ubuntu@ubuntu:~$ arm-linux-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gcc
COLLECT_LTO_WRAPPER=/opt/EmbedSky/4.6.0/libexec/gcc/arm-embedsky-linux-gnueabi/4.6.0/lto-wrapper
Target: arm-embedsky-linux-gnueabi
Configured with: /opt/EmbedSky/build-4.6.0/.build/src/gcc-4.6.0/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-embedsky-linux-gnueabi --prefix=/opt/EmbedSky/4.6.0 --with-sysroot=/opt/EmbedSky/4.6.0/arm-embedsky-linux-gnueabi/embedsky --enable-languages=c,c++ --disable-multilib --with-arch=armv6 --with-cpu=arm1176jzf-s --with-tune=arm1176jzf-s --with-fpu=vfp --with-float=softfp --with-pkgversion='for TQ6410 EmbedSky Tech' --with-bugurl=http://www.embedsky.net --disable-sjlj-exceptions --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --with-gmp=/opt/EmbedSky/build-4.6.0/.build/arm-embedsky-linux-gnueabi/build/static --with-mpfr=/opt/EmbedSky/build-4.6.0/.build/arm-embedsky-linux-gnueabi/build/static --with-mpc=/opt/EmbedSky/build-4.6.0/.build/arm-embedsky-linux-gnueabi/build/static --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --enable-threads=posix --enable-target-optspace --without-long-double-128 --with-local-prefix=/opt/EmbedSky/4.6.0/arm-embedsky-linux-gnueabi/embedsky --disable-nls --enable-c99 --enable-long-long
Thread model: posix
gcc version 4.6.0 (for TQ6410 EmbedSky Tech)

可以看到红色部分Target是arm-embedsky-linux-gnueabi即是针对arm-linux的,所以首先你要安装一个交叉编译器。

动态库与静态库

  在编译的时候可能需要用到库,库可分为静态库和动态库。静态库是在编译的时候与源程序一起编译的,生成的可执行文件执行时不再需要再用到静态库。动态库是事先编译过的,他不需要与源程序一起编译,而是在执行时再调用库。可参考:动态库与静态库的区别

如果源文件使用了系统的库,在用交叉编译器编译时如果需要先将使用库也用交叉编译器进行安装编译,然后将库文件.so文件移到arm-linux中/usr/lib下,这样程序才能调用它。具体操作可参考:Linux学习笔记——如何在交叉编译时使用共享库。

总结:要解决一个问题,要从问题点出发,找到原因再扩散到相关知识点,最终解决问题,其实大部分问题别人都有经历过,通过互联网搜索,总能找到答案。这边博文主要还是讲了一点点概念,而且引用很多别人的博客,因为他们写得已经非常的好了,希望这边博文能够给一些人帮助,也给自己存个档,日后可以再深入的学习!!

你可能感兴趣的:(初尝linux——arm-linux移植之动态库问题)