您好,  [请登录] [QQ登录]  [支付宝登录[免费注册]

商品分类

分享到: 百度搜藏 搜狐微博 新浪微博 腾讯微博 QQ收藏 人人网 Facebook Twitter

Cygwin环境下构建arm-linux-gcc-4.5.0交叉工具链

发布日期:2011-05-02

1引言

    交叉编译工具链作为嵌入式Linux开发的基础,直接影响到嵌入式开发的项目进度和完成质量。由于目前大多数开发人员使用Windows作为嵌入式开发的宿主机,在Windows中通过安装VMware等虚拟机软件来进行嵌入式Linux开发,这样对宿主机的性能要求极高。Cygwin直接作为Windows下的软件完全能满足嵌入式Linux的开发工作,对硬件的要求低及方便快捷的特点成为嵌入式开发的最佳选择。

目前网络上Cygwin下直接可用的交叉编译器寥寥无几且版本都比较低,不能满足开源软件对编译器版本依赖性的要求(如低版本工具链编译U-Boot出现软浮点问题等);Crosstool等交叉工具链制作工具也是更新跟不上自由软件版本的进度;同时系统介绍Cygwin下制作交叉编译器方面的资料很少。针对上述情况,基于最新版gcc等自由软件构建Cygwin下的交叉编译器显得尤为迫切和重要。

2构建前准备工作

    首先Cygwin下必须保证基本工具比如make}gcc等来构建bootstrap-gcc编译器,这可以在安装Cygwin时选择安装。参照gcc等安装说明文档来在Cygwin下查看是否已经安装,如输入gcc --v等。

2.1源码下载

    gcc-4.5.0的编译需mpc的支持,而mpc又依赖gmpmpfr库。从各个项目官方网站上下载的最新的源码:

    binutils-2.20. l .tar.bz2

    gmp-S.O. l .tar.bz2

    mpc-0.8.2.tar.gz

    mpfr-3.O.O.tar.bz2

    gcc-4.S.O.tar.bz2

    linux-2.6.34.tar.bz2

    glibc-2.11.2.tar.bz2

    glibc-ports-2. l l .tar.bz2

gdb-7. l.tar.bz2

2.2设置环境变量

    HOST:工具链要运行的目标机器;BUILD:用来建立工具链的机器;TARGET工具链编译产生的二进制代码可以运行的机器。

    BUILD=i686-pc-cygwin

    HOST=i686-pc-cygwin    TARGET=arm-linux

    SYSROOT指定根目录,$PREFIX指定安装目录。目标系统的头文件、库文件、运行时对象都将被限定在其中,这在交叉编译中有时很重要,可以防止使用宿主机的头文件和库文件。本文首选$SYSROOT为安装目录,$PREFIX主要作为glibc库安装目录。

    SYSROOT=/cross-root

    PREFIX=/cross-root/arm-linux

    由于GCC-4.5.0需要mpfr,gmp,mpc的支持,而这三个库又不需要交叉编译,仅仅是在编译交叉编译链时使用,所以放在一个临时的目录。

    TEMP_PREFIX=/build-temp

    控制某些程序的本地化的环境变量:

    LC ALL=POSIX

    设置环境变量:

    PATH=$SYSROOT/bin:in:/usr/bin

    设置编译时的线程数f31减少编译时间:

    PROCS=2

    定义各个软件版本:

    BINUTILS V=2.20.1

    GCC V=4.5.0

    GMP V=5.0.1

    MPFR V=3.0.0

    MPC V0.8.2

    LINUX V2.6.34

    GLIBC V=2.11.2

    GLIBC-PORTS V=2.11

    GDB V=7.1

3构建过程详解

    鉴于手工编译费时费力,统一把构建过程写到Makefile脚本文件中,把其同源码包放在同一目录下,执行make或顺次执行每个命令即可进行无人值守的编译安装交叉工具

链。以下主要以Makefile执行过程为主线进行讲解。

3.1执行“make”命令实现全速运行

    可在CygwinShell环境下执行“make>make.log 2>&1命令把编译过程及出现的错误都输出到make.log中,便于查找:

    all:prerequest install-deps install-cross-stage-one install-

cross-stage-two

3.2预处理操作

    "make prerequest',命令实现单步执行的第一步,实现输出变量、建立目录及解压源码包等操作。0'seth”关闭bashHash功能,使要运行程序的时候,shell将总是搜索PATH里的目录[4]。这样新工具一旦编译好,shell就可以在$(SYSROOT)/bin目录里找到:    prerequest:

      set +h&&mkdir -p $(SYSROOT)/bin&&

    mkdir -p $(PREFIX)/include&&

    mkdir -p $(TEMPREFIX)&&

    export PATH LCes ALL&&

    tar -xvf gmp-$(GMP_V).tar.bz2&&

    tar -xvf mpfr-$(MPFR_V).tar.bz2&&

    tar -xvf mpc-$(MPC_V).tar.gz&&

    tar -xvf binutils-$(BINUTILS_V).tar.bz2&&

    tar -xvf gcc-$(GCC_V).tar.bz2&&

    tar -xvf linux-$(LINUX_V).tar.bz2&&

    tar -xvf glibc-$(GLIBC_V).tar.bz2&&

    tar -xvf glibc-ports-$(GLIBC-PORTS_V).tar.bz2&&

    my glibc-ports-$(GLIBC-PORTS_V)

    glibc-$(GLIBC_V)/ports&&

    tar -xvf gdb-$(GDB V).tar.bz2

3.3非交叉编译安装gcc支持包mpc

    00make install-deps”命令实现单步执行的第二步,实现mpc本地编译,mpc依赖于gmpmpfr

    install-deps:gmp mpfr mpc

    gmp:gmp-$(GMP_V)

      mkdir -p build/gmp&&cd build/gmp&&

    ../../gmp-*/configure

    --disable-shared --prefix=$(TEMP_PREFIX)&&

    $(MAKE)$(PROCS)&&$(MAKE) install

    mpfr:mpfr-$(MPFR_V)

      mkdir -p b-uild/mpfr&&cd build/mpfr&&

    ../..//mpfr-*/configure

    LDF'LAGS="-Wl,-search_paths_first”--disable-shared

    --with-gmp=$(TEMP_PREFIX)

    --prefix=$(TEMP_PREFIX)&&

    $(MAKE)$(PROCS) all&&$(MAKE) install

    mpc: mpc-$(MPC_V) gmp mpfr

      mkdir -p build/mpc&&cd build/mpc&&

    ../../mpc-*/configure

    --with-mpfr=$(TEMP PREFIX)

    --with-gmp=$(TEMP_PREFIX)

    --prefix=$(TEMP_PREFIX)&&

    $(MAKE)$(PROCS)&&$(MAKE) install

3.4交叉编译第一阶段   

"make install-cross-stage-one',命令实现单步执行的第三步,编译安装binutils,bootstrap-gcc和获取Linux内核头文件:

    install-cross-stage-one:cross-binutils cross-gcc get-kernel-headers

    编译安装binutils

    cross-binutils: binutils-$(BINUTILS_ V)

      mkdir -p build/binutils&&cd build/binutils&&

    ../..//binutils-*/configure --prefix=$(SYSROOT)

    --target=$(TARGET)--disable-nls&&

    $(MAKE)j$(PROCS)&&$(MAKE) install

    编译安装bootstrap-gcc。使用一disable-shared参数的意思是不编译和安装libgcc_ eh.a文件。glibc软件包依赖这个库,因为它使用其内部的一lgcc_eh来创建系统[6]。这种依赖

性,可通过建立一个指向libgcc.a符号链接得到满足,因为该文件最终将含有通常在libgcc- eh.a中的对象(也可通过补丁文件实现)

    cross-gcc:gcc-$(GCC_V)

    mkdir -p build/gcc&&cd build/gcc&&

    //gcc-*/configure

    --target=$(TARGET)--prefix=$(SYSROOT)

    --disable-nls --disable-shared --disable-multilib

      --disable-decimal-float--disable-threads

    --disable-libmudflap --disable-libssp

    --disable-libgomp --enable-languages=c

    --with-gmp=$(TEMP_PREFIX)

    --with-mpfr=$(TEMP_PREFIX)

    --with-mpc=$(TEMP_PREFIX)&&

    $(MAKE) -j$(PROCS)&&$(MAICE) install&&

    In -vs libgcc.a'arm-linux-gcc -print-libgcc-file-name I

    sed's/libgcc/& eh/'}

    获取Linux内核头文件:

    get-kernel-headersainux-$(LINUX_V)

    cd linux-$(LINUX_V)&&

    $(MAICE) mrproper&&$(MAKE) headers check&&

    $(MAKE) ARCH=arm&&

    INSTALLes HDR_ PATH=dest headers_ install&&

    find dest/include

    (-name .install一。-name ..install.cmd)-delete&&

    cp -rv desdinclude/* $(PREFIX)/include

3.5交叉编译第二阶段

    编译安装glibc、重新编译安装binutils、完整编译安装gcc和编译安装gdb o  "make install-cross-stage-two',命令实现单步执行的第四步:    install-cross-stage-two:cross-glibc cross-rebinutils cross-g++ cross-gdb

    编译安装glibca  glib。的安装路径特意选为$(PREFIX),与gcc更好找到动态链接库也有关系,选在$(SYSROOT)提示找不到crti.o; glibc已经不再支持i386;  glibcARM等的处理器的支持主要通过glibc-ports包来实现;正确认识大小写敏感(Case Sensitive)和大小写不敏感(CaseInsensitive)系统,大小写敏感问题主要影响到glibc,是交叉编译glibc成功的关键:Cygwin帮助手册中可知Cygwin是默认大小写不敏感的n},但是UNIX系统是大小写敏感的,这也是CygwinUNIX类系统的一个区别。通过作者自行参考制作的glibc-2.11.2-cygwin.patchT使glibc变为Case-Insensitive,此补丁主要是对大小写敏感问题改名来实现。

    交叉编译过程中安装的链接器,在安装完Glibc以前都无法使用。也就是说这个配置的forced unwind支持测试会失败,因为它依赖运行中的链接器。设置libc_  cvforced unwind=yes这个选项是为了通知configure支持force-unwind,而不需要进行测试。libc cv_c_cleanup=yes类似的,在configure脚本中使用libc_cv_c cleanup=yes,以便配置成跳过测试而支持C语言清理处理。

    cross-glibc:glibc-$(GLIBC_V)

    cd glibc-$(GLIBC_V)&&

    patch -Np 1 –i...//glibc-2.11.2-cygwin.patch&&

    cd..&&mkdir -p build/glibc&&

    cd build/glibc&&

    echo"libc cv_forcedes unwind=yes">config.cache&&

    echo "libc cv_c_cleanup=yes">>config.cache&&

    echo "libc cv_arm_tls=yes">>config.cache&&

    ../../glibc-*/configure --host=$(TARGET)

    --build=$(../OneScheme/glibc-2.11.2/scripts/config.guess)

    --prefix=$(PREFIX)--disable-profile

    --enable-add-ons --enable-kernel=2.6.22.5

    --with-headers=$(PREFIX)/include

    --cache-file=config.cache&&

    $(MAKE)&&$(MAKE) install

    重新编译安装binutils。编译之前要调整工具链,使其

指向新生成的动态连接器。

    调整工具链:

      SPECS=

    'dirname $(arm-linux-gcc -print-libgcc-file-name)'/specs

    arm-linux-gcc -dumpspecs

    sed -e 's@/lib(64)\?/ld@$(PREFTX)&@g'    -e ,}/}}*cPP}$/{n;s,$-isystem $(PREFIX)/include,}"

    >$SPECS

    echo "New specs file is: $SPECS"

    unset SPECS

    测试调整后工具链:

    echo 'main(川’>dummy.c

    arm-linux-gcc

    -B/cross-root/arm-linux/lib dummy.c

    readelf -1 a.out I grep’:/cross-roobarm-linux'

    调整正确的输出结果:

    [Requesting program interpreter: /tools/lib/ld-linux.so.2j

    一切正确后删除测试程序:

    rm -v dummy.c a.out

    重新编译binutils。指定--host,--build--target,否则配置不成功,其config.guess识别能力不如gcc做的好。

    cross-rebinutils: binutils-$(BINUTILS_V)

      mkdir -p build/rebinutils&&

    cd build/rebinutils&&CC="$(TARGET)-gcc

    -B/cross-roodarm-linux/lib/"&&AR=$(TARGET)-ar&&

    RANLIB=$(TARGET)-ranlib&&../..//binutils-*/configure

    --host=$(HOST)--build=$(BUILD)--target=$(TARGET)

    --prefix=$(SYSROOT)--disable-nls

    --with-lib-path=$(PREFIX)/lib&&

    $(MAKE)--$(PROCS)&&$(MAKE) install

    高于4.3版的gcc把这个编译当作一个重置的编译器,并且禁止在被一prefix指定的位置搜索startfiles。因为这次不是重置的编译器,并且$(SYSROOT)目录中的startfiles对于创

建一个链接到$$(SYSROOT)目录库的工作编译器很重要,所以我们使用下面的补丁,它可以部分还原gcc的老功能tai .    patch -Npl –i../gcc-4.5.0-startfiles_fix-l.patch

    在正常条件下,运行gccfixincludes脚本,是为了修复可能损坏的头文件。它会把宿主系统中已修复的头文件安装到gcc专属头文件目录里,通过执行下面的命令,可以抑

fixincludes脚本的运行[9](此时目录为/gcc-4.5.0)

    cp -v gcc/Makefile.in{,.orig}

    sed 's@\./fixinc\.sh@-c true@'

    gcc/Makefile.in.orig > gcc/Makefile.in

    下面更改gcc的默认动态链接器的位置,使用已安装在/cross-root/ann-linux目录下的链接器,这样确保在gcc真实的编译过程中使用新的动态链接器。即在编译过程中创建的所有

二进制文件,都会链接到新的glibc文件

      for file in

    $(find gcc/config -name linux64.h-o -name linux.h –o -name sysv4.h)

    do cp -uv $file{,.orig}

    sed -a 's@/lib(64)?(32)?/Id@/cross-root/arm-linux&@g’-e's@/usr@/cross-rootlarm-linux@g' $file.orig>$file echo‘

    #undef STANDARD INCLUDE DIR

    #define STANDARD_ INCLUDE DIR "/cross-root/arm-linux/include"

    #define STANDARD STARTFILE PREFIX 1 "/cross-root/arm-linux/lib"

    #define STANDARD_ STARTFILE_ PREFIX_ 2””’>>$file

    touch $file.orig done

    完整编译安装gcc。最好通过指定--libexecdir更改libexecdiratm-linux目录下。--with-local-prefix选项指定gcc本地包含文件的安装路径此处设为$$(PREFIX),安装后就会在内核头文件的路径下。路径前指定$(Pwd)则以当前路径为基点,不指定则默认以/home路径为基点,这点要注意。

    cross-g++:gcc-$(GCC-)

    mkdir -p build/g+&&cd build/g++&&

    CC="$(TARGET)-gcc AR=$(TARGET)-ar&&

    -B/cross-roodarm-linux/lib/"&&

    RANLIB=$(TARGET)-ranlib&&

    ..//gcc-*/configure

    --host=$(HOST)--build=$(BUILD)--target=$(TARGET)

    --prefix=$(SYSROOT)--with-local-prefix=$(PREFIX)

    --enable-clocale=gnu --enable-shared

    --enable-threads=posix --enable -cxa_atexit

    --enable-languages=c,c++--enable-c99

    --enable-long-long --disable-libstdcxx-pch

    --disable-libunwind-exceptions

    --with-gmp=$(TEMP_PREFIX)

    --with-mpfr=$(TEMP_PREFIX)

    --with-mpc=$(TEMP_PREFIX)&&

    $(MAKE) LD_IBRARY_ATH=

    $(pwd)/$(../../gcc-4.5.0/config.guess)/libgcc&&

    $(MAKE) install

    编译安装gdb,至此完成整个工具链的制作。

    cross-gdb: gdb-$(GDB V)

    mkdir -p build/gdb&&cd build/gdb&&

    ../../gdb-*/configure --prefix=$(SYSROOT)

    --target=$(TARGET)--disable-werror&&

    $(MAKE)-j$(PROCS)&&$(MAKE) install

3.6make clean”命令清除编译生成的文件和创建解压的文件夹

    .PHONY:clean

    dean:

    rm -fr $(TEMP_PREFIX) build

    binutils-$(BINUTIL,S_V) gcc-$(GCC_V)

    glibc-$(NEWL.IB_V) gdb-$(GDB_V)

    gmp-$(GMP_V) mpc-$(MPC_V) mpfr-$(MPFR_V)

4工具链测试

    命令行中输入以下内容:

    echo 'main(){}>dummy.c

    arm-linux-gcc -o dummy.exe dummy.c

    file dummy.exe

    运行正常的结果:

    dummy.exe: ELF 32-bit LSB executable, ARM, version 1,for GNU/Linux 2.6.22, dynamically linked (uses shared libs),not stripped.

5结束语

    本文通过gcc等自由软件编译实现Cygwin下的交叉工具链,结合详细说明给出了完整的实现步骤,最后通过简单的实例验证工具链的正确性。实际应用表明本工具链完全满足嵌入式开发应用,为在Cygwin下开发嵌入式产品扫清了障碍。

版权说明:本站部分文章来自网络,版权归原作者、原杂志社和原网站所有,本站引用仅作交流学习之用,不作为商业用途,如涉及侵权,请及时告知,本站第一时间删除。特此说明!