使用交叉编译链
简介
交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc 3个部分组成。有时出于减小libc库大小的考虑,也可以用别的c库来代替glibc,例如uClibc、dietlibc和newlib。交叉编译工具链主要包括针对目标系统的编译器gcc、目标系统的二进制工具binutils、目标系统的标准c库glibc和目标系统的Linux内核头文件。第一个步骤就是确定目标平台。每个目标平台都有一个明确的格式,这些信息用于在构建过程中识别要使用的不同工具的正确版本。因此,当在一个特定目标机下运行GCC时,GCC便在目录路径中查找包含该目标规范的应用程序路径。GNU的目标规范格式为CPU-PLATFORM-OS。例如,建立基于ARM平台的交叉工具链,目标平台名为arm-linux-gnu。
交叉编译工具链的制作方法
分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。
通过Crosstool脚本工具来实现一次编译生成交叉编译工具链。
直接通过网上(ftp.arm.kernel.org.uk)下载已经制作好的交叉编译工具链。
方法1相对比较困难,适合想深入学习构建交叉工具链的读者。如果只是想使用交叉工具链,建议使用方法2或方法3构建交叉工具链。方法3的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名的错误,建议你慎用此方法。
方法1:分步构建交叉编译工具链
下载所需的源代码包
建立工作目录
建立环境变量
编译、安装Binutils
获取内核头文件
编译gcc的辅助编译器
编译生成glibc库
编译生成完整的gcc
由于在问答中的篇幅,我不能细述具体的步骤,兴趣的同学请自行阅读开源共创协议的《Linux from scratch》,网址是:linuxfromscratch dot org
。
方法2:用Crosstool工具构建交叉工具链(推荐)
Crosstool是一组脚本工具集,可构建和测试不同版本的gcc和glibc,用于那些支持glibc的体系结构。它也是一个开源项目,下载地址是kegel dot com/crosstool。用Crosstool构建交叉工具链要比上述的分步编译容易得多,并且也方便许多,对于仅仅为了工作需要构建交叉编译工具链的你,建议使用此方法。
运行which makeinfo,如果不能找见该命令,在解压texinfo-4.11.tar.bz2,进入texinfo-4.11目录,执行./configure&&make&&make install完成makeinfo工具的安装
准备文件:
下载所需资源文件linux-2.4.20.tar.gz、binutils-2.19.tar.bz2、gcc-3.3.6.tar.gz、glibc- 2.3.2.tar.gz、glibc-linuxthreads-2.3.2.tar.gz和gdb-6.5.tar.bz2。然后将这些工具包文件放在新建的$HOME/downloads目录下,最后在$HOME/目录下解压crosstool-0.43.tar.gz,命
令如下:
#cd$HOME/
#tar–xvzfcrosstool-0.43.tar.gz
建立脚本文件
接着需要建立自己的编译脚本,起名为arm.sh,为了简化编写arm.sh,寻找一个最接近的脚本文件demo-arm.sh作为模板,然后将该脚本的内容复制到arm.sh,修改arm.sh脚本,具体操作如下:
# cd crosstool-0.43
# cp demo-arm.sh arm.sh
# vi arm.sh
修改后的arm.sh脚本内容如下:
#!/bin/sh
set-ex
TARBALLS_DIR=$HOME/downloads#定义工具链源码所存放位置。
RESULT_TOP=$HOME/arm-bin#定义工具链的安装目录
exportTARBALLS_DIRRESULT_TOP
GCC_LANGUAGES="c,c++"#定义支持C,C++语言
exportGCC_LANGUAGES
#创建/opt/crosstool目录
mkdir-p$RESULT_TOP
#编译工具链,该过程需要数小时完成。
eval'catarm.datgcc-3.3.6-glibc-2.3.2.dat'shall.sh--notest
echoDone.
建立配置文件
在arm.sh脚本文件中需要注意arm-xscale.dat和gcc-3.3.6-glibc-2.3.2.dat两个文件,这两个文件是作为Crosstool的编译的配置文件。其中arm.dat文件内容如下,主要用于定义配置文件、定义生成编译工具链的名称以及定义编译选项等。
KERNELCONFIG='pwd'/arm.config#内核的配置
TARGET=arm-linux#编译生成的工具链名称
TARGET_CFLAGS="-O"#编译选项
gcc-3.3.6-glibc-2.3.2.dat文件内容如下,该文件主要定义编译过程中所需要的库以及它定义的版本,如果在编译过程中发现有些库不存在时,Crosstool会自动在相关网站上下载,该工具在这点上相对比较智能,也非常有用。
BINUTILS_DIR=binutils-2.19
GCC_DIR=gcc-3.3.6
GLIBC_DIR=glibc-2.3.2
LINUX_DIR=linux-2.6.10-8(根据实际情况填写)
GDB_DIR=gdb-6.5
执行脚本
将Crosstool的脚本文件和配置文件准备好之后,开始执行arm.sh脚本来编译交叉编译工具。具体执行命令如下:
#cdcrosstool-0.43
#./arm.sh
经过数小时的漫长编译之后,会在/opt/crosstool目录下生成新的交叉编译工具,其中包括以下内容:
arm-linux-addr2linearm-linux-g++arm-linux-ldarm-linux-size
arm-linux-ararm-linux-gccarm-linux-nmarm-linux-strings
arm-linux-asarm-linux-gcc-3.3.6arm-linux-objarm-linux-strip
arm-linux-c++arm-linux-gccbugarm-linux-objmpfix-embedded-paths
arm-linux-c++filtarm-linux-gcovarm-linux-ranlib
arm-linux-cpparm-linux-gprofarm-linux-readelf
添加环境变量
然后将生成的编译工具链路径添加到环境变量PATH上去,添加的方法是在系统/etc/ bashrc文件的最后添加下面一行,在bashrc文件中添加环境变量
export PATH=/home/jiabing/gcc-3.3.6-glibc-2.3.2/arm-linux-bin/bin:$PATH
至此,arm-linux下的交叉编译工具链已经完成,现在就可以使用arm-linux-gcc来生成试验箱上的程序了!
❷ 关于交叉编译工具链的问题
核心转储是崩溃报告的一个过程,他只是把当前崩溃的信息转存出来方便差错。而且这个核心转储几个字也不过是个提示输出信息。这个提示不会给与任何与错误相关的内容,必须看其他的错误信息或者他转储出来的东西来分析。
不过核心转储,应该是程序运行出错而崩溃。这种问题出现在你正在运行的程序,而不是编译过程出现的编译错误(也就是说,出现核心转储应该就是 GCC 或者他调用的程序自己崩溃了)。出现这个问题的原因很多。
如果是因为没有找到某些 header 文件,不应该是核心转储错误,而是编译器或者某个过程提示错误信息后退出,他会输出错误信息告诉你问题所在。
至于你编译的这些东西版本都比较老,我建议还是尝试降级整个系统来编译、运行你现在的这些东西。或者升级你这个交叉编译工具链到当前主流的版本来用。
至于交叉工具连当中的 GCC 和你当前本机的 GCC,完全是两个互相独立的 GCC 。
只是他们编译输出的二进制程序针对的指令集不同而已。相对的 binutils 和 glibc 和 kernel-header 都是一样的意思,针对目标而输出的相关程序。当然 glibc 和 kernel-header 主要是以“数据”方式存在,gcc 和 binutils 主要是以可以运行的程序方式存在(当然不是绝对的,比如 gcc 还会提供几个 lib 相关的内容,不过大部分情况下你可以这么理解更直观了解他们的作用)。
一般说来 GCC 是编译器,binutils 是连接器,glibc 是标准 C 库(主要是连接时,连接器必须有目标的函数库文件,也就是 .so 文件,对应 Windows 是 .dll 文件。连接器把函数调用正确的挂接到对应的函数入口上)。linux header 就是 C 语言常见的 C header 文件和相关的开发数据。一般主要用来编译 glibc ,glibc 作为中间层来提供内核相关调用。当然程序有些时候也会直接调用内核函数,这样这些程序在编译时也需要 kernel 的 header 。
这两套东西一个输出你当前 PC 的程序,一个输出 ARM 的程序。两个 GCC 套装之间不能互相替换。只能自己输出属于自己的程序。
但是这两套程序虽然输出的程序不同,但可以运行的部分,却都是在你的计算机上运行。而且你本机的 GCC 因为可以输出本机的程序。所以你需要用他来输出在你本机运行,但是却输出 ARM 程序的 GCC 套装。
这就好比两个锤子,一个锤子用来打铁,一个锤子用来打锡。用途不同,但这两个锤子都是铁做的。
你作这个交叉编译工具链,就是用你手里已经有的打铁的锤子,打出一个用铁制作的用来打锡的锤子。这个打锡的锤子是不能打铁的,同样这个打铁的锤子是不能用来打锡的。
❸ 交叉编译器的交叉编译
在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓平台,实际上包含两个概念:体系结构(Architecture)、操作系统(Operating System)。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,我们常说的x86 Linux平台实际上是Intel x86体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。
有时是因为目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
交叉编译这个概念的出现和流行是和嵌入式系统的广泛发展同步的。我们常用的计算机软件,都需要通过编译的方式,把使用高级计算机语言编写的代码(比如C代码)编译(compile)成计算机可以识别和执行的二进制代码。比如,我们在Windows平台上,可使用Visual C++开发环境,编写程序并编译成可执行程序。这种方式下,我们使用PC平台上的Windows工具开发针对Windows本身的可执行程序,这种编译过程称为native compilation,中文可理解为本机编译。然而,在进行嵌入式系统的开发时,运行程序的目标平台通常具有有限的存储空间和运算能力,比如常见的 ARM 平台,其一般的静态存储空间大概是16到32MB,而CPU的主频大概在100MHz到500MHz之间。这种情况下,在ARM平台上进行本机编译就不太可能了,这是因为一般的编译工具链(compilation tool chain)需要很大的存储空间,并需要很强的CPU运算能力。为了解决这个问题,交叉编译工具就应运而生了。通过交叉编译工具,我们就可以在CPU能力很强、存储空间足够的主机平台上(比如PC上)编译出针对其他平台的可执行程序。
要进行交叉编译,我们需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译我们的源代码,最终生成可在目标平台上运行的代码。

❹ 什么是交叉编译工具链
内核不同就需要交叉编译。简单的说,就是在一个平台上生成另一个平台上的可执行代码;
❺ 如何交叉编译开源库
所谓的搭建交叉编译环境,即安装、配置交叉编译工具链。在该环境下编译出嵌入式Linux系统所需的操作系统、应用程序等,然后再上传到目标机上。
交叉编译工具链是为了编译、链接、处理和调试跨平台体系结构的程序代码。对于交叉开发的工具链来说,在文件名称上加了一个前缀,用来区别本地的工具链。例如,arm-linux-表示是对arm的交叉编译工具链;arm-linux-gcc表示是使用gcc的编译器。除了体系结构相关的编译选项以外,其使用方法与Linux主机上的gcc相同,所以Linux编程技术对于嵌入式同样适用。不过,并不是任何一个版本拿来都能用,各种软件包往往存在版本匹配问题。例如,编译内核时需要使用arm-linux-gcc-4.3.3版本的交叉编译工具链,而使用arm-linux-gcc-3.4.1的交叉编译工具链,则会导致编译失败。
那么gcc和arm-linux-gcc的区别是什么呢?区别就是gcc是linux下的c语言编译器,编译出来的程序在本地执行,而arm-linux-gcc用来在linux下跨平台的C语言编译器,编译出来的程序在目标机(如ARM平台)上执行,嵌入式开发应使用嵌入式交叉编译工具链。
工具/原料
电脑系统:win7系统。虚拟机系统:workstation6.5 。虚拟机安装的linux版本:fedora9.0。内核:linux2.6.25 。
方法/步骤
1
我使用的交叉编译工具链是arm-linux-gcc-4.4.3,把它放在linux系统的路径是图一
2
在linux系统的路径/home/song/share下放了交叉编译工具链arm-linux-gcc-4.4.3的压缩包,另一个版本的不用。有的人可能会问到怎么把这个压缩包弄到虚拟机的linux的系统的,我是通过samba服务从主机复制到虚拟机的,这里的share文件夹就是我samba服务器的工作目录,多了不说,这不是重点。
然后通过命令mkdir embedded 建立一个arm-linux-gcc的安装目录,如图二所示。当然安装路径和目录名称“embedded”可以依自己的喜好而定。
步骤阅读
然后通过命令将share文件夹下的arm-linux-gcc-4.4.3.tar.gz复制到这里的embedded文件夹下, 当然这里你也可以不进行这一步我这是为了方便以后管理,将arm-linux-gcc安装到embedded文件夹下,方便以后寻找。
然后使用tar命令:tar zxvf arm-gcc-4.4.3.tar.gz将embedded文件夹下的arm-linux-gcc-4.4.3.tar.gz解压缩安装到当前目录下
执行完解压缩命令,就已经将交叉编译工具链arm-linux-gcc-4.4.3安装到linux系统上了,这里默认安装到了图六所示的路径上。
接下来配置系统环境变量,把交叉编译工具链的路径添加到环境变量PATH中去,这样就可以在任何目录下使用这些工具。 vi /etc/profile 编辑profile文件,添加环境变量。
在profile中的位置处,添加图八所示的红线标注的一行,路径就是图六中的红线标注的路径后面加上/4.4.3/bin。
图八中的路径一定是你自己的安装路径,可以使用pwd命令查找一下那个bin目录的路径。添加完路径后,保存退出。接下来使用命令:source /etc/profile,是修改后的profile文件生效,如图九所示。
然后,使用命令:arm-linux-gcc -v查看当前交叉编译链工具的版本信息,如图九中的红线标注第③行所示。很明显 可以看到,如果不执行第②步,则查看版本信息不成功。
然后验证交叉编译工具链是否安装成功并且可以使用,如图九所示,随便找一个目录编辑一个hello源代码。
编辑好hello.c文件后,保存退出。然后使用交叉编译器对hello.c进行编译,并生成可执行文件hello
这里生成的hello文件并不能像gcc编译出来的文件那样直接使用“./hello”命令执行并显示内容 因为它是一个二进制文件,只能下载到开发板上执行!
至此,搭建交叉编译环境步骤结束。
❻ 为什么要用交叉编译器
交叉编译,简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓平台,实际上包含两个概念:体系结构(Architecture)、操作系统(Operating System)。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,我们常说的x86 Linux平台实际上是Intel x86体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。
有时是因为目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
综上,在嵌入式开发的时候我们就要使用交叉编译器。
❼ 如何制定android交叉编译工具链
经常搞嵌入式开发的朋友对于交叉编译环境应该并不陌生,说白了,就是一组运行在x86 PC机的编译工具,可以让你在PC机上编译出目标平台(例如ARM)可识别的二进制文件。Android平台也提供了这样的交叉编译工具链,就放在Android的NDK开发包的toolchains目录下,因此,我们的Makefile文件中,只需给出相应的编译工具即可。
废话就先说到这,直接上例子,我们目标是把下面这个math.c文件编译成一个静态库文件:
#include <stdio.h>
int add( int a , int b ) {
return a+b;
}
你需要编写一个Makefile文件,这里假设你的Android ndk被安装在 /opt/android/ndk 目录下,当然,你可以根据自己的实际情况修改Makefile中相关路径的定义,Makefile文件示例如下:
# Makefile Written by ticktick
# Show how to cross-compile c/c++ code for android platform
.PHONY: clean
NDKROOT=/opt/android/ndk
PLATFORM=$(NDKROOT)/platforms/android-14/arch-arm
CROSS_COMPILE=$(NDKROOT)/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
CC=$(CROSS_COMPILE)gcc
AR=$(CROSS_COMPILE)ar
LD=$(CROSS_COMPILE)ld
CFLAGS = -I$(PWD) -I$(PLATFORM)/usr/include -Wall -O2 -fPIC -DANDROID -DHAVE_PTHREAD -mfpu=neon -mfloat-abi=softfp
LDFLAGS =
TARGET = libmath.a
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
all: $(OBJS)
$(AR) -rc $(TARGET) $(OBJS)
clean:
rm -f *.o *.a *.so
这里不讲Makefile文件的基本原理,只说明一下针对Android环境的Makefile文件编写的注意事项。
(1) CROSS_COMPILE
必须正确给出Android NDK编译工具链的路径,当在目录中执行make命令的时候,编译系统会根据 CROSS_COMPILE 前缀寻找对应的编译命令。
(2) -I$(PLATFORM)/usr/include
由于Android平台没有使用传统的c语言库libc,而是自己编写了一套更加高效更适合嵌入式平台的c语言库,所以系统头文件目录不能再使用默认的路径,必须直到Android平台的头文件目录
(3) -Wall -O2 -fPIC -DANDROID -DHAVE_PTHREAD -mfpu=neon -mfloat-abi=softfp
这些参数的意义网上基本上都有介绍,我就不一一解释了,并不都是必须添加的,但比较常用。
编译方法:
写好makefile文件,并且保存之后,就可以直接在当前目录下执行make命令,编译完成后,当前目录下会生成 libmath.a ,即可直接拿到Android的jni工程中和使用了。
❽ arm-linux-gnueabihf交叉编译工具链使用问题
与使用gcc或g++方法一样,只是把命令替换成arm-linux-gnueabihf-gcc或arm-linux-gnueabihf-g++
例如
arm-linux-gnueabihf-gcc -g -o helloworld main.c
写Makefile文件时也要注意命令的替换,举例
CC=arm-linux-gnueabihf-gcc
helloworld : main.c
$(CC) -g -o helloworld main.c
❾ 如何交叉编译 动态库
首先,你要保证你编译的程序使用的交叉编译链是开发板支持的,例如arm-linux-4.3.2,一般是在虚拟机下面的linux系统下的/etc/profile里面添加编译链路径;接着,需要确保使用的内核是开发板目前使用的内核,一般MINI2440是使用linux-2.6.30版本的,这个要在程序的makefile文件里面改;还有,如果你使用静态编译方式文件会比较大,但是不用依赖库,如果是用动态编译,文件就比较小,但是依赖动态库,如果放到开发板上运行提示缺少动态库,就证明你没有把动态库放进开发板的/lib里面,可以用ldd指令查看需要哪些库;最后,记住移植的方式可以使用NFS或者TFTP,U盘也可以,放到开发板上后必须在文件存放的当前目录下./可执行文件,或者把文件放入/bin或者/sbin下面,就可以直接可执行文件,不用加./你可以在程序里面加些调试信息输出,例如printf,以此证明有执行。
