APP下载

一种简化鲁棒的ARM-Linux交叉编译器构建方法*

2014-03-27李云飞刘军清雷帮军龚国强

关键词:源码编译器静态

李云飞,刘军清,雷帮军,龚国强

(三峡大学 智能视觉与图像信息研究所, 湖北 宜昌 443002)

在嵌入式应用系统中,ARM-Linux嵌入式平台技术正在迅速发展,其应用范围越来越广泛,有着很好的发展前景,在手机处理器中ARM处理器已经占了90%的份额。从事以ARM-Linux为平台的嵌入式开发工作,针对ARM-Linux平台的交叉编译器是必备的工具。最常用的针对ARM-Linux平台的交叉编译器是在Linux环境下的ARM-Linux交叉编译器。构建ARM-Linux交叉编译器可以利用Crosstool脚本工具构建,也可以采用分步方式构建。与利用Crosstool脚本工具构建交叉编译器的方式相比,分步方式较复杂,但分步方式的构建过程完全可控,具有高度的可定制性,可以构建出符合特定要求的交叉编译器。因此,利用分步式构建的交叉编译器可以和目标机有非常好的吻合,具有高可靠性和便利性[1-3]。

利用分步方式构建交叉编译器,构建过程较复杂,因此编译成功率低,本文对分步式构建交叉编译器的方法进行了改进,并对构建过程中遇到的参数设置、版本选择、库依赖等问题进行了分析和总结,以提高利用分步式构建交叉编译器的成功率。

1 常规的构建方法

分步式构建交叉编译器的基本工作是利用交叉编译器所需的程序源码并按照一定步骤编译出所要求的交叉编译器。利用源码编译程序有参数配置、编译、安装三个步骤[4],如图1所示。三个步骤中参数配置是最重要的一步,参数配置是否正确,决定着后续编译工作是否能顺利进行。

图1 利用源码编译安装程序步骤Fig.1 The steps of compiling and installing program form source

图2为ARM-Linux交叉编译器的常规分步方式构建流程。分为7个步骤。前三个步骤为准备阶段,为后续工作提供必要的程序源码、工具软件和头文件,后面四个步骤是核心工作。这四个步骤之间有严格依赖的关系,所以它们的执行顺序必须严格遵从图所示的顺序。Binutils提供一系列交叉编译器的二进制工具,后续阶段都需要利用它。静态GCC的作用是用来编译Glibc,是一个过度性工具,这个阶段的GCC只支持C语言,不支持动态库、线程库等一些特性。Glibc提供C语言标准的静态库和动态库。完整版GCC支持动态库、线程库等一些特性,这些特性是需要有Glibc库的支持才可以编译成功[5-8]。

图2 常规分步式构建交叉编译器流程图Fig.2 The flowchart of the conventional method to build a cross-compiler step by step

2 改进分步式构建方法

图3为改进的分步式构建交叉编译器的构建流程。相对于常规的方法,改进方法中没有了编译静态GCC的步骤,但在准备工作阶段,改进方法需要安装功能完整的交叉编译器,在编译Glibc时使用的编译器是安装的功能完整ARM-Linux交叉编译器。在常规分步式构建交叉编译器的过程中,静态GCC是一个过度性工具,它的作用只是编译Glibc,因此可以利用功能完整的交叉编译器代替静态GCC来编译Glibc。与常规方法中的静态GCC不同,替代的功能完整ARM-Linux交叉编译器的选择不是唯一的,所有能编译对应Glibc的功能完整ARM-Linux交叉编译器都可以使用。一般情况下,最后编译的完整版GCC的特性是要符合特定要求的,参数配置中关于处理器架构的配置参数和替代的功能完整交叉编译器的可能不同,所以在利用替代的交叉编译器编译Glibc时,要检查替代的交叉编译器的配置参数中与处理器架构相关的配置参数和将要编译的完整版的GCC中关于处理器架构的参数配置是否一样,如果不一样,在编译Glibc时需要使用如-march、-mcpu、-mfloat等与处理器架构相关的编译参数,使替代交叉编译器用与将要编译完整GCC的参数配置中相同的处理器架构相关的编译参数编译Glibc[9-15]。

图3 改进的分步式构建交叉编译器流程图Fig.3 The flowchart of the improved method to build a cross-compiler step by step

在常规分步式构建交叉编译器的过程中,在编译静态GCC时,还没有编译Glibc,参数配置时需要关闭需要Glibc库支持的特性,开启必需的功能,使参数配置变得复杂,容易出错,从而导致编译失败率增加。在编译Glibc时,由于此时编译它的静态GCC功能不完整,需要在参数配置时进行相应的设置和修改相关文件,才能使编译通过。这些原因增加构建交叉编译器的复杂,并降低了成功率。在改进的方法中,利用已功能完整的交叉编译器代替静态GCC,没有编译静态GCC的阶段,因此可以避免编译静态GCC时复杂的参数配置和易出现的失败。由于编译Glibc的编译器功能完整,在编译Glibc时,无需进行特定参数设置和修改相关文件,因此降低了编译Glibc是参数配置的复杂度和失败率。与常规方法中的静态GCC不同,替代的功能完整ARM-Linux交叉编译器选择不是唯一的,所有能编译对应Glibc的功能完整ARM-Linux交叉编译器都可以使用,因此,在编译Glibc时,可以避免由于GCC和Glibc版本不匹配导致的错误。在准备阶段,改进方法需要另外安装功能完整的交叉编译器,但功能完整的交叉编译器容易获得,安装简单,对整体工作量和难度的影响很小。

为了验证分析结果,在最终编译出的完整GCC特性要求相同,主机环境相同条件下,分别用常规的方法和改进的方法做编译实验,获得两种方法核心步骤中每个步骤的所必须的参数配置数目。实验环境如表1所示。

表1 实验环境

实验结果如表2所示。表2显示了两种方法的在最终完整GCC特性要求相同的情况下核心步骤的参数配置的数目。从表2可以看出,改进方法需要配置的参数数目总共39个,比常规方法少了20个,很大程度上减少了参数配置的复杂度。分步式构建交叉编译器的过程中产生的大部分错误都是由参数配置不当而引起的,参数配置的复杂度越低,产生错误的概率就越小。因此改进的方法可以很大程度地提高整个编译过程的成功率和稳定性。

表2 核心步骤参数配置数目

图4显示用柱状图来比较两种方法的核心步骤的参数配置数目。从图中可以直观的看出改进的方法的参数数目比常规的方法要少很多。本文方法不存在编译静态GCC的步骤,编译过程中总的参数配置数目要比传统方法少20个以上。

图4 核心步骤参数配置数目的柱状图Fig.4 The histogram of number of parameters in the core steps

3 问题分析及解决方法

下面就本文方法在实际应用中存在的三个主要问题进行分析,并给出相应的解决方法。

3.1 参数配置

每个阶段的编译工作都需要通过configure脚本文件进行参数配置,可以使用configure-help命令查看参数的简要说明。每个步骤有很多配置参数,主要包括安装目录参数(如-prefix)、系统类型参数(-build、-host、-target)、相关特性和功能参数(以enable、disable、with、without为前缀)等。

安装目录参数中最常用的是-prefix,作用是将所有的文件安装到指定目录下。其他相关的安装目录参数作用是将不同类型文件分别安装到不同目录下。系统类型参数包括-build、-host和-target,但Glibc的系统类型参数只有-build和-host。参数-build指定编译此工具的平台,参数-host指定运行此工具的平台,参数-target指定此工具产生的文件运行的平台。通常情况,参数-build、-host的值是编译此工具的平台,参数-build、-host的值可以通过命令echo ${MACHTYPE}获得。-target参数的值可以根据表3设置。每个工具的相关特性和功能参数有所不同,而且此类型的参数较多,对于它们的设置要根据具体要求设置。

表3 Target值

3.2 版本选择

在制作交叉编译器之前,需要选择满足要求的Binutils、GCC、Glibc和主机GCC的版本,否则,会导致编译失败。一般情况,由于版本选择问题导致的编译失败,主要表现为符号未定义、函数名未定义等语法错误。这是由于在新版本中存在一定程度的改动或添加了一些新特性,导致程序之间会存在兼容性问题。

在利用常规的分步式构建交叉编译器过程中,如果在编译Glibc时出现符号未定义、函数名未定义等语法错误,主要原因是由于前一阶段编译的静态GCC的版本不满足要求,因为编译Glibc是利用前一阶段的静态GCC来进行的。如果在编译静态GCC和完整版GCC出现符号未定义、函数名未定义等语法错误,主要是由于主机GCC版本不满足要求,因为静态GCC和完整版GCC由主机GCC编译的。在选择每个工具的版本时,首先选择Glibc的版本,尽量不要选择最新的版本。然后,根据Glibc源码根目录下的INSTALL文件里说明,选择GCC和Binutils版本。再根据GCC源码目录下INSTALL文件夹下prerequisites.html文件里的说明选择主机GCC的版本。

在改进的方法中,在编译Glibc时出现符号未定义、函数名未定义等语法错误,主要原因是替代静态GCC的完整交叉编译器的版本选择不满足要求。要根据Glibc源码根目录下的INSTALL文件里说明选择其版本,建议选择和将要编译的GCC的版本相近的版本。对于GCC和binutils版本的选择不需要根据Glibc源码根目录下的INSTALL文件中的要求选择,选择自由度大。宿主机的GCC编译器的版本要根据GCC源码目录下INSTALL文件夹下prerequisites.html文件里的要求选择。

3.3 库依赖问题

库依赖问题,是指编译器搜索不到所需的库文件。在编译交叉编译器的过程中,库依赖问题经常出现。出现库依赖问题,一般会有“ld: cannot find -lx”(x为库名)的错误提示,然而一些情况,一些其他错误提示也可能由库依赖问题引起,这种情况,需要到出错的目录下,查看config.cache文件。在此文件中,在出现错误信息的前面几行会显示出错的具体原因,如果是库依赖问题引起的,会有相关错误提示。

在制作交叉编译器的过程中出现库依赖问题的原因主要有三种。相关库的路径不在编译器的搜索路径里会产生库依赖问题。这种情况可以通过变量LD_LIBRARY_PATH或LDFLAGS将库文件的路径添加到编译器的搜索路径里;库文件的链接文件失效或不存在会产生库依赖问题。这种情况,要重新建立库文件的链接文件。在利用常规的分步式构建交叉编译器过程中,静态GCC编译完成后,需要对libgcc.a静态库文件在同目录下建立两个名为libgcc_sh.a、libgcc_eh.a的链接文件,否则,会引起由于库文件的链接文件不存在导致的库依赖问题;在利用常规的分步式和改进的方法构建交叉编译器过程中,在编译Glibc完成后,都需要对安装目录下lib文件夹下的libc.so和libpthread.so进行修改,这两个文件需要在终端里用VI编辑器打开,并将两个文件中GROUP后面每个库文件的绝对路径删除。如果不删除绝对路径,会导致编译器找不到这两个文件中描述的库文件[16]。

4 总 结

本文对分步式构建交叉编译器的方法做了改进,在改进的方法中,去除了编译静态GCC的阶段,所以可以省去在这阶段中复杂的参数配置,而且,由于编译Glibc的交叉编译器功能完整,在Glibc的参数配置中无需配置一些相应的参数,所以编译Glibc阶段的参数配置也变得相对简单。不仅参数配置变得简单,而且版本选择相对容易。同时,也可以避免编译静态GCC时出现的失败,和由于静态GCC的不完整导致编译Glibc失败。因此,改进的方法可以很好的弥补分步式方法构建交叉编译器时过程复杂、成功率低的不足。本文构建的交叉编译器的方法是针对ARM处理器的,但同样也适合MIPS、POWERPC等其他处理器。

[1] 刘二刚.利用crosstool-ng构建交叉编译工具链[J].电脑知识与技术,2011,7(19):4553-4554+4567.

[2] 张欢庆,高丽,宋承祥.基于ARM的嵌入式Linux交叉编译环境的研究与实现[J].计算机与数字工程, 2012,40(2):151-153.

[3] 李文,张建泽.基于S3C2440的嵌入式Linux系统移植[J].化工自动化及仪表,2010,37(9):88-92.

[4] 孟庆昌,牛欣源.Linux教程[M].北京,电子工业出版社,2011.

[5] WANG W H, GAO M Y. Design of embedded media player based on S3C2440 and SDL-FFMPEG[C]∥International Conference on Electrical and Control Engineering, 2011:2979-2982.

[6] 尤盈盈,孟利民.构建嵌入式Linux交叉编译环境[J].计算机与数字工程,2006,34(6):30-34.

[7] 林炎,张友益.Windows平台下构建嵌入式Linux交叉编译环境[J].单片机与嵌入式系统应用,2013(2):74-78.

[8] 许青林,解争龙.基于ARM的Linux系统移植研究与实现[J].物联网技术,2013(1):37-42.

[9] 陈永强,陶品,王笃强.嵌入式Linux移植[J].实验室研究与探索,2012,31(9):67-72.

[10] 张瑞,于德海,马明龙.基于ARM的嵌入式Linux的交叉编译环境的建立[J].科技信息,2009(25):508-509.

[11] 何春山,谭剑.基于Redhat AS4并行计算机群的安装研究[J]. 中山大学学报:自然科学版,2006,45(3):114-116.

[12] 谭会生.ARM嵌入式系统原理及应用开发[M].西安:西安电子科技大学出版社,2012.

[13] 李佳佳,马永杰.Linux系统在S3C2440上移植的分析与实现[J].计算机系统应用,2012,21(10):214-219.

[14] 刘发贵,林恺,柴阳阳.GDIXEAP:面向服务的嵌入式软件开发平台[J].中山大学学报:自然科学版,2008,47(2):37-41.

[15] 冯钢,郑扣银.基于GCC的交叉编译研究与开发[J].计算机工程与设计,2004,25(11):1880-1883.

[16] 阳富明,李文海,涂刚.嵌入式动态库小型化技术研究[J].华中科技大学学报,2004,32(9):6-8.

猜你喜欢

源码编译器静态
面向数据可靠传输的高译码率带反馈的LT码
最新进展!中老铁路开始静态验收
静态随机存储器在轨自检算法
国内一站式工程设备租赁平台众能联合完成C2、C3两轮融资
面向理想性能空间的跨架构编译分析方法
浅谈开源操作系统的历史
企业如何保护源码
基于相异编译器的安全计算机平台交叉编译环境设计
运行速度大突破华为《方舟编译器》详解
油罐车静态侧倾稳定角的多体仿真计算