本文在前章的基础上,继续深入研究,如何能正确的编译出交叉工具链
关于 --with-sysroot 这个参数,真是一个让人觉得可恨的参数,这个参数会引起一系列的问题,前章中,不得已的在 /opt/cross_toolchains/arm 中建立了两个连接文件
mkdir usr
cd usr
ln -s ../include include
mkdir -p opt/cross_toolchains
cd opt/cross_toolchains
ln -s ../../../arm arm
还记得这两段脚本吗?让我觉得极其不爽,不得已才用这种办法去解决遇到的问题,而这两个问题都是因为使用了 --with-sysroot 这个 configure 参数而导致的,关键是我不知道如何解决!!
下面的脚本中我们将不再使用 --with-sysroot 这个configure 参数
下面的脚本将编译 arm eabi 的交叉工具链
值得注意的地方是,在编译完 glibc 后的一些处理
cd $PREFIX/arm-none-linux-gnueabi
rm lib include -rf
ln -s ../lib lib
ln -s ../include include
上面这段会解决一些看起来很难理解的问题,但我觉得这样做是正确的,因为在最后编译gcc时,需要使用到binutil的一些工具,而binutils的命令安装在bin目录下
与这个bin 同一层的 lib 和 include 目录并不存在,所以会引起编译gcc 中 pthread.h 头文件找不到,链接需要的 c 库 开工代码 ctri.o ctxxx几个 o文件找不到等问题
通过这样处理,可以解决这个问题,并且避免了使用 --with-sysroot 这个恶心的参数(autoconf 做的不够好啊,要么就是 gcc 的 autoconf脚本没写好)
比如这种问题:
arm-none-linux-gnueabi/bin/ld: cannot find crti.o: No such file or directory
自动化脚本如下,使用方法:将脚本保存为 makecross.sh,并且设置权限 chmod a+x makecross.sh,然后执行脚本./makecross.sh,可以看到帮助
后续我会补充上 targe的选择以及检测方法,cpu指令集的选择,uclibc 编译,等相关内容
#!/bin/sh
# the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
unset CPU
unset MFR
unset KERNEL
unset OS
unset VER_GCC
unset DIR_OPT
unset DIR_SRC
unset PREFIX
unset TARGET
export CPU=arm
export MFR=none
export KERNEL=linux
#export OS=uclibceabi
export OS=gnueabi
export VER_GCC=4.6.1
export DIR_OPT=/opt/cross_toolchains
export DIR_SRC=/root/cross_toolchains/src
export PREFIX=$DIR_OPT/$CPU/$VER_GCC
export CONFIGURE_BASE="../configure --prefix=$PREFIX"
export TARGET=$CPU-$MFR-$KERNEL-$OS
export PATH=$PATH:$PREFIX/bin
function do_unzip_single()
{
cd $DIR_SRC
if [ "$1" = "binutils" ];then
tar -xf binutils-2.21.tar.gz
elif [ "$1" = "gcc" ];then
tar -xf gcc-4.6.1.tar.gz
tar -xf mpfr-3.0.1.tar.gz
tar -xf mpc-0.9.tar.gz
tar -xf gmp-5.0.2.tar.gz
mv gmp-5.0.2 gcc-4.6.1/gmp
mv mpc-0.9 gcc-4.6.1/mpc
mv mpfr-3.0.1 gcc-4.6.1/mpfr
elif [ "$1" = "glibc" ];then
tar -xf glibc-2.13.tar.gz
tar -xf glibc-ports-2.13.tar.gz
mv glibc-ports-2.13 glibc-2.13/ports
elif [ "$1" = "kernel" ];then
tar -xf linux-2.6.39.2.tar.bz2
fi
}
function do_download_single_do()
{
cd $DIR_SRC
if [ ! -e $DIR_SRC/$1 ];then
wget $2
fi
}
function do_download_single()
{
FILE_NAME=""
URL=""
if [ "$1" = "binutils" ];then
set FILE_NAME=binutils-2.21.tar.gz
set URL=ftp://ftp.gnu.org/gnu/binutils/binutils-2.21.tar.gz
do_download_single_do $FILE_NAME $URL
elif [ "$1" = "gcc" ];then
set FILE_NAME=gcc-4.6.1.tar.gz
set URL=ftp://ftp.gnu.org/gnu/gcc/gcc-4.6.1/gcc-4.6.1.tar.gz
do_download_single_do $FILE_NAME $URL
set FILE_NAME=mpfr-3.0.1.tar.gz
set URL=ftp://ftp.gnu.org/gnu/mpfr/mpfr-3.0.1.tar.gz
do_download_single_do $FILE_NAME $URL
set FILE_NAME=mpc-0.9.tar.gz
set URL=http://www.multiprecision.org/mpc/download/mpc-0.9.tar.gz
do_download_single_do $FILE_NAME $URL
set FILE_NAME=gmp-5.0.2.tar.gz
set URL=ftp://ftp.gnu.org/gnu/gmp/gmp-5.0.2.tar.gz
do_download_single_do $FILE_NAME $URL
elif [ "$1" = "glibc" ];then
set FILE_NAME=glibc-2.13.tar.gz
set URL=ftp://ftp.gnu.org/gnu/glibc/glibc-2.13.tar.gz
do_download_single_do $FILE_NAME $URL
set FILE_NAME=glibc-ports-2.13.tar.gz
set URL=ftp://ftp.gnu.org/gnu/glibc/glibc-ports-2.13.tar.gz
do_download_single_do $FILE_NAME $URL
elif [ "$1" = "kernel" ];then
set FILE_NAME=linux-2.6.39.2.tar.bz2
set URL=http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.2.tar.bz2
do_download_single_do $FILE_NAME $URL
fi
}
function do_remove_single()
{
cd $DIR_SRC
# only remove the directory,but not the zip file.
if [ "$1" = "binutils" ];then
rm -rf binutils-2.21
elif [ "$1" = "gcc" ];then
rm -rf gcc-4.6.1
rm -rf mpfr-3.0.1
rm -rf mpc-0.9
rm -rf gmp-5.0.2
elif [ "$1" = "glibc" ];then
rm -rf glibc-2.13
rm -rf glibc-ports-2.13
elif [ "$1" = "kernel" ];then
rm -rf linux-2.6.39.2
fi
}
function do_reconstruction_single()
{
echo "reconstruction single package $1"
cd $DIR_SRC
do_remove_single $1;
do_download_single $1
do_unzip_single $1
}
function do_reconstruction()
{
cd $DIR_SRC
if [ "$1" = "all" ]
then
do_reconstruction_single binutils
do_reconstruction_single gcc
do_reconstruction_single glibc
else
do_reconstruction_single $1
fi
}
function do_build_single_pre()
{
if [ "$1" = "binutils" ];then
cd binutils-2.21
elif [ "$1" = "gcc_first" ];then
# glibc need kernel's .h file
mkdir -p $PREFIX/include
cd $PREFIX/include
rm -f asm
rm -f linux
rm -f asm-generic
ln -s $DIR_SRC/linux-2.6.39.2/arch/arm/include/asm asm
ln -s $DIR_SRC/linux-2.6.39.2/include/linux linux
ln -s $DIR_SRC/linux-2.6.39.2/include/asm-generic asm-generic
cd $DIR_SRC
cd gcc-4.6.1
elif [ "$1" = "glibc" ];then
cd glibc-2.13
echo "/* Value used for dtv entries for which the allocation is delayed. */" >> ports/sysdeps/arm/dl-tls.h
echo "#define TLS_DTV_UNALLOCATED ((void *) -1l)" >> ports/sysdeps/arm/dl-tls.h
elif [ "$1" = "gcc" ];then
cd gcc-4.6.1
elif [ "$1" = "kernel" ];then
cd linux-2.6.39.2
fi
# create build directory
rm -rf build
mkdir -p build
if [ "$1" = "kernel" ];then
rm -rf build
fi
}
function do_build_single_config
{
# configure
if [ "$1" = "binutils" ];then
$CONFIGURE_BASE \
--target=$TARGET \
--enable-shared
elif [ "$1" = "gcc_first" ];then
$CONFIGURE_BASE \
--target=$TARGET \
--disable-shared \
--without-headers \
--with-newlib \
--enable-languages=c \
--disable-threads
elif [ "$1" = "glibc" ];then
CC=$PREFIX/bin/$TARGET-gcc \
$CONFIGURE_BASE \
--host=$TARGET \
-enable-add-ons \
--with-headers=$PREFIX/include \
--with-binutils=$PREFIX/bin \
libc_cv_forced_unwind=yes \
libc_cv_c_cleanup=yes
elif [ "$1" = "gcc" ];then
$CONFIGURE_BASE \
--target=$TARGET \
--enable-shared \
--enable-languages=c,c++ \
--enable-c99 \
--enable-long-long \
--enable-__cxa_atexit
elif [ "$1" = "kernel" ];then
make menuconfig
fi
}
function do_build_single_make()
{
# make and make install
if [ "$1" = "gcc_first" ];then
make -j4 all-gcc all-target-libgcc
make -j4 install-gcc install-target-libgcc
cd $PREFIX/lib/gcc/$TARGET/$VER_GCC
rm libgcc_eh.a
ln -s libgcc.a libgcc_eh.a
elif [ "$1" = "glibc" ];then
make -j4
make -j4 install
cd $PREFIX/arm-none-linux-gnueabi
rm lib include -rf
ln -s ../lib lib
ln -s ../include include
else
make -j4
make -j4 install
fi
}
function do_build_single()
{
cd $DIR_SRC
echo "build single package $1"
if [ "$1" = "kernel" ];then
do_build_single_pre $1
do_build_single_config $1
else
do_build_single_pre $1
cd build
do_build_single_config $1
do_build_single_make $1
fi
}
function do_build()
{
if [ "$1" = "all" ]
then
do_build_single binutils
do_build_single gcc_first
do_build_single glibc
do_build_single gcc
else
do_build_single $1
fi
}
function do_rebuild()
{
rm -rf $PREFIX/*
do_reconstruction $1
do_build $1
}
function do_help()
{
echo "usage:"
echo " ./makecross reconstruction binutils"
echo " ./makecross reconstruction gcc"
echo " ./makecross reconstruction glibc"
echo " ./makecross reconstruction all"
echo " ./makecross build binutils"
echo " ./makecross build gcc_first"
echo " ./makecross build glibc"
echo " ./makecross build gcc"
echo " ./makecross build all"
echo " ./makecross rebuild all"
}
# main entery
# to install necessary package
# aptitude install build-essential automake bison flex texinfo gawk g\+\+ zip
# aptitude remove mawk
SOME=`aptitude show build-essential automake bison flex texinfo gawk g\+\+ zip|grep "State: not install"`
#echo $SOME
if [ ! "$SOME" = "" ];then
echo "aptitude install"
aptitude install build-essential automake bison flex texinfo gawk g\+\+ zip
fi
SOME=`aptitude show mawk | grep "State: installed"`
if [ ! "$SOME" = "" ];then
echo "aptitude remove mawk"
aptitude remove mawk
fi
# about kernel
# if there is no kernel headers,then rebuild kernel
# include/linux/version.h and include/generated/autoconf.h
if [ ! -e $DIR_SRC/linux-2.6.39.2/include/linux/version.h ];then
#echo "version"
if [ ! -e $DIR_SRC/linux-2.6.39.2/include/generated/autoconf.h ];then
echo "reconstruction kernel"
do_reconstruction_single $1
fi
fi
echo "check and rebuild env done."
# do command
if [ "$1" = "reconstruction" ];then
do_reconstruction $2
elif [ "$1" = "build" ];then
echo "build"
do_build $2
elif [ "$1" = "rebuild" ];then
do_rebuild $2
else
do_help
fi