⼀步⼀步教你怎么编译GNUARMGCC交叉编译器arm-none-
eabi-gcc
⾸先,对于编译器这东西,我⼀向认为很⾼深,当然现在还是这么认为,呵,所以呢,⼀般都是⽤别⼈编译好的现成的编译好版本。可是最近因为要
在windows下⾯编译u-boot的原因,因为不到合适的arm编译器,故只能⾃⼰编译⼀个了。下⾯就是整个的编译过程,⼀步步来吧。
在开始之前,还要说明⼀点,这⾥所编译的gnu arm gcc编译器,运⾏时是依赖于cygwin的,⽽且这也是我所需要的,⾄于为什么,请看我的另⼀篇:如何实现在windows下⾯编译u-boot,⾥⾯已经说了详细的原因。如果你不想依赖于cygwin,那请直接⽤yagarto,或其他的windows版本的gnu arm gcc吧。
. 确定要编译arm编译器的类型和版本,下载合适的编译器源⽂件和库源⽂件
(1)类型:arm-none-eabi-gcc
(2)版本:Binutils-2.22,Newlib-1.20.0,GCC-4.7.1,GDB-7.4.1,insight-6.8.1
嘿嘿,这个版本的问题,我参考了yagarto还有⼀些其他的版本,yagarto⽤Eclipse + CDT作为代码编辑和调试的前端,所有没有编insight-6.8.1,我这时是编了,如果你不需要⽤insight来作为调试的前端,你也不⽤编,只编前⾯四个就可以了。
(3)下载所要的源⽂件:
Binutils-2.22:
.0:
也可以通过CVS来获得:
cvs -z 9 -d :pserver:dhat:/cvs/src login
{enter "anoncvs" as the password}
cvs -z 9 -d :pserver:dhat:/cvs/src co newlib
GCC-4.7.1:
GDB-7.4.1:
insight-6.8.1:
下载地址:
也可以通过CVS来获得:
cvs -z9 -d :pserver::/cvs/src login
[enter "anoncvs" as the password]
cvs -z9 -d :pserver::/cvs/src co -r gdb_6_8-branch insight
官⽹不变,下载地址这⾥只是给出参考,感觉随时会变,那时候就google或百度。
. 编译前的准备
编译之前还要做⼏件事:
1)准备好cygwin,并且装好所需要的Mingw gcc等软件,主要是devel选项下的。
2)建好编译时所要的⽬录:
⾸先,建⼀个⽤来存⼊编译好的编译器的⽬录,建义在cygwin安装⽬录下建⼀下opt⽬录,⾥⾯建⼀个arm-gnu-tools⽬录,⽐如我的cygwin是装
在:d:\cygwin,那么我就建d:\cygwin\opt\arm-gnu-tools,这样你就可以在cygwin下通过/opt/arm-gnu-tools来访问了
其次,再建⼀个⽬录build-arm-tools,然后在建⽴build-binutils, build-gcc, build-gdb, build-newlib,并且拷⼊源⽂件,解压缩。下⾯就是我建好⽬录结构:
E:\build-arm-tools
│ binutils-2.22.tar.bz2
│ build_arm_tools.bat
│ gcc-4.7.1.tar.bz2
│ gdb-7.4.1.tar.bz2
│ insight-6.8-1.tar.bz2
│ newlib-1.20.
│
├─build-binutils
├─build-gcc
├─build-gdb
├─build-insight
├─build-newlib
├─binutils-2.22
├─gcc-4.7.1
├─gdb-7.4.1
├─insight-6.8-1
└─newlib-1.20.0
其中build_arm_tools.bat是我们要进⾏编译要⽤到的脚本,主要作⽤是设置⼀些环境变量,启动cygwin环境,具体内容如下:
@echo off
set TARGET=arm-none-eabi
set PREFIX=/opt/arm-gnu-tools
set BIN_PATH=/opt/arm-gnu-tools/bin
set LANG=C.UTF-8
set CYGWIN_DIR=d:\cygwin
set PATH=%CYGWIN_DIR%\bin;%PATH%
set HOME=e:\build-arm-tools\
bash --login –i
双击启动后显⽰:
(3)确定编译参数
这部分内容的话,我是参考了yagarto, GNUARM, WinARM, devkitARM, SysGcc_ARM等,CodeSourcery和Linaro是基于linux库的,所以⽆可⽐性,最后觉得yagarto的参数最好的,然后⼜在它的基础上加了⼏个,具体的如下:
--target=arm-none-eabi
--prefix=/opt/arm-gnu-tools
--disable-nls
--disable-threads
--enable-languages=c,c++
--enable-interwork
--with-gcc
--with-gnu-ld
--with-gnu-as
--with-dwarf2
--with-float=soft
--disable-shared
--with-newlib
--enable-multilib
--disable-libssp
--disable-libstdcxx-pch
--disable-libmudflap
--disable-libgomp –v
-
-with-headers=../newlib-1.20.0/newlib/libc/include
--with-pkgversion='semilog_ARM release 01'
--enable-target-optspace
--with-cpu=cpu
--with-arch=armv7
下⾯就分别对(我知道的)参数说明⼀下吧:
--target=arm-none-eabi
所要⽣成的⽬标编译器,这⾥是arm-none-eabi,它的命名差不多是这样的arch-vendor[-os]-eabi-gcc ,对于这⾥没有os,因为没有加⼊linux下的glibc,⽽是⽤的newlib,⽤于编os或者bootloader。
--prefix=/opt/arm-gnu-tools
编译好⽣成的编译器存放的地⽅,⽐如,编好了,就会在arm-gnu-tools⽬录下⽣成所要编译器。
--disable-nls
这个参数真他妈坑爹,⽹上到的说法是“这个参数禁⽌了国际化”,我怎么看也不明⽩,结果在gcc reference book上到原⽂:Specifies that Native Language Support (NLS) be included as part of the compiler to allow for the display of warning and error messages in languages other than American English,这才明⽩,意思⼤概是:编译时只使⽤英语来作为提⽰警告和错误消息的语⾔,⽽不使⽤本地语⾔。⽐如我们编译时,提⽰也不会成中⽂。我真想抽那个第⼀个把它说成“禁⽌国际化的⼈”,这不是误⼈⼦弟⿇~~~
--disable-threads
这个参数等价于--enable-threads=single,⽽可以看到linux下的gcc的参数中写差—enable-threads=posix,具体的我也不知道什么意思,多半是⽀持多线程。
--enable-languages=c,c++
Gcc的编译的语⾔只⽀持c和c++,我看到codeSourcery上⾯还⽀持Fortran,额~~~我长见识了。
--enable-interwork
这个是⽀持thumb和arm代码的相互调⽤。
--with-gnu-ld
--with-gnu-as
--with-dwarf2
上⾯四个参数是⽤来表明显⽰表明,⽤gcc编c语⾔,gnu-as编汇编,gnu-ld链接,调试⽂件格式是dwarf2的。
--with-float=soft
这个是浮点运算⽤软件来实现,ARM中有的型号其实有还硬件浮点运逄单元的,因为很多库为了兼容,所以都使⽤软件实现,这样平台依赖没有那么强,便于移植。
--disable-shared
禁⽌共享库。linux下的库有两种:静态库和共享库(动态库)。⼆者的不同点在于代码被载⼊的时刻不同。静态库的代码在编译过程中已经被载⼊可执⾏程序,因此体积较⼤。共享库的代码是在可执⾏程序运⾏时才载⼊内存的,在编译过程中仅简单的引⽤,因此代码体积较⼩。
--with-newlib
使⽤newlib库,Newlib是⼀个⾯向嵌⼊式系统的C运⾏库。最初是由Cygnus Solutions收集组装的⼀个源代码集合,取名为newlib,现在由Red Hat维护。我们⽤它来作为我们的库,⽽不是linux的glibc
--enable-multilib
⼤部分系统上都是默认选项,这表明了针对⽬标的多种库都会被编译,这⾥是针对ARM。
--disable-libssp
--disable-libstdcxx-pch
--disable-libmudflap
--disable-libgomp
上⾯的四个参数,就是⽤来--enable-multilib中的多种库中去掉这些列出来的,具体提这些库是做什么的,还没有去细究。
--with-headers=../newlib-1.20.0/newlib/libc/include
嘿嘿,这⼈参数⼀看就明⽩了,我就不⽤多说了。
--with-pkgversion='semilog_ARM release 01'
这个也是的,我把它改成我⾃⼰的名字了。哈。
--enable-target-optspace
Specifies that the libraries should be optimized for size instead of speed,这⾥我们不⽤,默认是⽤O2优化。
--with-cpu=cpu
--with-arch=armv7
这个参数要说⼀下,如果你选了—with-cpu=arm7tdmi,那么会特别针对这个arm7tdmi来优化编译器。下⾯,你懂的,你也可以优化你想要的。这个参数和--with-arch=armv7这样是差不多意思。
好了准备⼯作基本上完了,下⾯来编译了。
. 编译GNU ARM GCC编译器
双击建好的build_arm_tools.bat,
(1)⾸先编译binutils-2.22
在提⽰$符下分别输⼊:
$cd build-binutils
$../binutils-2.22/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib
$make all
$make install
这⼀步做完之后还⽤⼀件事要做:
就是把/opt/arm-gnu-tools/bin,因为编gcc的时候,要⽤到⾥⾯的第⼀步已⽣成的程序,
可以建个快捷⽅式:
$ln -s /opt/arm-gnu-tools/bin/* /usr/local/bin
注意:以后每⼀步编译完都执⾏⼀次。
主要是我是cygwin下⾯加⼊到$PATH下没有效果,所以就⽤上⾯的⽅法了。
(2)第⼀遍编译gcc-4.7.1
这⼀次只是加⼊newlib的头⽂件,没有任何库⽂件,因为还没有⽣成
$cd ../build-gcc
$../gcc-4.7.1/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib --disable-nls --disable-threads --with-gcc --with-gnu-as --with-gnu-ld --with-dwarf2 --disable-shared --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libgomp --with-newlib --with-headers=../newlib-1.20.0/newlib/libc/include/ --enable-languages="c,c++" --with-pkgversion='semilog ARM release 01'
$make all-gcc
$make install-gcc
$ln -s /opt/arm-gnu-tools/bin/* /usr/local/bin
(3)编译newlib-1.20.0
现在就⽤新⽣成的gcc来编译newlib库
$cd ../build-newlib
$../newlib-1.20.0/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib $make all
$make install
(4)第⼆次编gcc-4.7.1
这次编译的时候是⽤新⽣成的newlib库来完成gcc带库的编译。
$cd ../build-gcc
$make all
$make install
(5)编译gdb-4.7.1
$cd ../build-gdb
$../ gdb-4.7.1/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib
$make all
$make install
$ln -s /opt/arm-gnu-tools/bin/* /usr/local/bin
(6)编译insight-6.8-1
$cd ../build-insight
$../insight-6.8-1/configure --target=$TARGET --prefix=$PREFIX --enable-interwork --enable-multilib $make all
$make install
不过在编译insight-6.8-1的时候可没有那么顺利啊,有⼀些错误要进⾏修改。具体的错误及修改如下:【1】⾸先遇到的是
HAVE_NO_SEH=1-DEXCEPTION_DISPOSITION=int -DSTDC_HEADERS=1 -DHAVE_SYS_TYPE
S_H=1 -DHAVE_SYS_STAT_H=1-DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE _STRINGS_H=1 -DHAVE_INTTYPES_H=1-DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DBUILD_t cl../../../insight-6.8-1/tcl/win/../generic/tclAlloc.c -o tclAlloc.o
In file included from ../../../insight-6.8-1/tcl/win/../generic/../win/tclWinPort.h:72:0,
from../../../insight-6.8-1/tcl/win/../generic/tclPort.h:22,
from../../../insight-6.8-1/tcl/win/../generic/tclAlloc.c:29:
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../include/w32api/winsock2.h:103:2:
warning: #warning "fd_set andassociated macros have been defined in sys/types.
This may cause runtime problemswith W32 sockets"
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../include/w32api/winsock2.h:632:32:
error: conflicting typesfor ‘select’
/usr/include/sys/select.h:31:5:note: previous declaration of ‘select’ was here
gnu编译器Makefile:423: recipe for target`tclAlloc.o' failed
make[3]: *** [tclAlloc.o] Error 1
make[3]: Leaving directory`/cygdrive/e/build-gcc/build-insight/tcl/win'
Makefile:15: recipe for target`all' failed
make[2]: *** [all] Error 2
make[2]: Leaving directory`/cygdrive/e/build-gcc/build-insight/tcl'
Makefile:6631: recipe for target`all-tcl' failed
make[1]: *** [all-tcl] Error 2
make[1]: Leaving directory`/cygdrive/e/build-gcc/build-insight'
Makefile:705: recipe for target`all' failed
make: *** [all] Error 2
错误的地⽅我⽤红⾊标出来了,是因为cygwin下的/usr/include/w32api/winsock2.h⾥⾯的:
WINSOCK_API_LINKAGE int PASCAL select(intnfds,fd_set*,fd_set*,fd_set*,const struct timeval*);
和/usr/include/sys/select.h⾥⾯的:
int select __P ((int __n, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds, struct timeval*__timeout));
两个函数冲突,因为select.h下在的定义在系统下,且后⾯还要⽤到,故注掉winsock2.h⾥的select函数即可。
【2】接下来会遇到这个错误
tclWinChan.o:In function `Tcl_MakeFileChannel':
/cygdrive/e/build-gcc/build-insight/tcl/win/../../../insight-6.8-1/tcl/win/tclWinChan.c:1052:undefined reference to `_ESP'
/cygdrive/e/build-gcc/build-insight/tcl/win/../../../insight-6.8-1/tcl/win/tclWinChan.c:1052:undefined reference to `_EBP'
/cygdrive/e/build-gcc/build-insight/tcl/win/../../../insight-6.8-1/tcl/win/tclWinChan.c:1067:undefined reference to `_ESP'
/cygdrive/e/build-gcc/build-insight/tcl/win/../../../insight-6.8-1/tcl/win/tclWinChan.c:1067:undefined reference to `_EBP'
打开tclwinChan.c 对应的 1052代码如下,怎么看也不知道错在什么地⽅。
__asm__ __volatile__ (
"movl %esp, _ESP" "\n\t"
"movl %ebp, _EBP");
上⽹ESP,EBP,突然看到 124⾏
static void *ESP;
static void *EBP;
⽤的是static 属性,想想可能是因为内嵌汇编⽆法引⽤指针引起的,于是去掉static,结果真是可以了,
就是这个原因。然后在⽹上也
到insight6.8的patch,果然就这样改。Patch的⽹址:
Fix upInsight 6.8 to build up on a x86 host and a modern GCC toolchain
arm-elf-*target debugger on a i686 host
Insight6.8 and GDB need a serious code clean up to build without warnings and errorswith GCC 4.x series.
Theproposed patch is a simple workaround so that Insight 6.8 (and previousreleases) builds OK on a x86 host. Note that would also needs to remove the
----------------------------------------------------------------------------------------------
diff -urinsight-6.8/tcl/win/tclWinChan.c w/tcl/win/tclWinChan.c
---insight-6.8/tcl/win/tclWinChan.c 2006-02-02 21:02:09.000000000 +0100
+++w/tcl/win/tclWinChan.c 2009-03-1622:07:40.711125000 +0100
@@-122,8 +122,8 @@
};
#ifdef HAVE_NO_SEH
-static void *ESP;
-static void *EBP;
+void *ESP;
+void *EBP;
#endif /* HAVE_NO_SEH */
diff -urinsight-6.8/tcl/win/tclWinDde.c w/tcl/win/tclWinDde.c
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论