【提要】 在对skyeye了解并动手实践后,发现原来嵌入式软件开发的交叉编译环境也并不好理解和掌握,今天就回头对交叉编译环境的基本问题进行小结,迟点再针对各种具体目标的编译环境配置具体方法进行总结。
【内容】
交叉编译问题的由来:
做过简单C语言编译的朋友知道,我们以前接触的程序设计和编译并没那么复杂,只要在机子上写好程序,调用编译工具(如Turbo C)做一个编译就可以获得可执行文件了,然后直接就可以启动程序,观察结果。注意,这里有一个我们很少注意的问题:写程序的平台、编译程序的平台、运行程序的平台,三者都是一样的,都是同一类型的机,甚至就是完全在一台计算机上,比如我们的x86 PC机。
而我们做嵌入式软件的开发,实际原理上也可以像以往的工作那样简单,即让编译环境统一在运行环境中。但精明的人们不这么做,可执行的二进制文件最终是在目标板上的,而目标板做了最吝啬的设计,一般没有足够的资源可供编译软件的安装和运行。这就需要把编译和运行两步分隔开来,让程序的设计和编译工作安排在宿主机,比如安装x86 PC的linux系统中,然后再把可执行文件下载到开发板上运行。这种“借卵孵蛋”的做法牵扯出一个麻烦的问题,就是需要目的明确地针对特定的目标板(主要的是板上CPU类型的差别)进行程序的编译,而嵌入式目标板的类型实在太多了,所以,根据需要,建立交叉编译环境就有N多套不同的具体配置方式,让特定的编译工具组合起来特定编译适应于目标CPU运行的软件。另外,编译嵌入式系统时,根据不同的对象系统(如uclinux、ucosii等)也需要特定的编译工具配合。所以出现了arm-linux交叉编译环境、建立uclinux交叉编译环境等等不同却有部分重叠的配置,这其实是种定制的方式。而各种看起来一样却不能通用的配置,各种不同的编译工具,正是让初学者摸不着头脑的。
当然,现在有许多集成开发环境,减小了开发工具配置的难度,只要选择你的目标开发板/CPU,要编译的嵌入式系统,就可以自动选择合适的编译工具进行编译。但像原始的GNU TOOLS CHAIN就没那么简单,学习使用基本的GNU工具对我们来说也是大有裨益的。
下面就基于GNU工具对常见的目标CPU的交叉环境配置基本步骤和常见的编译相关工具进行一个概括。
基本的编译工具及配置:
1、认识本地GNU编译环境
首先了解gcc本地编译工具/环境,在通过源码安装skyeye的时候用到的就是本地gcc环境。
gcc需不需要安装呢?怎样安装?
“如果你对Unix/Linux有所了解的话,你应该知道他们大都自带了C和C++的编译器,分别是GCC和G++”(本句摘自网上文章)。其实redhat linux9在安装的时候选择了develop tools,就安装了包括gcc的C/C++编译工具,版本是3.2.2。可以在终端中输入:
#gcc -v (因为gcc本身是一个命令,故可以这样查看版本,但glibc,gdb等的版本就不能这样了)
来查看系统中的gcc版本。我装的是redhat9,完全安装,查看到的gcc信息是:
gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
另外,也可以通过
#rpm -q gcc
来查看gcc版本信息,我得到的信息是
gcc-3.2.2-5
如果你的系统没有gcc,你可以用光盘对系统进行升级,在内容中选上develop tool支持就可以了,当然,也可以从相关网站下载gcc源码安装。
实际,linux一般自带了GNU工具集,包括gcc,glibc,当然还有gdb,binutils。可以通过下面的命令查看其版本:
#rpm -q glibc
#rpm -q gdb
#rpm -q binutils
我的系统中的信息是:
glibc-2.3.2-11.9
gdb-5.3post-0.20020129.18
binutils-2.13.90.0.18-9
补充说明的是,如果具体开发工作中需要其他版本的GNU工具,就需要对相应的软件包进行卸载、升级、重装了。
2、交叉编译环境
对于skyeye本机编译和运行的软件,可以直接用上面提到的自带gcc工具,但如果针对不同的CPU/开发板编译不同的嵌入式系统(注意:两个问题,一个是目标板的类型;一个是嵌入式系统),就需要再配置特定的编译环境了,这就是所谓的交叉编译环境。常见的情况如下:
------------------------------------------------------------------------------------
下面的理解不准确!!纠正见2006-12-14后记
------------------------------------------------------------------------------------
注意:下面的嵌入式系统都是基于ARM CPU目标板的,如果针对其他类型的目标板则需要不同的一套编译工具和环境
uC/OS-II(或简单写成ucosii)
需要交叉编译工具arm-elf-tools,比如arm-elf-tools-20030314.sh 注意并不是最新版的交叉编译工具都适用的,要看它支不支持你要编译的什么系统,用在什么板上。
实际上arm-elf-tools也并不是单纯针对arm板的ucosii系统的,只能简单点准确地说arm+ucosii就是需要arm-elf-tools
uClinux(或写成uclinux)
需要arm-elf-tools交叉编译环境,这个恰巧与ucosii是一样的。
arm-linux(或写成armlinux)
需要arm-linux-gcc类的交叉编译工具,具体的安装包如cross-2.95.3.tar.bz2,arm-linux-gcc- 3.3.2.tar.bz2,有时候可能不止安装一个arm-linux-gcc类的工具包,但无论怎样,清楚一个问题:arm-linux嵌入式系统就是需要arm-linux-gcc交叉编译环境。
这只是一个大略的说明,具体的可以见下面的常见的编译相关工具
3、说明:
1、一般意义上,当提到GNU工具(集),GNU Tools的时候,泛指gcc工具,binutils二进制工具程序集,gdb调试工具,甚至包括glibc库等,即它泛指一个合理的编译环境或工具。
而要指明gcc命令的时候就一般用这样的说法:gcc工具,gcc软件包。同理,要说明二进制工具的时候也会具体说binutils工具/软件包。
一句话:由于称代的习惯,GNU,GNU工具,GNU Tools等在不同的场合会有不大一致的含义。这点是需要注意的。
2、另外,具体的开发中(特定的CPU和特定的嵌入式系统)当具备合适的交叉编译环境后,可能还需要作一些附加配置,比如准备合适版本的特定的库文件等(如glibc库)。
3、还有,binutils软件包、gcc软件包、glibc软件包这三个重要的东西是相对独立的,没直接联系,独立发行和维护。选择三个软件包配置合适的交叉编译环境的时候注意,并不是3个软件包的任意版本组合都是可用的!可以通过尝试来获得可用的组合,也可以通过别人的经验来得到合理的版本组合方式。这个问题可以参考相关的资料,比如《源码开放的嵌入式系统软件分析与实践——基于skyeye和 arm开发平台》陈渝 李明 杨晔 等编著 北京航空航天大学出版社
------------------------------------------------------------------------------------
(2006-12-14)后记:
要理解和制作交叉编译工具链绝不是一件容易的事情!到现在写补记,我才基本了解各个概念和工具之间的本质差别。看了之前写下的上面的理解,有点乱套,但也开心自己算也是对比从前有进步了。
首先,交叉编译工具在交叉编译项目中是必须的!
第二,交叉编译工具你需要自己去准备,而且还要自己去指定工具的位置,而不是自动去找的,除非你把工具放在系统搜索的路径,如/usr/bin或 /usr/local/bin,做了新的交叉工具并不影响原先安装的本地gcc工具(以前我还老担心这么多工具装下来会不会冲突,打架,覆盖啊,其实不是的,很简单,它只是一个文件包,放在任何一个位置,在一个具体的编译过程中,只有你指定用它,才会找到它)
第三,关于编译什么嵌入式系统需要什么交叉工具的问题,以前的理解就很明显是不准确的。
这里需要分几点说明:
1、不同的目标板/cpu,需要的交叉工具肯定是不同的!
2、同一系统的目标,如arm交叉编译,它需要的交叉编译工具也不是固定的,单纯是arm交叉编译工具就够晕的,需要考虑第一,你想编译什么内核系统? uclinux还是arm-linux?第二,你编译的内核是什么版本?对于不同版本的内核,需要的交叉工具本质上说可以说是一样的,但要求的高低不同,故需要选择合适版本的gcc,glbic,binutils等去做工具链。简单说,拿现成的工具链来说,编译2.4内核用cross2.95.3就可以了,但编译2.6内核,就需要换用3.3.2的工具链了~
然后,还有个问题,在低版本内核编译中使用什么工具链是不定的,如2.4内核当然可以用2.95.3的,但还可以用3.3.2的!uclinux一般使用 arm-elf那套工具就可以了,但如果uclinux-dist中Makefile指明用arm-linux的工具,也不是不可以的!反正没那么简单,但我也一时说不清楚了~只是看到以前写的东西在误导人很不爽而已...
第四,关于arm-elf-和arm-linux-工具,他们本质上属于适合编译不同版本的linux内核而使用的,但这个名称则是很虚的!那套工具叫arm-linux-只是个习惯命名而已,如果你亲自做过交叉编译工具链就知道,利用gcc,binutils,glibc等一堆东西去做工具链的时候,可以用一个参数去指定编译出来的工具链用什么样的前缀,记得好象是--target = 这个参数,只是大家习惯用arm-linux而已了。所以以前我说“编译armlinux系统一定需要arm-linux工具链“实在没什么意义。
常见的编译相关工具:
鉴于各种编译工具名称类似却各有分别,而且版本繁多,下面就对我掌握的资料进行简单的小结。以便需要时查阅。
GNU Tools
gcc软件包
binutils软件包
glibc软件包
patch
下面是《源码开放的嵌入式系统软件分析与实践——基于skyeye和arm开发平台》陈渝 李明 杨晔 等编著 北京航空航天大学出版社 附带光盘材料的说明
下面内容也可见http://www.cublog.cn/opera/showart.php?blogid=1780&id=54609
cdrom
│ cd.txt
│
├───ARMlinux (针对linux-2.4.x内核的armlinux补丁)
│ ├───v2.4
│ │ patch-2.4.13-ac2-rmk1.bz2
│ │ patch-2.4.13-ac4-rmk1.bz2
│ │ patch-2.4.13-ac5-rmk1-broken.bz2
│ │ patch-2.4.13-ac5-rmk2.bz2
│ │ patch-2.4.13-ac8-rmk1.bz2
│ │ patch-2.4.18-rmk7.bz2
│ │ patch-2.4.19-rmk7.bz2
│ │ patch-2.4.21-rmk2.bz2
│ │
│ └───xscale
│ └───pxa (针对基于ARM的linux-2.4.x内核的XScale架构的PXA2xx的补丁)
│ diff-2.4.18-rmk7-pxa1.gz
│ diff-2.4.18-rmk7-pxa2.gz
│ diff-2.4.18-rmk7-pxa3.gz
│ diff-2.4.19-rmk7-pxa1.gz
│ diff-2.4.19-rmk7-pxa2.gz
│
├───DevelopTools (交叉编译工具)
│ ├───ARMlinux_gnutools (for ARM Linux)
│ │ │ README
│ │ │
│ │ ├───arm (可以用来编译大多数针对带MMU和Cache的ARM核CPU的开发板的操作系统)
│ │ │ cross-2.95.3.tar.bz2 (可以编译linux-2.4.x以下(包括linux-2.4.x)版本)
│ │ │ arm-linux-gcc-3.3.2.tar.bz2 (可以编译linux-2.6.x)
│ │ │
│ │ └───xscale (对Intel XScale架构的CPU进行了优化的交叉编译工具)
│ │ xscale-gcc-3.3.3.tar.bz2 (可以编译linux-2.6.x)
│ │
│ └───uClinux_gnutools (for uC/os-II,uClinux)
│ │ genromfs-0.5.1.tar.gz (用来生成romfs文件系统的工具)
│ │
│ └───arm
│ arm-elf-tools-20030314.sh 和arm-elf-tools-20011219.tar.gz (可以编译uClinux和uC/OS-II的交叉编译工具)
│
│
├───Hardware (各种基于ARM的开发板硬件文档资料)
│ ├───ARM (关于ARM核CPU的硬件文档)
│ │ doc.tar.bz2
│ │
│ ├───ARM_Evaluator_7T (关于ARM_Evaluator_7T硬件开发板的硬件文档和部分相关源码)
│ │ doc.tar.bz2
│ │ source.tar.bz2
│ │
│ ├───AT91_EV40 (关于基于Ateml AT91X40 CPU的开发板AT91_EV40的硬件文档资料)
│ │ doc.tar.bz2
│ │
│ ├───CirrusLogic_EP7312 (关于基于CirrusLogic EP7312 CPU的开发板硬件文档资料)
│ │ doc.tar.bz2
│ │
│ ├───Intel_Lubbock_XScale (关于Intel XScale 架构、PXA2xx CPU和Lubbock开发板的硬件文档资料)
│ │ doc.tar.bz2
│ │
│ ├───Intel_StrongARM (关于Intel StrongARM CPU和开发板的硬件文档资料)
│ │ doc.tar.bz2
│ │
│ └───Strong_44B0 (关于基于Samsung S3C44B0X CPU的思创开发板硬件文档资料)
│ doc.tar.bz2
│ source.tar.bz2
│
├───SkyEye
│ │ skyeye.conf.txt (有关skyeye.conf的说明文档)
│ │ softwarerelations.txt (与skyeye相关软件的依赖关系文档)
│ │ skyeye-v0.8.0.rh9.bin (在rh9上编译的0.8.0版本的skyeye的二进制文件)
│ │
│ ├───skyeye (截止到本书出版时,SkyEye的最新发行版本)
│ │ skyeye-0.8.0.tar.bz2
│ │
│ ├───testsuit (用于演示嵌入式OS在skyeye模拟的各种开发板上运行的测试套件)
│ │ skyeye-binary-testutils-1.0.7.1.tar.bz2
│ │
│ ├───uclinux4skyeye (可在skyeye上运行的uclinux的网络驱动程序)
│ │ skyeye.conf.txt
│ │ softwarerelations.txt
│ │ uclinux4skeye-v0.1.1b1.tgz
│ │ uclinux4skeye-v0.1a1.tgz
│ │ uclinux4skeye-v0.1b1.tgz
│ │ uclinux4skeye-v0.2.tgz
│ │ uclinux4skyeye-v0.2.1.tgz
│ │ uclinux4skyeye-v0.2.2.tgz
│ │ uclinux4skyeye-v0.2.3.tgz
│ │
│ ├───ucosii4skyeye (可在skyeye上运行的ucosii操作系统和相关应用程序包括TCP/IP协议栈)
│ │ ucos_lwip_4skyeye.v1.0.preview.src.tgz
│ │ ucosii-verA-skyeye-1.0.1.src.tar.bz2
│ │ ucosii-verA-skyeye-1.0.tar.bz2
│ │ ucosii-verB-skyeye-1.0.1.src.tar.bz2
│ │ ucosii-verB-skyeye-1.0.tar.bz2
│ │ ucosii-verB-skyeye-1.1.src.tar.bz2
│ │ ucosii.src.tar.bz2
│ │ ucosii4skyeye-1.4-preview.src.tgz
│ │ ucosii4skyeye-1.8.4.tgz
│ │ ucosii4skyeye-v1.6b2.tgz
│ │ ucosii4skyeye-v1.6b3.tgz
│ │ ucosii4skyeye-v1.6b4.tgz
│ │ ucosii4skyeye-v1.7.tgz
│ │ ucosii4skyeye-v1.8.1.tgz
│ │ ucosii4skyeye-v1.8.2.tgz
│ │ ucosii4skyeye-v1.8.3.tgz
│ │ ucosii4skyeye-v1.8.tgz
│ │
│ ├───vnet (skyeye的虚拟hub内核模块,配合skyeye虚拟网络实现)
│ │ skyeye.conf.txt
│ │ softwarerelations.txt
│ │ vnet-v0.1.tgz
│ │ vnet-v0.2.tgz
│ │
│ └───armlinux4skyeye (可在skyeye上运行的armlinux和minigui源代码)
│ └───ep7312
│ │ linux-2.4.13-patched-4-ep7312.tar.bz2 (armlinux源代码,已打过补丁,可直接编译)
│ │
│ └───minigui-packages (minigui1.3.0发行包,做过少量更改,并增加了针对skyeye的配置脚本)
│ libminigui-1.3.0-4-skyeye.tar.gz
│ mde-1.3.0-4-skyeye.tar.gz
│ minigui-res-1.3.0-4-skyeye.tar.gz
│
├───demo(演示视频)
│ build_armlinux_4_skyeye.avi (演示如何编译armlinux for skyeye)
│ build_cross_compile_enviroment.avi (演示建立交叉编译环境)
│ build_install_skyeye.avi (演示配置编译安装skyeye)
│ build_uclinux_4_skyeye.avi (演示如何编译uclinux for skyeye)
│ build_ucosii_4_skyeye.avi (演示如何编译ucosii for skyeye)
│ readme (详细的步骤说明)
│ skyeye-ep7312-armlinux-minigui-same.avi (演示minigui在skyeye上运行)
│
├───systemsoft (各种嵌入式系统软件)
│ ├───busybox (一种多功能的嵌入式软件工具)
│ │ busybox-1.00-pre10.tar.gz
│ │
│ ├───glibc (标准的GNU C库)
│ │ glibc-2.3.2.tar.bz2
│ │ glibc-linuxthreads-2.3.2.tar.bz2
│ │
│ ├───lwip (嵌入式TCP/IP协议栈)
│ │ lwip-0.6.2.tar.gz
│ │
│ └───uclibc (轻量级嵌入式C库)
│ uClibc-0.9.26.tar.bz2
│
└───uClinux (uClinux的发行版本及针对2.6版本的补丁)
│ uClinux-dist-20030522.tar.gz
│
└───v2.6 (针对linux-2.6.x的uClinux补丁)
linux-2.6.0-test1-uc0.patch.gz
linux-2.6.0-test10-uc0.patch.gz
linux-2.6.0-test11-uc0.patch.gz
linux-2.6.0-test2-uc0.patch.gz
linux-2.6.0-test3-uc0.patch.gz
linux-2.6.0-test4-uc0.patch.gz
linux-2.6.0-test5-uc0.patch.gz
linux-2.6.0-test6-uc0.patch.gz
linux-2.6.0-test7-uc0.patch.gz
linux-2.6.0-test8-uc0.patch.gz
linux-2.6.0-test9-uc0.patch.gz
linux-2.6.0-uc0.patch.gz
linux-2.6.1-uc0.patch.gz
linux-2.6.2-hsc0.patch.gz
linux-2.6.2-uc0.patch.gz
linux-2.6.3-uc0.patch.gz
linux-2.6.5-uc0.patch.gz
linux-2.6.6-uc0.patch.gz
通过上面的资料,也可以基本了解各个常见的编译工具之间的分别了,包括各种库文件,内核文件等。
*****************************************************************************************************************************
后记:
完整的交叉编译工具分2部分:
1)交叉编译器arm-linux-gcc
2)编译的内核。
arm-linux-gcc提供了gcc编译器和链接时需要的lib;
内核了需要的头文件等符号参数。
大家只注重1,而往往忽视2。其实任何编译的代码都是面向一定的内核版本的。
同一个版本的arm-linux-gcc对2.4和2.6版本的内核生成目标代码时难道没有区别吗?肯定是有区别的!
所以编译时最好采用 arm-linux-gcc -o helloworld helloworld.c -I/linux-2.6/include,根据内核指定头文件,不要采用gcc自带的include。
【遗留问题】
1、如果系统中的gcc或自己后来安装的gcc版本不合使用要求,那么怎样进行gcc的卸载和改装呢?gcc好像是安装在usr/bin/下的,那里很多东西,不好找出文件手工删除……
2、
【参考资料】
1、SkyEye详细安装使用指南 v0.4 陈渝 20030122
这是网上流传的比较经典的文章,详细介绍了在windows下及在linux下安装和使用skyeye的方法,值得研究和收藏。
2、在Linux下安装skyeye的方法
CSDN上的文章
3、本站网络资源导航
下载需要工具的链接
4、《源码开放的嵌入式系统软件分析与实践——基于skyeye和arm开发平台》陈渝 李明 杨晔 等编著 北京航空航天大学出版社