交叉编译详解 二 从零制作交叉编译链

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengfei240/article/details/52917018

编译环境

主机硬件环境:

    $ 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

猜你喜欢

转载自blog.csdn.net/pengfei240/article/details/52917018