交叉编译

来源:互联网 发布:淘宝买家秀怎么发微淘 编辑:程序博客网 时间:2024/05/21 07:32

参考一

交叉编译大致过程

1、首先配置环境变量。环境变量主要是为了下面的步骤做准备,如PATH等环境变量。将安装交叉编译器的bin目录添加到PATH环境变量,如

export PATH=/opt/eldk/usr/bin:$PATH

2、进入源码包根目录下,运行./configure。configure命令有很多参数可配置,可以用./configure –help来查看,在交叉编译过程中可设置–host,–target,–build这几个参数,如–host=ppc-linux,–build=i686-pc-linux-gnu,–target=ppc-linux。

个人理解是–host表示主机上安装的交叉编译器对应目标板的架构和所运行操作系统,–target表示目标板的架构和所运行操作系统,–build表示主机的架构及操作系统类型。这些参数配置后,configure时会读取源码目录下面的config.sub文件,查找、检查设置的参数是否支持,如ppc架构是否支持、linux操作系统是否支持等。./configure –prefix参数表示生成的库文件所安装的目录,默认的是在/usr/local目录下。其他参数含义可以通过./configure –help来查看,configure过程中若失败可通过查找config.log文件来查找出错原因。./configure –diabale-可以把源码包中的某个模块不配置,编译的时候也就不编译,如配置thinkfinger时–disable-pam将pam模块配置排除在外。

3、make。make的过程如果前期配置了正确的环境变量并configure成功后一般都没遇到什么问题,具体问题具体解决,可以通过查看控制台打印出来的信息了解make的过程。

4、make install,主要是把生成的库文件、可执行文件等拷贝到合适的目录下,目标目录根你./configure时设置的–prefix参数有关。同样可以通过查看控制台打印出来的信息了解make install过程。

附:thinkfinger的交叉编译过程

./configure –host=ppc-linux –build=i686-pc-linux-gnu –target=ppc-linux –prefix=/opt/eldk/ppc_4xx/usr –disable-pam
make install
make

地址:http://www.360doc.com/content/11/1128/22/1317564_168224249.shtml

交叉编译 host,build target的含义:
build就是你正在使用的机器,host就是你编译好的程序可以运行的平台,
target就是你编译的程序可以处理的平台.
这个 build和host比较好理解,但是target就不好办了,到底什么意思呢?
一般来说,我们平时所说的交差编译用不到他target的,
比如. /configure –build=i386-linux,–host=arm-linux就可以了,在386的平台上编译可以运行在arm板的程序.

原文地址 http://oss.lzu.edu.cn/blog/blog.php?/do_showone/tid_116.html

参考二

一)交叉编译器简介

在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,这个编译过程就叫交叉编译.简单地说,就是在一个平台上生成另一个平台上的可执行代码.
(二)体系结构与操作系统

(1)常见的体系结构有ARM结构、x86结构等.

(2)常见的操作系统有linux,windows等.

(3)同一个体系结构可以运行不同操作系统,如x86上可以运行Linux、Windows等,在ARM上可以运行Linux、WinCE.

(4)同一个操作系统可以在不同的体系结构上运行,比如Linux可以运行在x86上,也可以运行在ARM上.

(5)同样的程序不可能运行在多个平台上,比如Windows下应用程序不能在Linux下运行.如果一个应用程序想在另一个平台上运行,必须使用 针对该平台的编译器,来重新编译该应用程序的二进制代码.比如在Linux系统下运行Windows平台的QQ软件,必须按照以下几个步骤:
1.QQ程序源代码
2.使用Linux下的编译器来编译QQ软件的源代码
这样编译出来的可执行程序就可以在Linux下运行了.所以,如何使ARM来运行用户的应用程序呢,就需要用到针对ARM的编译器来编译程序.

(三)使用交叉编译器的原因

ARM上可以运行操作系统,所以用户完全可以将ARM当做计算机来使用,理论上也可以在ARM上使用本地的编译器来编译程序.但是,编译器在编译程序时, 会产生大量的中间文件,这会占用很大的内存和磁盘空间,且对CPU处理速度要求较高,比如S3C2440A内存、磁盘空间只有几十到100多兆,CPU只 有400-500MHz,完全达不到编译程序的要求.所以,在进行ARM-linux嵌入式开发时必须在PC机(x86结构)上编译出能够运行在ARM上 的程序,然后再将程序下载到ARM中来运行.这就用到了交叉编译器.

要进行交叉编译,用户需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译用户的源代码,最终生成可在目标平台上运行的代码.交叉编译工具链可以从网上下载,也可以自己制作.但编译器 不是万能的,受版本限制,编译某些程序时会报错.常见的交叉编译工具链有:

(1)Cross -2.95.3 tar: 该版本较早,除了编译vivi外一般不使用.

(2)arm920t-eabi.tgz: 4.1.2版本的编译器,支持eabi,可以编译TX2440A开发板上的所有程序.

(3)arm-linux-gcc: 4.3.2版本的编译器,支持eabi,是最常见的交叉工具链.

Attention!!!

什么是EABI
EABI,Embeded application binary interface,即嵌入式应用二进制接口,是描述可连接目标代码、库目标代码、可执行文件影像、如何连接、执行和调试以及目标代码生成过程,和c, c++语言接口的规范,是编译连接工具的基础规范,也是研究它们工作原理的基础.简而言之,EABI就是一种编译规范,交叉编译器在编译时,对于浮点运算 会使用硬浮点运算,而对于没有硬浮点运算的处理器,比如S3C2440,会使用软浮点,但这样会在速度上受到很大的限制,而EABI则对浮点运算进行了优 化,提高了浮点运算的性能,节省了编译时间.

(四)安装交叉工具链arm-linux-gcc 4.3.2

安装交叉编译器arm-linux-gcc就是在主机平台(pc机的Linux操作系统)上安装对应的交叉编译工具链,换句话说,是将交叉编译器arm-linux-gcc 4.3.2在Linux操作系统下安装.安装步骤:

(1)启动Samba服务器,打开共享目录/home/lishuai,将压缩文件arm-linux-gcc-4.3.2.tgz复制到/home/lishuai下.

(2)解压软件包arm-linux-gcc-4.3.2.tgz.

[root@localhost lishuai]#tar xzvf arm-linux-gcc4.3.2.tgz

1.目录4.3.2就是该交叉编译器的目录.从arm-linux-gcc-4.3.2.tgz解压信息来看,该软件包需要解压在usr/local /arm下,而实际却解压到了共享目录/home/lishuai下

2.进入目录usr/local/内,并没有找到arm文件夹,所以需要新建一arm文件夹,再将目录4.3.2移动到新建目录usr/local/arm下.其中,4.3.2/bin就是arm-linux-gcc的可执行文件.
[root@localhost local]#mv /home/lishuai/usr/local/arm/4.3.2 ./

3.进入目录/usr/local/arm/4.3.2/bin,可以看到不同类型的编译器.但在ARM下经常用到是arm-linux-gcc.其实它 也是一个gcc编译器,与gcc使用方法一致,不过该编译器是针对arm体系结构、Linux操作系统的编译器.利用该编译器就可以编译出运行在ARM上 的Linux操作系统下的应用程序.

4.进入目录/usr/local/arm/4.3.2/arm-none-linux-gnueabi.其中,lib目录下存放的是库文件,用户编写的应用程序在运行时就依赖于这些库文件.

5.此时还不能编译源码,系统一般会提示找不到命令arm-linux-gcc.这是环境变量在作祟.所以必须修改环境变量PATH.
[root@localhost lishuai]#vi /etc/profile

在”export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC”这一行的下面添加环境变量,
输入:export PATH=/usr/local/arm/4.3.2/bin:$PATH
指定变量PATH为交叉编译器的路径,目的是告诉操作系统可以到目录/usr/local/arm/4.3.2/bin下查找可执行文件
6. 使环境变量生效

root@localhost lishuai#:source /etc/profile
//使已修改的配置文件/etc/profile生效

7.查看arm-linux-gcc编译器的版本

[root@localhost lishuai]#arm-linux-gcc -v

(五)arm-linu-gcc应用实例

实例:如何使用交叉编译器编译源码包boa-0.94.13.tar.tar
1. 启动SMB服务器,将源码包放在共享文件夹/home/lishuai下
2. 输入命令: tar xzvf boa-0.94.13.tar.tar

//解压该源码包

//一般的源码包内有Makefile文件,执行make就可以编译,但该源码包内没有,此时执行make是无效的

//仍然没有Makefile,但找到了configure文件,通过执行configure文件可以生成Makefile

[root@localhost lishuai]# ./configure

//运行configure文件,生成了Makefile文件
//由于要编译出在ARM平台上的程序,就需要使用交叉编译器.在Makefile文件内的绿色大写字母都是Makefile变量,可以看到变量 CFLAGS = -g -o2 -pipe -Wall -l,该变量是设置编译选项;变量CC = gcc,该变量是设置需要使用的编译器.由于要使用交叉编译器arm-linux-gcc,所以该变量应设置为CC = arm-linux-gcc,CPP = arm-linux-gcc -E,保存并退出.

[root@localhost lishuai]#make

//执行make进行编译
//生成名为boa的可执行程序,该程序可下载到ARM内来执行

其实,这个过程也叫做移植.移植就是将一个源码包经过修改、配置、交叉编译,然后下载到一个平台上运行.比如经常移植的有Bootloader、内核、QT等.

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hanzengyi/archive/2010/11/06/5991915.aspx

参考三

  首先,所谓的configure虽然用的多,但是它也只是一个自动生成的东西,如果你打开这个东西一看,那真和天书差不多。我们下载下来的Linux开源工程,往往编译步骤是先执行命令./configure,检查是否符合编译条件,然后生成一个Makefile,才是make & make install。这个configure是一个自动生成的脚本文件,所用的工具是autoconf和automake,这两个工具,根据configure.in和makefile.am文件(可能还需要makefile.in吧,我不太清楚),生成configure。如果你拿到的开源代码有configure,那么肯定也有configure.in和makefile.am,这两个,才是人写给人看的,configure是机器写给机器看的。

  所以,如果我们想对一个由configure编译的工程进行交叉编译,一个思路就是修改configure.in和makefile.am(可以还需要修改makefile.in),不过显然我不是这样做的,太花时间了,还要额外去学autoconf和automake。一个比较简单的办法是通过设置configure的参数,因为configure也是一个工具,具有很好的可定制性。

  交叉编译,一般来说就是两个地方处理好就可以了:编译器和依赖库。

  对于configure来说,编译器可以通过环境变量CC来设置,因为configure生成编译器指向的时候,就是从环境变量里面找的,CC是C语言编译器,C++啊什么的,和普通Makefile的也是完全一样的。

  设置依赖库也是和makefile一样的,通过环境变量LDFLAGS。设置对应的头文件则是通过环境变量CFLAGS。

  那么,一个办法是直接修改这三个环境变量(暴力了一点),在一个办法就是在命令行里临时指定这三个环境变量,我用的是后面的办法,写了一个脚本文件如下:

CC=/usr/local/arm11-toolchain/g4.4.2/cross-tools/bin/g-4.4.2 \
LDFLAGS=”-L/home/third_party/source/lib -L/home/third_party/library/g-4.4.2/zlib/lib” \
./configure –build=i686-pc-linux –host=arm-linux –target=i686-linux \
–enable-shared –prefix=PREFIX withfreetypeconfig=PREFIX/bin/freetype-config \
–enable-libxml2 –with-arch=arm \
CFLAGS=-I/home/third_party/library/g-4.4.2/freetype/include-I/home/third_party/library/g-4.4.2/freetype/include/freetype2 \

  第一行指定了交叉编译所用的编译器

  第二行指定了依赖库所在的目录

  最后一行是头文件所在目录,这个放在前面应该也可以……不过我没试过。

  但是需要注意的是粗体的那几行,–build指明的是在什么环境下编译,–host是要编译到哪个环境,–target是在什么环境下运行。如果你要做交叉编译,这三个选项是一定要写上的,否则configure不知道自己是在进行交叉编译。

  剩下的两个选项,就是原来的编译手册要求的,我照猫画虎放上去而已啦。每一行结束处的斜杠表示下一行要接上来(好长一行吧,所以才写成脚本)。

  你在做configure工程的交叉编译的时候,可以先试试看按照上面的办法,指定编译器、依赖库和头文件目录,另外就是加上build、host、target这三个参数,对于大部分程序,应该就可以了。

这里是一个比较详细的 configure参数:http://www.linuxsky.org/doc/newbie/200801/242.html

如果你对自己写configure有兴趣,可以参考这里:http://www.ibm.com/developerworks/cn/linux/l-makefile/

参考四

Linux的交叉编译 及configure配置

这两天需要把一个CDVS的工程代码从Linux 平台上移植到ARM平台上,花了两天才搞定,之前很早申请的博客,到现在还没有技术文章会,以后决定凡是花两三天才搞定的东西都会把解决过程发到这里,很多东西靠百度什么的不太好使,必要的时候确实Google更好用。想想也是,在百度上搜,很多都是迄今为止中国程序员碰到过的问题,在Google上搜就是全世界程序员碰到过的问题。废话不多说了,切入正题。

由于原工程已经在PC-Linux上跑通,所以只需要修改configure的配置参数即可。这里我通过linux下的build.sh来对configure传入脚本。

下面试build.sh的脚本内容:

#!/bin/sh# build the CDVS Test Model# with full optimizations and multithreading:CFLAGS="-march=armv7-a -O2 -DNDEBUG -fopenmp -pipe"export PATH=$PATH:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin# run configure with optimization flags and prepending "tm-" to all binaries (e.g. tm-extract, tm-match, etc.)mkdir -p buildcd buildCC=arm-hik_v7a-linux-uclibcgnueabi-gcc CXX=arm-hik_v7a-linux-uclibcgnueabi-c++ LD=arm-hik_v7a-linux-uclibcgnueabi-ld AR=arm-hik_v7a-linux-uclibcgnueabi-ar AS=arm-hik_v7a-linux-uclibcgnueabi-as NM=arm-hik_v7a-linux-uclibcgnueabi-nm STRIP= RANLIB=arm-hik_v7a-linux-uclibcgnueabi-strip  OBJDUMP=arm-hik_v7a-linux-uclibcgnueabi-objdump ../configure --build=i386-pc-linux-gnu --host=arm-hik_v7a-linux-uclibcgnueabi --target=arm-hik_v7a-linux-uclibcgnueabi --cache-file=arm-hik_v7a-linux-uclibcgnueabi.cache prefix=$HOME/cdvs_bin_for_arm --program-prefix="tm-" CFLAGS="${CFLAGS}" CXXFLAGS="${CFLAGS}" # build all binariesmake# install all binaries in $HOME/bin (no need of admin priviledges)make install

对脚本的内容进行分析:

首先是CFLAGS,里面定义了需要传入到configure的参数这里的-march变量是目标机的系统架构也就是architecture,由于我们的目标机上平台是armv7-a,所以此处赋值armv7-a。此处要留心,我一开始没有改,依然是native,那么configure会自动的用本机的arch值传入,这样就会编译失败。我一开始也不清楚这个地方具体应该填什么。这样我们可以查看编译器支持的芯片类型。

我的编译器的前缀是arm-hik_v7a-linux-uclibcgnueabi,所以这是这个编译器下所有工具的前缀。

由于交叉编译器已经安装在/usr/local/arm目录下,并且已经把/uar/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin目录添加到/etc/profile文件中,所以在控制台中可以直接调用编译器。

在控制台中我们输入arm-hik_v7a-linux-uclibcgnueabi-gcc -v 此命令会输出该编译器的版本信息
这里写图片描述

在输出图片中我们可以看到变量–with-arch=armv7-a,一开始输成了ARMv7-A,各种乱试,确实需要从根源下手,直接查看编译器版本信息。OK,接下来进入下一步。

可以看到脚本中还有一句PATH=$PATH:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin 这是对当前脚本执行的环境加上环境变量,不知道为什么在系统中添加环境变量后还是脚本运行时不能检索到编译器位置,一直报错,可以看config.log的输出日志。

PATH: /usr/local/sbinPATH: /usr/local/binPATH: /usr/sbinPATH: /usr/binPATH: /sbinPATH: /bin

在这里并没有将我们环境变量的值给读进来,

而我打开终端中直接打印PATH,发现值已经在里面了。此处不太明白,所以我在build.sh里又中添加了export语句在临时追加环境变量。

louyihang@ubuntu:~$ echo $PATH/home/louyihang/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin

接着我们在当前目录下用mkdir 创建build文件夹,整个编译过程中的各种输出文件都将会在这里除了最后的exe。

在下面可以看到我定义了一堆变量,用来指定编译器

CC=arm-hik_v7a-linux-uclibcgnueabi-gcc CXX=arm-hik_v7a-linux-uclibcgnueabi-c++ LD=arm-hik_v7a-linux-uclibcgnueabi-ld AR=arm-hik_v7a-linux-uclibcgnueabi-ar AS=arm-hik_v7a-linux-uclibcgnueabi-as NM=arm-hik_v7a-linux-uclibcgnueabi-nm STRIP= RANLIB=arm-hik_v7a-linux-uclibcgnueabi-strip  OBJDUMP=arm-hik_v7a-linux-uclibcgnueabi-objdump ../configure --build=i386-pc-linux-gnu --host=arm-hik_v7a-linux-uclibcgnueabi --target=arm-hik_v7a-linux-uclibcgnueabi --cache-file=arm-hik_v7a-linux-uclibcgnueabi.cache prefix=$HOME/cdvs_bin_for_arm --program-prefix="tm-" CFLAGS="${CFLAGS}" CXXFLAGS="${CFLAGS}" 

CC变量指定的是gcc编译器,可以在configure文件中得知这个变量来告诉configure关于交叉编译器gcc的信息,同理CXX 指的是C++,只要前缀不变,所以接下来依样画葫芦把所需要用到的编译器直接定义在 configure语句执行之前。

CC=arm-hik_v7a-linux-uclibcgnueabi-gcc CXX=arm-hik_v7a-linux-uclibcgnueabi-c++ LD=arm-hik_v7a-linux-uclibcgnueabi-ld AR=arm-hik_v7a-linux-uclibcgnueabi-ar AS=arm-hik_v7a-linux-uclibcgnueabi-as NM=arm-hik_v7a-linux-uclibcgnueabi-nm STRIP= RANLIB=arm-hik_v7a-linux-uclibcgnueabi-strip  OBJDUMP=arm-hik_v7a-linux-uclibcgnueabi-objdump 

需要注意的是其实你这些语句总共是4行,其实这里是没有回车的,因为这整个一长串都是一条语句,只不过在configure的的编译器参数需要再configure之前被设置。

OK这里弄完。接着看我们configure之后的参数。

–build参数指定的是编译器完成整个build的工程的机器结构在这里我们输入i386-pc-linux-gnu

–host参数指定最终生成可执行文件的运行环境 arm-hik_v7a-linux-uclibcgnueabi (也就是我们用的交叉编译器工具的前缀——即编译器的文件夹的名字 )这些都是一致的

–target参数目标机的环境等同host。

–cache-file在这里指定缓存文件的名字,在该文件中我们可以看到编译过程中的整个测试过程的结果和反馈。

–prefix=$Home/cdvs_bin_for_arm 这里是最终生成可执行文件的安装目录也就是exe的存放目录。可以根据自己的需要调整。

后面的–program-prefix CFLAGS CXXFLAGS的参数与linux PC机上一样不用调整。

OK最后在最后跟上make make install 完成整个configure的配置。

当然什么事情都不会跟教程一样顺利,接下来的问题总是不断。

在终端中输入 sudo ./build.sh | more

看输出内容
这里写图片描述

可以看到出现了 checking whether the C compiler works …no 后面还出现了error。

看来 交叉编译器并没有开始工作。所以转入到build 文件夹下 打开config.log的输出日志。
这里写图片描述

看到一条语句 arm-hik_v7a-linux-uclibcgnueabi-gcc-raw: libgomp.spec: No such file or directory

很明显这是由于库里少了一个文件,没有被编译器找到,所以需要再库里面添加进liggomp.spec这个文件。

当时把我迷糊了好久,上哪里去整个这个文件,上百度也百度不到,上google也不好使。

想到他毕竟是个gcc的编译器,库里面的东西大概都差不多吧,所以我去找了标准的arm-linux-gcc的库文件,记得当时的百度云里还有一份stm32的资料,整了一个下来。
这里写图片描述

打开这个arm-linux-gcc-4.4.3.tgz直接在压缩包里面检索关键字libgomp

果然在这个编译器同样的lib下有了一堆跟libgomp相关的文件,所以把这些文件拷入到我们所需要的arm-hik_v7a-linux-uclibcgnueabi的编译器库下面

OK再运行一次configure
这里写图片描述
咦,居然还是不过,再次看config.log文件
这里写图片描述
看到中间有一句 lib/libgomp.so: file not recognized: treating as linker script 和下面 lib/libgomp.so:1: syntax error。 不识别,这文件应该是不需要的被引入了,所以在Lib中将其删除。再次运行
这里写图片描述
OK 大功告成,可以看到whether the C compiler works …. yes 接下来一堆文件的测试,并且在指定目录生成了exe。

整个过程花了差不多2天时间,第一次弄交叉编译,确实是有点费劲的,也发现了一些自己的不足,之前没有看log文件的习惯,后来发现这个东西是非常好的,非常有助于我们分析问题的原因。第一次写blog,写的比较乱,希望能帮到碰到同样问题的你!
转自:http://www.cnblogs.com/louyihang-loves-baiyan/p/4171368.html

0 0