crosstool是个不错的软件,能够很方便的编译自己的交叉编译环境
目前最新版本crosstool-0.43 在地址 http://kegel.com/crosstool/crosstool-0.43.tar.gz 可以下载。
首先获取工具包,解压后进入其目录
-
wget http: // kegel.com / crosstool / crosstool -0.43 . tar .gz
-
tar -xzvf crosstool -0.43 . tar .gz
-
cd crosstool -0.43
选择自己希望的模板,这儿是以arm9做试验玩,因此选择了 demo-arm9tdmi.sh 做模板。
-
cat demo-arm9tdmi. sh
可以看到
#!/bin/sh
# This script has one line for each known working toolchain
# for this architecture. Uncomment the one you want.
# Generated by generate-demo.pl from buildlogs/all.dats.txt
set -ex
TARBALLS_DIR=/home/kevin/downloads #下载的软件包存放的地址
RESULT_TOP=/home/kevin/crosstool #交叉编译环境安装在哪里
export TARBALLS_DIR RESULT_TOP
GCC_LANGUAGES=”c,c++”
export GCC_LANGUAGES
# Really, you should do the mkdir before running this,
# and chown /opt/crosstool to yourself so you don’t need to run as root.
mkdir -p $RESULT_TOP
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.3.6-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.2.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.5-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-3.4.5-glibc-2.3.6-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.2.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.2-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.5.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.5-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.0.2-glibc-2.3.6-tls.dat` sh all.sh –notest
#eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2.dat` sh all.sh –notest
eval `cat arm9tdmi.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh –notest
echo Done.
其中红色字为自己修改的地方,看最后一个红色的行,表示我们要编译 gcc 4.1.0 的,如果你想要制作某个版本的交叉编译器,就必须要找到对应的dat文件。
-
cat arm9tdmi.dat
可以看到
KERNELCONFIG=`pwd`/arm.config
TARGET=arm-9tdmi-linux-gnu
GCC_EXTRA_CONFIG=”–with-cpu=arm9tdmi –enable-cxx-flags=-mcpu=arm9tdmi”
TARGET_CFLAGS=”-O”
其中红色的文字可以根据自己的需要做修改,一般是 arm-linux ,符合网上面很多编译情形的。
-
cat gcc -4.1 .0 -glibc -2.3 .2 -tls.dat
可以看到
BINUTILS_DIR=binutils-2.16.1
GCC_CORE_DIR=gcc-3.3.6
GCC_DIR=gcc-4.1.0
GLIBC_DIR=glibc-2.3.2
LINUX_DIR=linux-2.6.15.4
LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.2
GDB_DIR=gdb-6.5
GLIBC_EXTRA_CONFIG=”$GLIBC_EXTRA_CONFIG –with-tls –with-__thread –enable-kernel=2.4.18″
通过这个文件可以看到为了生成4.1.0的交叉编译器需要各种不同软件包的版本号,制作不同版本的交叉编译器,配置时需要的软件版本号是非常严格的,将红色的字对应的bz2包下载下来(这些文件我基本都是在 chinaunix 那儿下载的,下载速度很快),放到前面设定的 /home/kevin/downloads目录中。不下载也可以,sh脚本中自己会用wget下载,但是会等很多时间,比自己直接下载多出了很多很多的时 间(具体多多少,自己试验一下就知道了,保证你试了后会很后悔,呵呵^_^)。
然后执行
./ demo-arm9tdmi.sh #可以看到在这个脚本中其实时执行了all.sh,在all.sh中其实就是将我们先前一步步制作交叉编译器的步骤综合
编译完成后,有目录 /home/kevin/crosstool/gcc-4.1.0-glibc-2.3.2/arm-linux/ 目录比较长,后来分析了一下all.sh脚本,发现可以通过设置PREFIX值来减少结果路径长度,不过编译一遍需要那么长的时间,就没有实际试验.
最后在~/.bashrc文件的最后加入: export PATH= $PATH :/ home/ kevin/ crosstool/ gcc-4.1 .0 -glibc-2.3 .2 / arm-linux/ bin
这样新打开的终端就可以使用 arm-linux-gcc 等命令了。
在使用crosstool构建工具链的过程中,出现了如下问题,导致arm-linux-gcc没有生成:
> checking version of gcc... 4.0.0, bad
> checking for gnumake... no
> checking for gmake... gmake
> checking version of gmake... 3.80, ok
> configure: error:
> *** These critical programs are missing or too old: gcc
> *** Check the INSTALL file for required versions.
察看crosstool目录中的contrib/inbox.txt文件,有关于这个问题的邮件描述:
> checking build system type... i686-pc-linux-gnu
> checking host system type... mipsel-unknown-linux-gnu
> checking sysdep dirs... sysdeps/mips/elf sysdeps/unix/sysv/linux/mips
> sysdeps/unix/sysv/linux sysdeps/gnu sysdeps/unix/common
> sysdeps/unix/mman sysdeps/unix/inet sysdeps/unix/sysv sysdeps/unix/mips
> sysdeps/unix sysdeps/posix sysdeps/mips/mipsel sysdeps/mips/fpu
> sysdeps/mips sysdeps/wordsize-32 sysdeps/ieee754/flt-32
> sysdeps/ieee754/dbl-64 sysdeps/ieee754 sysdeps/generic/elf sysdeps/generic
> checking for a BSD-compatible install... /usr/bin/install -c
> checking whether ln -s works... yes
> checking for pwd... /bin/pwd
> checking for mipsel-unknown-linux-gnu-gcc... gcc
> checking version of gcc... 4.0.0, bad
> checking for gnumake... no
> checking for gmake... gmake
> checking version of gmake... 3.80, ok
> configure: error:
> *** These critical programs are missing or too old: gcc
> *** Check the INSTALL file for required versions.
>
I have had the same problem. What I found was that the glibc configure
script was testing for a version of gcc 3.2.* or later. It does not test
for a major number above 3 so the test fails. I do not know where this
test is initiated, but once you have reached that point you can patch
the configure script and run demo-*.sh with the --nounpack option added
to your desired toolchain build.
This patch worked for me:
--- configure.orig 2005-09-19 21:31:45.000000000 -0400
+++ configure 2005-09-19 21:32:13.000000000 -0400
@@ -2274,6 +2274,8 @@
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
3.[2-9]*)
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+ 4.*)
+ ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
esac
I hope that this helps. Good Luck.
-Mike Joyce
其意思就是说,在glibc的configure脚本里会检查gcc的版本,当不是需要的版本就报错, glibc的configure中有如下检查:
if test -z "$CC"; then
ac_verc_fail=yes
else
# Found it, now check the version.
echo "$as_me:$LINENO: checking version of $CC" >&5
echo $ECHO_N "checking version of $CC... $ECHO_C" >&6
ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version /([egcygnustpi-]*[0-9.]*/).*$//1/p'`
case $ac_prog_version in
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
3.[2-9]* )
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
esac
echo "$as_me:$LINENO: result: $ac_prog_version" >&5
echo "${ECHO_T}$ac_prog_version" >&6
fi
if test $ac_verc_fail = yes; then
critic_missing="$critic_missing gcc"
fi
在上面的gcc版本检查中,只使用了模式3.[2-9]*即只支持3.xxx版本的gcc,在crosstool自己的patches目录下有一个 patch:patches/glibc-2.3.3-allow-gcc-4.0-configure.patch,他会在编译glic-2.3.2的 时候给这个configure文件先打补丁 ,所以我们只需要修改对应的补丁文件也就是patches/glibc-2.3.3-allow-gcc-4.0-configure.patch,他会在编译 glic-2.3.2时候自动的将这个补丁打在 glic-2.3.2顶层的configure文件而不需要我们自己手动来打这个补丁 ,那个补丁来修复这个bug,但是这个补丁文件也不是很好,其内容是:
--- glibc-2.3.3/configure.old Mon Mar 14 12:01:10 2005
+++ glibc-2.3.3/configure Mon Mar 14 12:02:03 2005
@@ -3899,7 +3899,7 @@
ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version /([egcygnustpi-]*[0-9.]*/).*$//1/p'`
case $ac_prog_version in
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
- 3.[2-9]*)
+ 3.[2-9]*|4.[01]* )
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
即,它只是增加了对4.0xxx或者4.1xxx的支持,还是不够,我现在用的是4.2.1因此还是会出错,因此,修改这个patch,改为3. [2-9]*|4.*) 就可以过去了。
总之,在编译glibc的时候,其configure脚本对gcc的限定是比较严格的,而且并没有将后来的较新的版本考虑在内,这种严格的检查是我们在 configure是出了错。但是如果我们直接修改glibc原码中的configure文件,又会造成crosstool在用他自己的patches给 glibc的configure打补丁的时候出错,呵呵,还是去修改crosstool的补丁文件吧,glibc就留着不要动了。