构建ARM GNU交叉编译器

10

有一个类似但描述较少的帖子在这里

我正在尝试使用Ubuntu上的最新版本发布来制作自己的工具链,并希望在这里有足够的Linux社区,以便在遇到特定问题时可以获得具体建议。

借助大家的帮助,我希望最终能将其变成一个有用的参考资料。

首先,“Crosstool”,几乎所有人都提到过,有点过时(2006年),而“Crosstool-NG”现在似乎正在继续开发,但在我的机器上无法正常运行。我宁愿调试过程本身,而不是脚本(似乎需要我理解整个过程)。

以下是迄今为止我已经完成的基本步骤;目前我卡在尝试编译第一遍GCC上。

出错的地方...

它失败了,因为缺少包含"crti.o"的交叉编译库:

# ./gcc-4.4.1/configure --target=arm-linux --disable-thread --enable-langauges=c 
/bin/bash ../../../gcc-4.4.1/libgcc/../mkinstalldirs .
/usr/src/gnu-4.4.1-build/./gcc/xgcc -B ........
/usr/local/arm-linux/bin/ld: crti.o No such file: No such file or directory
collect2: ld returned 1 exit status
make[2]: *** [libgcc_s.so] Error 1
make[2]: Leaving directory `/usr/src/gnu/gcc-4.4.1-build/arm-linux/libgcc'
make[1]: *** [all-target-libgcc] Error 2
make[1]: Leaving directory `/usr/src/gnu/gcc-4.4.1-build'
make: *** [all] Error 2

构建步骤

在一个“全新”配置的Ubuntu 9.04安装中,这里是我目前已经完成的步骤:

#New configuration of Ubuntu 9.04
sudo updatedb
sudo apt-get install build-essential subversion
# For kernel configuration
sudo apt-get install libncurses5-dev
# For building GCC
sudo apt-get install libgmp3-dev libmpfr-dev

#Get Linux Headers for GCC/GLIBC compilations
# I use a hacked Linux from Artilla, 
pushd ~ && svn co http://.../linux m501-linux && cd !$
make ARCH=arm m501_defconfig
make ARCH=arm menuconfig
sudo mkdir /usr/local/arm-linux/include
sudo cp -dR include/asm-arm /usr/local/arm-linux/include/asm
sudo cp -dR include/linux /usr/local/arm-linux/include/linux
cd /usr/local/arm-linux/
sudo ln -s include sys-include
popd

#Get sources:
cd /usr/src/
sudo su root
mkdir gnu
ftp ftp.gnu.org
# get gnu/binutils/binutils-2.19.1.tar.bz2
# get gnu/gcc/gcc-4.4.1/gcc-4.4.1.tar.bz2
# get gnu/glibc/glibc-2.10.1.tar.bz2
# get gnu/gdb/gdb-6.8.tar.bz2

#Build Binutils
bzcat binutils-2.19.1.tar.bz2 | tar -xv
mkdir binutils-2.19.1-build && cd !$
cp ../binutils-2.19.1/gas/config/tc-arm.c ./tc-arm.c 
sed -r 's/(as_bad[ \t]*\()(.+\[.+\]\))/\1\"%s\",\2/' < ./tc-arm.c > ../binutils-2.19.1/gas/config/tc-arm.c 
rm ./tc-arm.c    
../binutils-2.19.1/configure --target=arm-linux
make && make install && cd ..

#Build GCC
bzcat gcc-4.4.1.tar.bz2 | tar -xv
mkdir gcc-4.4.1-build && cd !$
../gcc-4.4.1/configure --target=arm-linux --disable-thread --enable-langauges=c -with-headers=/usr/local/arm-linux/include
make

到处都是企鹅! :) - Tim Post
抱歉,我误读了你的问题,我假设你知道正确的libc将存在于目标主机上..而你只是在外部架构上进行编译。好吧,至少现在你有一个可用的ARM工具链 :) - Tim Post
7个回答

7

欢迎,你并不孤单。

故事背景

我不知道为什么ARM交叉编译如此困难。这不是我的观点,让我们看看别人怎么说...

构建用于嵌入式系统开发的gcc/glibc交叉工具链曾经是一项可怕的任务,需要铁一般的意志、数天甚至数周的努力、大量Unix和Gnu知识,有时还要愿意采取冒险的捷径。(http://www.kegel.com/crosstool/)

我的ARM电脑(GuruPlug)运行在Debian上,所以我只需要一个标准的G++编译器,无需任何调整。

我在笔记本上使用32位Ubuntu。有AVR交叉编译器的deb包,甚至有Z80的,但没有ARM的 - 为什么?好吧,我们得自己编译一个。开始吧。编译工具链的过程对我来说有点混乱。长达14k行的Makefile,谢谢。

经过几天(几个晚上)的尝试后,我失败了。

解决方案

最终,我找到了一个开箱即用的解决方案。我只是下载了这个东西的lite版本:http://www.codesourcery.com/sgpp/lite_edition.html 现在我很高兴。它有一个丑陋的安装程序,但它可以工作。它说: arm-none-linux-gnueabi-g++ (Sourcery G++ Lite 2010q1-202) 4.4.1,这是一个最新的G++版本。

(我的朋友有一台Mac,他在与它斗争了一个星期之后也未能编译出工具链。他现在在运行Ubuntu的虚拟机上使用这个编译器。)


我的特别挑战是要链接一个使用目标上现有库的工具链,并编译更近期版本的内核。我最终让它工作了,虽然放弃一个记录在案的方法几周后,但我不知道自己做了什么。现在,我将这些二进制文件作为tarball移动,只要我的主机安装了32位库。 - Jamie
顺便说一下,CodeSourcery的销售人员,至少是Carlos,在我理解我的需求方面非常有帮助。由于这些需求,他们无法为我提供“开箱即用”的帮助;尽管如此,我对他们为潜在客户提供的服务印象深刻。 - Jamie

3

这里是HelenOS arm-32工具链安装脚本,使用起来非常方便。我现在正在Ubuntu上使用它(我是HelenOS的开发人员之一)。这个脚本是由Martin Decky编写的。

#!/bin/bash

# Cross-Compiler Toolchain for ${PLATFORM}
#  by Martin Decky <martin@decky.cz>
#
#  GPL'ed, copyleft
#


check_error() {
    if [ "$1" -ne "0" ]; then
        echo
        echo "Script failed: $2"
        exit
    fi
}

if [ -z "${CROSS_PREFIX}" ] ; then
    CROSS_PREFIX="/usr/local"
fi

BINUTILS_VERSION="2.19.1"
GCC_VERSION="4.3.3"

BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2"
GCC_CPP="gcc-g++-${GCC_VERSION}.tar.bz2"

BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/"
GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/"

PLATFORM="arm"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"

echo ">>> Downloading tarballs"

if [ ! -f "${BINUTILS}" ]; then
    wget -c "${BINUTILS_SOURCE}${BINUTILS}"
    check_error $? "Error downloading binutils."
fi
if [ ! -f "${GCC_CORE}" ]; then
    wget -c "${GCC_SOURCE}${GCC_CORE}"
    check_error $? "Error downloading GCC Core."
fi
if [ ! -f "${GCC_OBJC}" ]; then
    wget -c "${GCC_SOURCE}${GCC_OBJC}"
    check_error $? "Error downloading GCC Objective C."
fi
if [ ! -f "${GCC_CPP}" ]; then
    wget -c "${GCC_SOURCE}${GCC_CPP}"
    check_error $? "Error downloading GCC C++."
fi

echo ">>> Creating destionation directory"
if [ ! -d "${PREFIX}" ]; then
    mkdir -p "${PREFIX}"
    test -d "${PREFIX}"
    check_error $? "Unable to create ${PREFIX}."
fi

echo ">>> Creating GCC work directory"
if [ ! -d "${OBJDIR}" ]; then
    mkdir -p "${OBJDIR}"
    test -d "${OBJDIR}"
    check_error $? "Unable to create ${OBJDIR}."
fi

echo ">>> Unpacking tarballs"
tar -xvzf "${BINUTILS}"
check_error $? "Error unpacking binutils."
tar -xvjf "${GCC_CORE}"
check_error $? "Error unpacking GCC Core."
tar -xvjf "${GCC_OBJC}"
check_error $? "Error unpacking GCC Objective C."
tar -xvjf "${GCC_CPP}"
check_error $? "Error unpacking GCC C++."

echo ">>> Compiling and installing binutils"
cd "${BINUTILSDIR}"
check_error $? "Change directory failed."
./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" "--disable-nls"
check_error $? "Error configuring binutils."
make all install
check_error $? "Error compiling/installing binutils."

echo ">>> Compiling and installing GCC"
cd "${OBJDIR}"
check_error $? "Change directory failed."
"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj --without-headers --disable-shared
check_error $? "Error configuring GCC."
PATH="${PATH}:${PREFIX}/bin" make all-gcc install-gcc
check_error $? "Error compiling/installing GCC."

echo
echo ">>> Cross-compiler for ${TARGET} installed."

抱歉可能会有换行问题,这很容易解决。如果你需要pastebin或http链接获取它,只需留下评论即可。


谢谢。我正在尝试;之前我希望我可以将您脚本中的配置行直接粘贴到我上面尝试的内容中……但没有成功(至少目前还没有)。 - Jamie
你测试过这个吗?Bin utils编译不了。在BINUTILS的编译中,我添加了一些“sed”脚本来更改其中一个源文件。请参见http://www.mail-archive.com/bug-binutils@gnu.org/msg06475.html。 - Jamie
1
除了编译 BinUtils 时出错外,如果你需要一个裸机编译器,这个可以工作。我需要一个 Linux/GLIBC 工具栈。谢谢。 - Jamie
1
结果证明,你的答案并不是我所问的问题,而是我本应该问的问题。(也就是说,我不需要一个交叉编译的GLIBC,因为目标系统上已经存在了一个。) - Jamie
@Jamie - 抱歉,我假设你知道这一点(并且只是在构建不同于主机机器架构的软件包)。 - Tim Post

3

你应该更加努力地使用crosstool-NG,因为crosstool邮件列表非常活跃。由于理解整个过程是一项巨大的任务,理解如何使用可能会重复使用的工具在我看来更有趣。


同意,我正在朝那个方向努力。但是我已经使用COTS arm板三年了,自己制造处理器、内存等有一个令人信服的商业案例。crosstool-NG非常出色,但它在“sys-root”中产生了相当大的占用空间。这项工作正在变成一种爱好,我想说“是啊,我可以做到,但为什么要麻烦呢”。 - Jamie

2
我最近使用crosstool-ng为ARM构建了GNU工具链。要想让这些工具链组件相互兼容,需要尝试多次才能找到正确的版本,但我最终成功地使用以下版本进行了构建:
- binutils 2.19.1 - gcc 4.3.2 - gmp 4.2.2 - linux kernel 2.6.29.1 - mpfr 2.3.1 - uClibc 0.9.30.1
如果你也想尝试,请看看是否适用于你。
此外,作为构建过程的一部分,OpenWrt创建了一个交叉编译工具链。即使您不想制作无线路由器,您也可以选择基于ARM的板子作为目标来尝试它。

1

如果你真的想要为自己构建整个工具链:
http://frank.harvard.edu/~coldwell/toolchain/
http://ftp.snapgear.org/pub/snapgear/tools/arm-linux/build-arm-linux-3.4.4
请注意,你应该搜索工具链兼容矩阵,否则可能会遇到奇怪的编译错误。

如果你仍然有使用crosstool-ng的选项,这就是我最近几天一直在做的事情:
http://blog.stranadurakov.com/2009/08/04/how-to-arm-linux/
在这里,你将找到我的crosstool-ng配置文件,它对我很有效。


1

我在使用buildroot构建用于交叉编译Linux的工具链和库方面运气不错。Buildroot使用轻量级的uclibc C库而不是glibc,因此它可能不适用于您的目的。(通过这种方式获取工具链可能不如自己编译令人兴奋。)


-1

这有点转移注意力。显然,在现有系统上交叉编译一个带有工作GLIBC的工具链不需要重新编译GLIBC。老实说,我不知道我是怎么忽略了这个事实。

所以,尽管我仍然不知道如何交叉编译GCC GLIBC,但我只需要GCC,因此我将把它标记为关闭。

如果可以的话,我会回来标记我最终做了什么。

编辑:

检查this


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接