分类: LINUX
2009-08-07 17:32:35
<1>binutils: 目前(2009.8.7 )最新版本是GNU binutils is 2.19
要点:
If you have GNU make, we recommend building in a different directory:
mkdir objdir
cd objdir
../binutils-XXX/configure [options]
make
make install
This relies on the VPATH feature of GNU make.
<2>gcc : 目前(2009.8.7 )最新版本是GCC-4.4.1
从GCC-4.3起,安装GCC将依赖于GMP-4.1以上版本和MPFR-2.3.2以上版本。如果将这两个软件包分别解压到GCC源码树的根目录下, 并分别命名为"gmp"和"mpfr",那么GCC的编译程序将自动将两者与GCC一起编译。建议尽可能使用最新的GMP和MPFR版本。
<3>linux kernel : 目前(2009.8.7)最新版本是2.6.30。 从armlinux 网站可以得知,2.6.0以后的内核不需要到 armlinux网站上下载patch. 只需要在linux kernel org 上下载即可。
<4>glibc: 目前(2009.08.7 )最新版本是2.10,可以使用git进行下载。2.9之前包括2.9可以使用http下载到tar包。
相应的ports包为Glibc-ports-2.9(为了支持ARM).
for compile: please see the readme and INSTALL in the tar glibc-2.9.tar.gz
要点: 1. glibc2.4以上的版本需要2.6.16以上的LINUX内核版本。 FROM README
2.推荐使用gcc 3.2以上的编译器来编译glibc. FROM FAQ
3. 推荐使用GNU make version 3.79 or newer. FROM FAQ
4. For Linux or Hurd, you want binutils 2.13 or higher. FROM FAQ
5. make 过程用到的其他软件:
* GNU gettext.
* Perl 5 is needed if you wish to test an installation of GNU libc
as the primary C library.
下载上面介绍的软件包
<1>binutils-2.19.tar.bz2
<2>linux-2.6.30.tar.bz2
<3> GCC
gcc-4.4.1.tar.gz
gmp-4.3.1.tar.bz2
mpfr-2.4.1.tar.gz
<4>Glibc
glibc-2.9.tar.bz2
glibc-ports-2.9.tar.bz2
glibc-2.9-arm_setjmp_fix-1.patch
glibc-2.9-cross_hacks-2.patch
glibc-2.9-libgcc_eh-1.patch
glibc-2.9-localedef_segfault-1.patch
glibc-2.9-nptl_lowlevellock-1.patch
编译步骤
step1: 创建目录和设定环境变量
mkdir -p /opt/package/cross-tools/source
mkdir -p /opt/package/cross-tools/build
mkdir -p /opt/cross-tools
export HOST=i686-pc-linux-gnu
export TARGET=arm-none-linux-gnueabi (要改为none,否则glibc gcc编译不过)
export PREFIX=/opt/cross-tools
step2:将下载的软件包放到source目录中
step3:编译binutils:
cd /opt/package/cross-tools/source
tar -jvxf binutils-2.19.tar.bz2
cd /opt/package/cross-tools/build
mkdir build-binutils
cd build-binutils
$../../source/
binutils-2.19/configure \
--target=${TARGET} \
--prefix=${PREFIX} \
--disable-nls \
--disable-werror \
--disable-multilib \
--enable-shared
make configure-host (可以不要)
make
make install
--target=${TARGET}
这个选项是跟--host一起表示编译生成的可执行文件运行在HOST上面,但这些可执行文件服务的对象是TARGET,也就是说用这些可执行文件连接和汇编出来的程序运行在TARGET上面。这里,默认就会使用主机的GCC编译器, 因此我们省略了--host选项。
--prefix=${RESULT_DIR}
告诉配置脚本当运行 make install 时把编译好的东西安装在RESULT_DIR目录。
--disable-nls
这里nls的意思是本地语言支持(Native Language Support)。可以禁止, 但是使能这一项也没问题。
--disable-werror
意思是禁止把警告当成错误。如果不加这一项,编译器会严格检查语法错误,出现警告也会停止编译,这样要想编译通过就很难了。所以禁止了werror,这样编译就可顺利完成。
--disable-multilib
禁止编译适用于多重目标体系的库。纯32位系统或纯64位系统都是NON-Multilib,但是如果有x64的U,想要既可以运行64bit的程序又可以运行32bit的程序,就得安装Multilib。
--enable-shared
编译出共享链接库。
make configure-host
检查主机环境以确保所有必须的工具都已经安装。这一个命令也可以去掉,不是必须的。
这次是利用主系统(i386)的GCC工具链来完成编译的,编译出来的程序也是运行在i386上的 。编译得到的工具主要包括:
· ld - GNU连接器the GNU linker.
· as - GNU汇编器the GNU assembler.
· addr2line - 把地址转换成文件名和所在的行数
· ar - A utility for creating, modifying and extracting from archives.
· c++filt - Filter to demangle encoded C++ symbols.
· dlltool - Creates files for building and using DLLs.
· gold - A new, faster, ELF only linker, still in beta test.
· gprof - Displays profiling information.
· nlmconv - Converts object code into an NLM.
· nm - Lists symbols from object files.
· objcopy - Copys and translates object files.
· objdump - Displays information from object files.
· ranlib - Generates an index to the contents of an archive.
· readelf - Displays information from any ELF format object file.
· size - Lists the section sizes of an object or archive file.
· strings - Lists printable strings from files.
· strip - Discards symbols.
step4:制作linux内核头文件
cd /opt/package/cross-tools/source
tar -jvxf linux-2.6.30.tar.bz2
make \
ARCH=arm \
CROSS_COMPILE=${TARGET}- \
INSTALL_HDR_PATH=${PREFIX}\${ TARGET} \
headers_install
指定ARCH=arm表示拷贝对应于ARM体系结构的头文件。虽然其中指定了 CROSS_COMPILE, 而此时交叉编译器还没有生成,这没有关系,因为根本不会用到交叉编译器。
step5: 编译静态gcc
cd /opt/package/cross-tools/source
tar -xzvf gcc-4.4.1.tar.gz
tar -jvxf gmp-4.3.1.tar.bz2
mv gmp-4.3.1 ./gcc-4.4.0/gmp
tar -xzvf mpfr-2.4.1.tar.gz
mv mpfr-2.4.1.tar.gz
cd /opt/package/cross-tools/build
mkdir build-gcc
cd build-gcc
../../source/gcc-4.4.1/configure --build=${HOST} --host=${HOST} \
--target=${TARGET} --prefix=${PREFIX} --without-headers \
--with-newlib --with-float=soft --with-cpu=arm920t --with-tune=arm9tdmi \
--with-gnu-as --with-gnu-ld --disable-nls --disable-decimal-float \
--disable-libgomp --disable-multilib --disable-libmudflap --disable-libssp \
--disable-shared --disable-threads --disable-libmudflap --disable-libstdcxx-pch \
--disable-libffi --enable-languages=c
make && make install
里面有两个--disable-libmudflap,不知道为什么?笔误?step6:编译glibc
export PATH= ${PREFIX /bin}:$PATH
cd /opt/package/cross-tools/source
tar -jxvf glibc-2.9.tar.bz2
tar -jxvf glibc-ports-2.9.tar.bz2
mv glibc-ports-2.9 ./glibc-2.9/ports
cd glibc-2.9
The Glibc build will expect to find libgcc_eh
, but this library is not installed when
GCC is built without "--enable-shared". As a result, the Glibc
build will fail. The following patch will force Glibc to check for
the existance of libgcc_eh
and try to
link to it only if it exists:
patch -Np1 -i ../glibc-2.9-libgcc_eh-1.patch
The following patch fixes an issue that can cause localdef to segfault:
patch -Np1 -i ../glibc-2.9-localedef_segfault-1.patch
The following patch builds zic-native
, localedef-native
, and rpcgen-native
. zic-native
is used to generate the zoneinfo,
localedef-native
is used to generate
the locale archive, and rpcgen-native
is used to generate part of librpcsvc.a
. All of these programs would normally
not be available when cross-compiling:
patch -Np1 -i ../glibc-2.9-cross_hacks-2.patch
The following patch adds a missing hidden alias for __sigsetjmp:
patch -Np1 -i ../glibc-2.9-arm_setjmp_fix-1.patch
The following patch adds a missing include that fixes a compilation error on arm.
patch -Np1 -i ../glibc-2.9-nptl_lowlevellock-1.patch
cd /opt/package/cross-tools/build
mkdir build-glibc
cd build-glibc
为了使Glibc 支持NPTL ,需要在Glibc 编译目录下建立config.cache 文件并写入:
cat > config.cache << EOF
libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
libc_cv_arm_tls=yes
libc_cv_gnu89_inline=yes
EOF
BUILD_CC=gcc
CC=${TARGET}-gcc AR=${TARGET}-ar RANLIB=${TARGET}-ranlib
../../source/glibc-2.9/configure --build=${HOST} --host=${TARGET}
--target=${TARGET} --prefix="/usr"
--with-headers=${PREFIX}/${TARGET}/include
--with-binutils=${PREFIX}/bin --with-tls --with-__thread
--enable-sim --enable-nptl --enable-add-ons --enable-kernel=2.6.0
--disable-profile --without-gd --without-cvs
--cache-file=config.cache
make
make install_root=${PREFIX}/${TARGET} prefix="" install
BUILD_CC="gcc"
Glibc在编译过程中需要先创建一些工具,这些工具需要用主机上的GCC来编译。
CC=${TARGET}-gcc
告诉Glibc使用我们在上一步为ARM目标平台创建的交叉编译器GCC来编译C库。
AR=${TARGET}-ar \
告诉Glibc使用我们在上一步为ARM目标平台创建的ar来汇编C库。
RANLIB=${TARGET}-ranlib
告诉Glibc使用我们在上一步为ARM目标平台创建的ranlib
-with-headers=${TARGET_PREFIX}/include \
--with-binutils=${RESULT_DIR}/bin
This tells Glibc to use the Binutils that are specific to our target architecture.
--with-tls
This tells Glibc to use Thread Local Storage.
--with-__thread
This tells Glibc to use use the __thread for libc and libpthread builds.
--enable-sim \
--enable-nptl \
--enable-add-ons
This tells Glibc to utilize all add-ons that are available.
--enable-kernel=2.6.0 \
--disable-profile
This builds the libraries without profiling information. Omit this option if profiling on the temporary tools is necessary.
--without-gd \
--without-cvs \
--cache-file=config.cache
This tells Glibc to utilize a premade cache file.
对 libc.so 的修正·
vi $PREFIX /${TARGET}/lib/libc.so
去掉绝对路径,修改后的内容如下:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.3 ) )
step7 编译完整的gcc
cd /opt/package/cross-tools/build/build-gcc
rm -rf *
../../source/gcc-4.4.0/configure
--build=${HOST} --host=${HOST} --target=${TARGET} --prefix=${PREFIX}
--with-float=soft --with-cpu=arm920t --with-tune=arm9tdmi
--enable-languages=c,c++ --enable-threads=posix --enable-c99
--enable-long-long --enable-shared --enable-__cxa_atexit
--enable-nls --disable-libgomp
make
make install
-enable-languages=c,c++
This option ensures that only the C and C++ compilers are built.
--enable-__cxa_atexit
This option allows use of __cxa_atexit, rather than atexit, to register C++ destructors for local statics and global objects and is essential for fully standards-compliant handling of destructors. It also affects the C++ ABI and therefore results in C++ shared libraries and C++ programs that are interoperable with other Linux distributions.
--enable-c99
Enable C99 support for C programs.
--enable-long-long
Enables long long support in the compiler.
--enable-threads=posix
This enables C++ exception handling for multi-threaded code.
--enable-nls \
--disable-libgomp
如果不加这一项会出现如下错误:
configure: error: Pthreads are required to build libgomp
make[1]: *** [configure-target-libgomp]
错误
1
make[1]:
正在离开目录
`/home/hongwang/mktoolchain/build/gcc-4.4.0-2'
make: *** [all]
错误
2
没有找到好的解决办法,只能在configure
里增加
--disable-libgomp
第一遍只编译一个支持c 的gcc ,原因是要编译出一个支持交叉的c++ ,必须有一个编译好的用于目标体系平台的glibc ,而不是只有glibc 的头文件就可以的,好在编译glibc 有c 支持就够了,所以编译glibc 也成了第一遍的gcc 唯一的理由和作用。工具链中gcc 的第一次和第二次编译都是由主系统的gcc 和binutils 来完成的(之前没有提及binutils ,只是为了理解方便,但实际上编译后是少不了链接过程的,这个过程是要binutils 来完成的)。到目前为止只有在编译glibc 的时候用到了交叉版本的binutils ,其它部分的链接都是由主系统的binutils 来完成的。
step8 测试交叉编译工具链
到此为止,已经介绍完了用分步构建的方法建立交叉编译工具链。下面通过一个简单的程序测试刚刚建立的交叉编译工具链看是否能够正常工作。写一个最简单的hello.c源文件,内容如下:
#include
int main( )
{
printf(“Hello,world!\n”);
return 0;
}
通 过以下命令进行编译,编译后生成名为hello的可执行文件,通过file命令可以查看文件的类型。当显示以下信息时表明交叉工具链正常安装了,通过编译 生成了ARM体系可执行的文件。注意,通过该交叉编译链编译的可执行文件只能在ARM体系下执行,不能在基于X86的普通PC上执行。
# arm-rui-linux-gcc –o hello hello.c
# file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.4.3,
dynamically linked (uses shared libs), not stripped