android linux 系统总结4

====================================================================
3. 制作交叉工具链
3.1 什么是工具链
3.2 获取交叉工具链的几种途径
3.3 android工具链与gnu工具链的比较

       每一个软件,在编译的过程中,都要经过一系列的处理,才能从源代码变成可执行的目标代码。这一系列处理包括:预编译,高级语言编译,
汇编,连接及重定位。这一套流程里面用到的每个工具和相关的库组成的集合,就称为工具链(tool chain)。以GNU的开发工具GCC为例,
它就包括了预编译器cpp,c编译器gcc,汇编器as,和连接器ld等。在GNU自己对工具链定义中,还加进了一套额外的用于处理二进制包的
工具包binutils,整个工具链应该是GCC+binutils+Glibc, binutils其实与Glibc关系不是很大,它可以被独立安装的,所以GNU工具
链也可以狭义地被理解为GCC+Glibc。
要构建出一个交叉工具链,需要解决三个问题。一是这个工具链必须是可以运行在原工作站平台上的。二是我们需要更换一个与目标平台对应的
汇编器,使得工具链能产生对应的目标代码,三是要更换一套与目标平台对应的二进制库,使得工具链在连接时能找到正确的二进制库。
3.2 获取交叉工具链的几种途径
3.2.1 利用源代码制作交叉工具链
网上直接下载工具链或者从方案商处获取(如:marvell)
下载地址:
http://www.angstrom-distribution.org/unstable/
3.2.2 用脚本制作工具链
3.2.2.1 croostool-0.43
http://www.kegel.com/crosstool/crosstool-0.43.tar.gz
制作工具链的源码包搭配情况: http://www.kegel.com/crosstool/crosstool-0.43/buildlogs/
3.2.2.2 buildroot
http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2
若想详细地了解buildroot可参考该文档http://buildroot.uclibc.org/buildroot.html
3.2.3 利用OE制作工具链
http://www.scratchbox.org/wiki/OpenEmbedded

3.3 android工具链与gnu工具链的比较
Android所用的Toolchain(即交叉编译工具链)可从下面的网址下载:
http://android.kernel.org/pub/android-toolchain-20081019.tar.bz2。如果下载了完整的Android项目的源代码,则可以在
“<your_android>/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”目录下找到交叉编译工具,比如Android所用的
arm-eabi-gcc-4.2.1。Android并没有采用glibc作为C库,而是采用了Google自己开发的Bionic Libc,它的官方Toolchain也是基于
Bionic Libc而并非glibc的。这使得使用或移植其他Toolchain来用于Android要比较麻烦:在Google公布用于Android的官方Toolchain之前,
多数的Android爱好者使用的Toolchain是在http://www.codesourcery.com/gnu_toolchains/arm/download.html 下载的一个通用的
Toolchain,它用来编译和移植Android 的Linux内核是可行的,因为内核并不需要C库,但是开发Android的应用程序时,直接采用或者移植其他
的Toolchain都比较麻烦,其他Toolchain编译的应用程序只能采用静态编译的方式才能运行于Android模拟器中,这显然是实际开发中所不能接
受的方式。目前尚没有看到说明成功移植其他交叉编译器来编译Android应用程序的资料。
与glibc相比,Bionic Libc有如下一些特点:
-          采用BSD License,而不是glibc的GPL License;
-          大小只有大约200k,比glibc差不多小一半,且比glibc更快;
-          实现了一个更小、更快的pthread;
-          提供了一些Android所需要的重要函数,如”getprop”, “LOGI”等;
-          不完全支持POSIX标准,比如C++ exceptions,wide chars等;
-          不提供libthread_db 和 libm的实现
另外,Android中所用的其他一些二进制工具也比较特殊:
-          加载动态库时使用的是/system/bin/linker而不是常用的/lib/ld.so;
-          prelink工具不是常用的prelink而是apriori,其源代码位于” <your_android>/build/tools/apriori”
-          strip工具也没有采用常用的strip,即“<your_android>/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”
目录下的arm-eabi-strip,而是位于<your_android>/out/host/linux-x86/bin/的soslim工具。

参考文档:
CLFS2.0原理分析 
http://www.linuxsir.org/bbs/showthread.php?t=267672
Cross-Compiled Linux From Scratch
http://cross-lfs.org/view/clfs-sysroot/arm/
全手工制作arm-linux交叉编译工具链《一》
http://blog.chinaunix.net/u2/62168/showart_1898748.html
自己制作arm-linux交叉编译环境(一)-scratch篇
http://blog.csdn.net/chenzhixin/archive/2007/01/12/1481442.aspx
如何建立交叉编译工具链
http://www.decell.org/article.asp?id=53
Android Toolchain与Bionic Libc
http://www.top-e.org/jiaoshi/html/?151.html
ndroid编译环境(2) - 手工编译C模块

=================================================


=================================================
4. 软件编译常识
4.1 链接器和加载器
4.2 android 的标准链接器和加载器
4.3 Makefile基本语法
何为链接器和加载器? 
链接器为ld,加载为ld-linux.so.2,两个的区别很大,一个编译时用,一个运行时用,ld负责在编译的搜索路径里找到要求的库,并查看
是否有提供了需要的 符号(如函数等),如果有,记录相关信息到程序中,由ld-linux.so.2在执行时查找到该库,并根据相关信息进行需
要符号的重定位等工作.注意 这两者的搜索库的方式是不同的。
动态连接器通常是指的动态加载器(不要与 Binutils 里的标准连接器 ld 混淆了)。动态连接器由 Glibc 提供,用来
找到并加载一个程序运行时所需的共享库,在做好程序运行的准备之后,运行这个程序。动态连接器的名称通常是 
ld-linux.so.2,标准连接器 ld 由 Binutils 这个包提供。

标准连接器
查看gcc使用的标准连接器
mhf@mhf-desktop:/usr/local/marvell-arm-linux-4.1.1/bin$ arm-linux-gcc -print-prog-name=ld
编译时库的搜索路径,以下几种方式让连接器去找需要的库
1. 编译的时候明确指定,如: gcc test.c  ./say.so -o test中的   ./say.so
2. 编译 Binutils 的时候通过LIB_PATH 变量指定,
如:make -C ld LIB_PATH=/tools/lib
 -C ld LIB_PATH=/tools/lib
这个选项重新编译 ld 子目录中的所有文件。在命令行中指定 Makefile 的 LIB_PATH 变量值,使它明确指向/tools/lib工具目录,
以覆盖默认值。这个变量的值指定了连接器的默认库搜索路径。
来源:Linux From Scratch - 版本 6.4第 5 章 构建临时系统  5.4. Binutils-2.18 - 第一遍
http://www.bitctp.org/lfsbook-6.4/chapter05/binutils-pass1.html
3. 在源码包configure的时候通过  --with-lib-path 指定,或者 --lib- path
例如:
binutils-2.18/configure --prefix=/tools --disable-nls --with-lib-path=/tools/lib
配置选项的含义:
--with-lib-path=/tools/lib
    告诉配置脚本在为编译 Binutils 的过程中使用正确的库搜索路径,也就是将 /tools/lib 传递给连接器。这防止连接器搜索宿主系统中的库文件目录。
来源: Linux From Scratch - 版本 6.4 第 5 章 构建临时系统  lfs 5.13. Binutils-2.18 - 第二遍 
http://www.bitctp.org/lfsbook-6.4/chapter05/binutils-pass2.html
4. 到 ld –verbose | grep SEARCH 列出的默认目录下去找
5. -L/usr/gpephone/lib 指定的目录找
经常以 LDFLAGS=" -L/usr/gpephone/lib  -L/lib -L/usr/lib -L/usr/X11R7/lib" 的方式传入

参数 -rpath 与  -rpath-link 
如果使用了'-rpath'选项, 那运行时搜索路径就只从'-rpath'选项中得到
'nodefaultlib'标志一个对象,使在搜索本对象所依赖的库时,忽略所有缺省库搜索路径.
LDFLAGS="-Wl,-rpath-link=/usr/gpephone/lib/:/usr/gphone/lib:/usr/local/lib  -L/usr/gpephone/lib  -L/usr/gphone/lib"
-rpath 与  -rpath-link 的特性:
1. 在编译的时候我们都可以使用这两个路径,
2. '-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径会被包含到可执行程序中,并在运行时使用,
而'-rpath-link'选项仅仅在链接时起作用。

-dumpspecs               Display all of the built in spec strings
  -dumpversion             Display the version of the compiler
  -dumpmachine             Display the compiler's target processor
  -print-search-dirs       Display the directories in the compiler's search path
  -print-prog-name=<prog>  Display the full path to compiler component <prog>
  -specs=<file>            Override built-in specs with the contents of <file>
  -Wa,<options>            Pass comma-separated <options> on to the assembler
  -Wp,<options>            Pass comma-separated <options> on to the preprocessor
  -Wl,<options>            Pass comma-separated <options> on to the linker
从工具链内建的规范中查看动态加载器
gcc -dumpspecs | grep  dynamic-linker  //本机
查看编译起所指定的动态加载器
1. s3c2440 (arm9tdmi) 平台的工具链
/scratchbox/compilers/arm-9tdmi-softfloat-linux-gcc-3.4.4-glibc-2.3.5/bin/arm-softfloat-linux-gnu-gcc -dumpspecs | grep  dynamic-linker
/scratchbox/compilers/arm-softfloat-linux-gcc-3.4.4-glibc-2.3.5/bin/arm-softfloat-linux-gnu-gcc -dumpspecs | grep  dynamic-linker
2. marvell 的工具链
/scratchbox/compilers/marvell-arm-linux-4.1.1/bin/arm-linux-gcc  -dumpspecs | grep  dynamic-linker
3. scrathbox 中工具链 host-gcc 
/scratchbox/compilers/host-gcc/bin/host-gcc  -dumpspecs | grep  dynamic-linker

如果我们在编译的时候给编译起 gcc 指定 -specs=/scratchbox/compilers/host-gcc/host-gcc.spec ,那么-specs指定
的规范将会覆盖工具链内建的规范。
cat /scratchbox/compilers/host-gcc/host-gcc.specs  | grep ld 有如下内容:
-dynamic-linker /scratchbox/host_shared/lib/ld.so
/scratchbox/compilers/host-gcc/bin/gcc -specs=/scratchbox/compilers/host-gcc/host-gcc.specs
mhf@mhf-desktop:/usr/local/marvell-arm-linux-4.1.1/arm-iwmmxt-linux-gnueabi/bin$ ./gcc -dumpspecs|grep dynamic-linker
gcc -dumpspecs | sed 's@/lib/ld-linux.so.2@/tools&@g'  | sudo tee  `dirname $(gcc -print-libgcc-file-name)`/specs
cat `dirname $(gcc -print-libgcc-file-name)`/specs | grep tools

查看本机应用程序使用的动态加载器
readelf -l /usr/bin/make | grep interpreter 
[Requesting program interpreter: /lib/ld-linux.so.2]
查看 scratchbox 中应用程序使用的动态加载器
readelf -l /scratchbox/tools/bin/make | grep interpreter
[Requesting program interpreter: /scratchbox/host_shared/lib/ld.so]

cd ~/svn/mohuifu.svn/trunk/mysource/compiler_test
/scratchbox/compilers/host-gcc/bin/gcc -specs=/scratchbox/compilers/host-gcc/host-gcc.specs -o ld.so.test1 ld.so.test.c
/scratchbox/compilers/host-gcc/bin/gcc -o ld.so.test2 ld.so.test.c
readelf -l ./ld.so.test1 | grep interpreter 
readelf -l ./ld.so.test2 | grep interpreter 
其他示例:
readelf -l /scratchbox/tools/bin/make | grep interpreter
readelf -l /usr/bin/make | grep interpreter
分别显示:
[Requesting program interpreter: /scratchbox/host_shared/lib/ld.so]
[Requesting program interpreter: /lib/ld-linux.so.2]
下面的方式也可以查看应用程序所使用的加载器
strings  /scratchbox/tools/bin/make  |grep lib
strings  /usr/bin/make  |grep lib
分别为:
/scratchbox/host_shared/lib/ld.so
/lib/ld-linux.so.2

查看应程序加载器库的搜索路径
显示 scratchbox 中加载器的库搜索路径
strings /scratchbox/host_shared/lib/ld.so |grep lib
display library search paths
/scratchbox/host_shared/lib/
/scratchbox/tools/lib/
显示本机中加载器的库搜索路径
strings  /lib/ld-linux.so.2 |grep lib
display library search paths
/lib/
/usr/lib/
/lib/i486-linux-gnu/
/usr/lib/i486-linux-gnu/
ldd 验证应用程序所使用动态库
ldd /scratchbox/tools/bin/make
	libc.so.6 => /scratchbox/host_shared/lib/libc.so.6 (0xb7ef9000)
	/scratchbox/host_shared/lib/ld.so => /scratchbox/host_shared/lib/ld.so (0xb802f000)
ldd /usr/bin/make
	librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7fb9000)
	libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e5b000)
	libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7e42000)
	/lib/ld-linux.so.2 (0xb7fd5000)

参考文档:
交叉编译中libtool相关的问题
http://hi.baidu.com/lieyu063/blog/item/9c99a2dd23e41f365882dd39.html
静态库和共享库库的定位搜索路径
http://blog.csdn.net/lwhsyit/archive/2008/08/26/2830783.aspx
Linux动态连接原理
http://blog.chinaunix.net/u2/67984/showart_1359874.html
程序编译链接运行时对库关系的探讨(原创)
http://www.360doc.com/content/061107/09/13188_251964.html
http://lamp.linux.gov.cn/Linux/LFS-6.2/chapter05/toolchaintechnotes.html
[Linux命令] ld 中文使用手册完全版(译) 
http://blog.csdn.net/rstevens/archive/2008/01/28/2070568.aspx
scratchbox 是mameo (nokia) 提供的一个集成开发环境,可以去官方网站:
http://www.scratchbox.org/
http://www.scratchbox.org/download/


4.2 android 的标准链接器和加载器
android的标准链接器 ./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-ld
android 中标准连接器搜索库的路径
./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-ld -verbose | grep SEARCH
SEARCH_DIR("/android/mathias/armdev/toolchain-eabi-4.2.1/arm-eabi/lib");
Android编译环境所用的交叉编译工具链是./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc,
-I和-L参数指定了所用的C库头文件和动态库文件路径分别是bionic/libc /include 和out/target/product/generic/obj/lib,
其他还包括很多编译选项以及-D所定义的预编译宏。这里值得留意的是参数“-Wl,-dynamic-linker,/system/bin/linker”,它指定了
Android专用的动态链接器/system/bin/linker,而不是通常所用的ld.so。
上面的“make clean-$(LOCAL_MODULE)”是Android编译环境提供的make clean的方式。

android中应用程序使用的加载器
strings  out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild  | grep link
/system/bin/linker
./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc -dumpspecs|grep dynamic-linker
%{mbig-endian:-EB} %{mlittle-endian:-EL} %{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} 
%{!static:%{shared: -Bsymbolic} %{!shared:%{rdynamic:-export-dynamic} %{!dynamic-linker:-dynamic-linker /system/bin/linker}}} -X

android中加载器搜索库的路径
strings /nfsroot/rootfs/system/bin/linker | grep lib
/system/lib
/lib

生成的可执行程序可用file和readelf命令来查看一下:
file out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild 
out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild: ELF 32-bit LSB executable, 
ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
readelf -d out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild  |grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [liblog.so]
 0x00000001 (NEEDED)                     Shared library: [libcutils.so]
 0x00000001 (NEEDED)                     Shared library: [libril.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
这是ARM格式的动态链接可执行文件,运行时需要libc.so和libm.so。“not stripped”表示它还没被STRIP。嵌入式系统中为节省空间通常
将编译完成的可执行文件或动态库进行STRIP,即去掉其中多余的符号表信息。在前面“make helloworld showcommands”命令的最后我们也
可以看到,Android编译环境中使用了out/host/linux-x86/bin/soslim工具进行STRIP。


4.3 Makefile基本语法
Makefile详解(超级好)
linux/Unix环境下的make和makefile详解
http://www.unlinux.com/doc/program/20051026/2365.html
跟我一起写 Makefile
http://dev.csdn.net/develop/article/20/20025.shtm
=================================================

你可能感兴趣的:(linux,android,工具,library,compiler,makefile)