编译环境
主机硬件环境:
$ uname -a
Linux PC 4.4.0-42-generic #62-Ubuntu SMP Fri Oct 7 23:11:45 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
主机软件环境:
$ cat /etc/issue
Ubuntu 16.04.1 LTS
需要安装的工具:
sudo apt-get install libncurses5-dev
sudo apt-get install gperf
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install texinfo
sudo apt-get install help2man
sudo apt-get install gawk
sudo apt-get install libtool
sudo apt-get install libtool-bin
sudo apt-get install automake
libncurses5-dev:
developer’s libraries for ncurses(执行 make menuconfig 时需要)
gperf:
一个完美的hash函数生成器。例子可以看这个帖子:
gperf 使用实例
bison:
一个语法分析器生成器。Bison 把一个关于“向前查看 从左到右 最右”(LALR) 上下文无关文法的描述转化成可以分析该文法的 C 或 C++ 程序。它也可以为二义文法生成 “通用的 从左到右 最右” (GLR)语法分析器
flex:
词法分析器
texinfo:
是Linux系统提供的另外一种格式的帮助信息。和man相比,textinfo具有更好交互功能。它支持链接跳转功能,通常使用info和pinfo命令来阅读textinfo文档
help2man:
一个可以自动为我们的程序生成man手册的工具
gawk:
linux下用于查找替换的文本工具
libtool / libtool-bin:
Generic library support script
automake:
Tool for generating GNU Standards-compliant Makefiles
备注:
- 不同的环境需要安装的工具不完全一致,出错时可以根据错误提示来排查
-
各种工具的描述可以使用
apt-cache search XXX
命令去查询
配置全局变量
export PRJROOT=/home/user/tool_prj1 # 修改为自己的工程所在的目录
export TARGET=arm-none-linux-gnueabi
export PREFIX=${PRJROOT}/tool-chain
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=${PREFIX}/bin:${PATH}
export ARCH=arm
export BINUTILS_VERSION=binutils-2.27
export GCC_VERSION=gcc-5.4.0
export GLIBC_VERSION=glibc-2.23
export KERNEL_VERSION=linux-4.4.25
目录结构
$ tree -L 2
tool_prj1
├── build # src的编译目录
├── script # 脚本工具目录
│ ├── toolchain_build.sh # 自己写的自动化编译脚本,后续的命令都集成在了这个脚本中
│ └── toolchain_config.lst # 用于配置全局变量
├── setup # 保存下载的源码包
│ ├── binutils-2.27.tar.bz2
│ ├── gcc-5.4.0.tar.bz2
│ ├── glibc-2.23.tar.bz2
│ └── linux-4.4.25.tar.xz
├── src # 解压后的源码文件
└── tool-chain # 工具链安装位置
源码包下载
cd setup
wget http://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.bz2
wget http://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_VERSION.tar.bz2
wget ftp://ftp.gnu.org/gnu/glibc/$GLIBC_VERSION.tar.bz2
wget https://www.kernel.org/pub/linux/kernel/v4.x/$KERNEL_VERSION.tar.xz
binutils
编译流程
cd src/
tar -jxf ../setup/$BINUTILS_VERSION.tar.bz2
mkdir ../build/$BINUTILS_VERSION
cd ../build/$BINUTILS_VERSION
sh ../../src/$BINUTILS_VERSION/configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-shared
make
make install
选项详解
–target=${TARGET}
编译好的程序能够处理的平台
注:build/host/target是一组相关参数,各项描述如下:
- build 当前编译使用的机器
- host 编译好的程序能够运行的平台
- target 编译好的程序能够处理的平台
比如我们需要在i386机器上为arm开发板编译一个可以处理mips程序的gcc,那么相关参数如下:
- build=i386-linux
- host=arm-linux
- target=mips-linux
–prefix=${RESULT_DIR}
告诉配置脚本当运行 make install 时,把编译好的东西安装在RESULT_DIR目录
–disable-nls
这里nls的意思是本地语言支持(Native Language Support)
–enable-shared
编译出共享链接库
检查编译结果
$ ls ../../tool-chain/bin/
arm-none-linux-gnueabi-addr2line arm-none-linux-gnueabi-c++filt arm-none-linux-gnueabi-ld arm-none-linux-gnueabi-objcopy arm-none-linux-gnueabi-readelf arm-none-linux-gnueabi-strip
arm-none-linux-gnueabi-ar arm-none-linux-gnueabi-elfedit arm-none-linux-gnueabi-ld.bfd arm-none-linux-gnueabi-objdump arm-none-linux-gnueabi-size
arm-none-linux-gnueabi-as arm-none-linux-gnueabi-gprof arm-none-linux-gnueabi-nm arm-none-linux-gnueabi-ranlib arm-none-linux-gnueabi-strings
制作Linux内核头文件
编译流程
cd src
tar -xf ../setup/$KERNEL_VERSION.tar.xz
cd $KERNEL_VERSION
make ARCH=$ARCH CROSS_COMPILE=$TARGET- INSTALL_HDR_PATH=$PREFIX/$TARGET headers_install
这一步是为了导出内核的头文件,后面编译GLIBC时需要
选项详解
ARCH
目标处理器的架构是arm处理器
CROSS_COMPILE
编译程序所用的交叉工具链的名称
INSTALL_HDR_PATH
头文件需要安装的位置
headers_install
make的执行动作为安装头文件
检查结果
$ ls $PREFIX/$TARGET
bin include lib
可以看见
include
文件夹
建立初始化GCC编译器
功能介绍
这一步主要是建立arm-linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要C库支持的程序,后面创建C库也要用到这个编译器。如果只想编译内核和BootLoader,那么安装完这个就可以到此结束
编译流程
cd src
tar -jxf ../setup/$GCC_VERSION.tar.bz2
cd $GCC_VERSION
./contrib/download_prerequisites # 下载mpfr/gmp/mpc/isl
mkdir ../../build/$GCC_VERSION
cd ../../build/$GCC_VERSION
sh ../../src/$GCC_VERSION/configure --target=$TARGET --prefix=$PREFIX --disable-shared --disable-threads --without-headers --disable-libmudflap --enable-languages=c,c++ --disable-nls
make all-gcc
make install-gcc
make all-target-libgcc
make install-target-libgcc
注意:GCC需要四个库
mpfr/gmp/mpc/isl
,当前的GCC可以使用
./contrib/download_prerequisites
脚本直接下载
-
mpfr
-
gmp
-
mpc
-
isl
选项详解
–disable-shared
不使用共享库
–disable-threads
不使用线程功能
–without-headers
不使用目标对象的头文件
–disable-libmudflap
暂时不清楚这个配置是什么意思
–enable-languages=c,c++
支持C/C++语言
其它详细的参数介绍可以参考文档:
gcc/doc/gccinstall.info
检查结果
$ ls tool-chain/bin/arm-none-linux-gnueabi-gcc*
tool-chain/bin/arm-none-linux-gnueabi-gcc tool-chain/bin/arm-none-linux-gnueabi-gcc-ar tool-chain/bin/arm-none-linux-gnueabi-gcc-ranlib
tool-chain/bin/arm-none-linux-gnueabi-gcc-5.4.0 tool-chain/bin/arm-none-linux-gnueabi-gcc-nm
可以看见GCC已经存在
GLibc
编译流程
cd src
tar -jxf ../setup/$GLIBC_VERSION.tar.bz2
mkdir ../build/$GLIBC_VERSION
cd ../build/$GLIBC_VERSION
sh ../../src/$GLIBC_VERSION/configure --host=$TARGET --prefix=$PREFIX/$TARGET --with-tls --disable-profile --enable-add-ons --with-headers=$PREFIX/$TARGET/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes libc_cv_arm_tls=yes --disable-nls
make CC=$TARGET-gcc AR=$TARGET-ar RANLIB=$TARGET-ranlib
make install
选项详解
–with-headers=@var{directory}
Look for kernel header files in @var{directory}
–with-tls
This tells Glibc to use Thread Local Storage
–disable-profile
Don’t build libraries with profiling information
–enable-add-ons
Specify add-on packages to include in the build
libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
libc_cv_arm_tls=yes
不清楚这三个参数的配置意义
其它详细的参数介绍可以参考文档:
manual/install.texi
检查结果
$ ls tool-chain/arm-none-linux-gnueabi/lib
audit libanl-2.23.so libc.a libc.so libm.a libnss_compat-2.23.so libnss_files-2.23.so libnss_nisplus.so.2 libresolv-2.23.so libSegFault.so Scrt1.o
crt1.o libanl.a libcidn-2.23.so libc.so.6 libmcheck.a libnss_compat.so libnss_files.so libnss_nis.so libresolv.a libthread_db-1.0.so
crti.o libanl.so libcidn.so libdl-2.23.so libmemusage.so libnss_compat.so.2 libnss_files.so.2 libnss_nis.so.2 libresolv.so libthread_db.so
crtn.o libanl.so.1 libcidn.so.1 libdl.a libm.so libnss_db-2.23.so libnss_hesiod-2.23.so libpcprofile.so libresolv.so.2 libthread_db.so.1
gconv libBrokenLocale-2.23.so libc_nonshared.a libdl.so libm.so.6 libnss_db.so libnss_hesiod.so libpthread-2.23.so librpcsvc.a libutil-2.23.so
gcrt1.o libBrokenLocale.a libcrypt-2.23.so libdl.so.2 libnsl-2.23.so libnss_db.so.2 libnss_hesiod.so.2 libpthread.a librt-2.23.so libutil.a
ld-2.23.so libBrokenLocale.so libcrypt.a libg.a libnsl.a libnss_dns-2.23.so libnss_nis-2.23.so libpthread_nonshared.a librt.a libutil.so
ld-linux.so.3 libBrokenLocale.so.1 libcrypt.so libieee.a libnsl.so libnss_dns.so libnss_nisplus-2.23.so libpthread.so librt.so libutil.so.1
ldscripts libc-2.23.so libcrypt.so.1 libm-2.23.so libnsl.so.1 libnss_dns.so.2 libnss_nisplus.so libpthread.so.0 librt.so.1 Mcrt1.o
建立完整GCC编译器
编译流程
cd build/$GCC_VERSION
rm -rf * # 删除以前的配置
sh ../../src/$GCC_VERSION/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --enable-shared --disable-nls
make
make install
验证完整编译链
动态编译
$ arm-none-linux-gnueabi-gcc -o hello hello.c
$ arm-none-linux-gnueabi-strip hello
$ file hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.32, stripped
静态编译
$ arm-none-linux-gnueabi-gcc -o hello hello.c -static
$ arm-none-linux-gnueabi-strip hello
$ file hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, stripped