之前做了一次在Android上的移植,后来多次被人问到移植的相关问题。正好做完那个项目很久了也没有认真的把编译的知识进行单纯的整理。有很多问题没有总结在此,是因为我没遇到。有些知识还是需要用到的时候再学也为时未晚的。好了不罗嗦了,开始对编译的过程进行简单的总结吧。
linux应用程序编译时,需要交叉编译GCC,它依赖于所运行系统的内核、glibc库等。针对ARM处理器平台建立交叉编译环境,通常是要在pc上建立目标代码为ARM的编译交叉连(toolchains),它可以编译和处理Linux内核及应用程序。需要下面几个工具链的源码。
-binutils,一组编译开发工具,包括连接器汇编器以及其他用于目标文件和档案的工具。它包括:
-----addr2line把程序地址转换为文件名和行号。在命令中给它一个地址和一个可执行文件名,它就使用这个可执行文件的调试信息之处在给出的地址上是那一个文件及行号。
------ar建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容。
------as 主要用来编译GNU C编译器(gcc)输出的汇编文件,产生目标文件由连接器ld连接。
------c++filt ,连接器使用它来过滤c++和java符号,防止重载函数冲突。
------gprof显示程序调用段的各种数据。
------nm列出目标文件中的符号。
------objcopy把目标文件中的内容复制到另一种类型的目标文件中。
-----objdump显示一个或更多目标文件的信息。使用选项来控制其显示的信息。它所显示的信息很有用,可用它观察到程序中全局变量和函数编译所处的数据段和地址。
-----ranlib产生归档文件索引,并将其保存到这个归档文件中。在索引列出了归档文件个成员所定义的可重分配的目标文件。
----readelf显示elf格式包括可执行文件的信息。
----size列出目标文件每一段的大小以及总体的大小。
-----strings打印某个文件的可打印字符串。这些字符串最少4个字符长也可以使用选项-n设置字符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其他类型的文件,它只打印整个文件的可打印字符,这个程序对于了解非文本文件的内容很有帮助。
----strip丢弃目标文件中的全部或者特定符号。通常,连接完成的elf格式的文件是没有经过strip的,他/它包括符号表等多余信息,可使用这个工具让elf文件更精简。通常他会在应用程序的最后发布时使用。
--gcc是linux中最重要的软件开发工具。它是gnu c和c++的编译器。利用gcc编译器可同时编译并链接c和c++源程序。
--glibc,提供系统调用和基本函数的c库(标准c库)如open\mallloc、printf等。所有linux上的c程序编译时都需要与glibc库链接。如果是动态连接的程序,在运行时也要用到它。另外面对一些简单的应用,也可以使用更为精简的C库,如uClibc。
--glibc-linuxthreads,POSIX(Portable Operating System Interface,可移植操作系统接口)线程库。
--linux内核源码。
当然,你如果时间充足的情况下,完全可以试图自己去做一个交叉编译环境,但是本人曾试着努力过。但是花了近两个月的时间,最终因为课程的原因还是使用了现成的交叉编译链。
首先需要明确在Android中存在两种交叉编译链,一个是arm-eabi-gcc;另一个是arm-none-linux-gnueabi-gcc。通常后面的支持的库函数相对多一点。但是Android本身使用的是前者。