歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 交叉工具鏈制作至尊寶典

交叉工具鏈制作至尊寶典

日期:2017/3/1 11:17:52   编辑:Linux編程

一些必須知道的基礎知識

  • Debian 操作系統 以及 aptitude 命令
  • autoconf and automake
  • 什麼是交叉編譯,configure 的幾個參數 build host target

    build:
    編譯代碼的機器,的CPU指令集

    host:
    編譯生成的東西,的CPU指令集(目標板上的CPU的指令集)

    target:
    編譯生成的東西,他編譯生成的的東西,的指令集(所以此選項一般不用,大多只有在做交叉工具鏈時使用)

    0、以Expert mode 安裝Debian

    不要升級,確保環境是一個純淨的環境

    1、聲明環境變量

    1. export IS_TARGET=arm-linux
    2. export DIR_SRC=/root/cross_toolchains/src
    3. export PREFIX=/opt/cross_toolchains/arm
    4. export CONFIGURE_BASE="../configure --prefix=$PREFIX --with-sysroot=$PREFIX"

    2、下載制作交叉工具鏈所必須的的代碼

    1. binutils
    2. ftp://ftp.gnu.org/gnu/binutils/binutils-2.21.tar.gz
    1. gcc
    2. ftp://ftp.gnu.org/gnu/gmp/gmp-5.0.2.tar.gz
    3. ftp://ftp.gnu.org/gnu/mpfr/mpfr-3.0.1.tar.gz
    4. http://www.multiprecision.org/mpc/download/mpc-0.9.tar.gz
    5. ftp://ftp.gnu.org/gnu/gcc/gcc-4.6.1/gcc-4.6.1.tar.gz
    1. glibc
    2. ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.gz
    3. ftp://ftp.gnu.org/gnu/glibc/glibc-ports-2.13.tar.gz
    1. linux kernel
    2. http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.2.tar.bz2

    3、安裝(卸載)必要的的軟件包

    1. aptitude install build-essential automake bison flex texinfo gawk g\+\+
    2. aptitude remove mawk

    4、解壓、歸檔軟件包

    1. cd $DIR_SRC
    2. tar -xf binutils-2.21.tar.gz
    3. tar -xf gmp-5.0.2.tar.gz
    4. tar -xf mpc-0.9.tar.gz
    5. tar -xf mpfr-3.0.1.tar.gz
    6. tar -xf gcc-4.6.1.tar.bz2
    7. tar -xf glibc-2.14.tar.gz
    8. tar -xf glibc-ports-2.13.tar.gz
    9. tar -xf linux-2.6.39.2.tar.bz2
    1. mv gmp-5.0.2 gcc-4.6.1/gmp
    2. mv mpc-0.9 gcc-4.6.1/mpc
    3. mv mpfr-3.0.1 gcc-4.6.1/mpfr
    4. mv glibc-ports-2.13 glibc-2.14/ports

    5、編譯 BINUTILS

    1. cd $DIR_SRC
    2. cd binutils-2.21
    3. mkdir build
    4. cd build
    5. $CONFIGURE_BASE --target=$IS_TARGET --disable-nls --enable-shared --disable-multilib
    1. make configure-host
    2. make
    3. make install
    1. export PATH=$PATH:$PREFIX/bin

    問題:
    編譯binutils一般不會遇到什麼問題,但是,如果前面步驟3中安裝的軟件不全會出現問題

    6、建立用於編譯C庫的GCC

    1. cd $DIR_SRC
    2. cd gcc-4.6.1
    3. mkdir build
    4. cd build
    5. $CONFIGURE_BASE \
    6. --target=$IS_TARGET \
    7. --disable-nls \
    8. --disable-shared \
    9. --without-headers \
    10. --with-newlib \
    11. --enable-languages=c \
    12. --disable-threads \
    13. --disable-multilib \
    14. --disable-decimal-float \
    15. --disable-libgomp \
    16. --disable-libmudflap \
    17. --disable-libssp
    1. make all-gcc all-target-libgcc
    2. make install-gcc install-target-libgcc
    1. 值得注意的幾個configure選項
    2. --target
    3. --disable-shared
    4. --without-headers
    5. --with-newlib
    6. --enable-language-c
    7. --disable-thread
    1. cd $PREFIX/lib/gcc/$IS_TARGET/4.6.1
    2. ln -s libgcc.a libgcc_eh.a
    1. 有建議修改 gcc/config/t-linux 這個文件
    2. 增加 -D__gthr_posix_h -Dinhibit_libc 兩個宏,但我這裡沒這樣做,是因為:
    3. 在configure後,編譯使用的命令並不是 make 或者是 make all 而是 make all-gcc 和 make all-target-libgcc,所以很多問題不會出現
    4. -with-newlib,這個選項不會迫使我們必須使用newlib
    1. libgcc.mvars: No such file or directory
    2. 不能在 GCC 的源代碼目錄進行configure,必須在另外的目錄進行configure make 等工作
    3. 所以這裡在代碼所在目錄下 mkdir build 並 cd build 再進行 ../configure 等工作
    1. configure: error: C compiler cannot create executables
    2. 如果使用 make 或 make all 會出現這樣的問題,因為我們還未編譯出目標指令集的 C 庫
    3. 所以只能先使用 make all-gcc make all-target-libgcc
    1. ../../../../arm-linux/bin/ld: cannot find -lgcc
    2. ../../../../arm-linux/bin/ld: cannot find -lgcc_eh
    3. 很多資料都只寫了 make all-gcc 而沒有寫 make all-target-libgcc 這樣只建立了gcc,沒有建立libgcc.a會出現以上第一個錯誤
    4. 如果沒手工建立鏈接文件 libgcc_eh.a 則會出現第二個錯誤

    7、配置內核生成必要的頭文件

    1. cd $DIR_SRC
    2. cd linux-2.6.39.2
    3. make ARCH=arm CROSS_COMPILE=$IS_TARGET- menuconfig
    4. make ARCH=arm CROSS_COMPILE=$IS_TARGET-
    1. mkdir -p $PREFIX/include
    2. cd $PREFIX/include
    3. ln -s $DIR_SRC/linux-2.6.39.2/arch/arm/include/asm asm
    4. ln -s $DIR_SRC/linux-2.6.39.2/include/linux linux
    5. ln -s $DIR_SRC/linux-2.6.39.2/include/asm-generic asm-generic
    1. 這裡並沒有將內核的頭文件復制到交叉工具鏈的安裝目錄
    2. 編譯C庫的時候,需要對應的CPU指令集的匯編代碼所以做了鏈接處理
    1. 編譯內核在執行 make ARCH=arm CROSS_COMPILE=$IS_TARGET- 時如果出錯,是沒有關系的,這裡只要生成了對應的 version.h autoconf.h就可以了

    8、編譯C庫

    1. cd $DIR_SRC
    2. cd glibc-2.9
    3. mkdir build
    4. cd build
    1. vi ../configure
    2. vi ../ports/sysdeps/unix/sysv/linux/arm/sigrestorer.S
    3. vi ../sysdeps/unix/syscall-template.S
    4. vi ../nptl/allocatestack.c
    5. vi ../elf/dl-tls.c
    6. vi ../sysdeps/ieee754/dbl-64/s_fma.c
    7. vi ../sysdeps/ieee754/dbl-64/s_fmaf.c
    8. 具體的修改,我寫在下面(覺得還是要說清楚為什麼修改,所以就沒用sed命令或是做一些patch文件了,請向下看)
    1. CC=$IS_TARGET-gcc \
    2. $CONFIGURE_BASE \
    3. --host=$IS_TARGET \
    4. -enable-add-ons \
    5. --with-binutils=$PREFIX/bin \
    6. --with-headers=$PREFIX/include \
    7. libc_cv_forced_unwind=yes \
    8. libc_cv_c_cleanup=yes
    1. 值得注意的幾個configure選項
    2. --host
    3. --with-headers
    4. lib_cv_forced_unwind
    5. lib_cv_c_cleanup
    1. make
    2. make install
    1. 這裡編譯的時候並有選擇TARGET為EABI,所以在制作交叉工具鏈時會有很多問題需要修改
    1. *** These critical programs are missing or too old: as ld
    2. *** Check the INSTALL file for required versions.
    3. vi ../configure
    4. 查找 "$AS --version" 將 2.1[3-9] 修改為 2.[1-2][0-9]
    5. 查詢 "$LD --version" 將 2.1[3-9] 修改為 2.[1-2][0-9]
    1. Error: previous CFI entry not closed (missing .cfi_endproc)
    2. vi ../ports/sysdeps/unix/sysv/linux/arm/sigrestorer.S
    3. ENTRY(__default_sa_restorer) 下增加
    4. END(__default_sa_restorer)
    5. ENTRY(__default_rt_sa_restorer) 下增加
    6. END(__default_rt_sa_restorer)
    1. syscall-template.S:82: Error: CFI instruction used without previous .cfi_startproc
    2. vi ../sysdeps/unix/syscall-template.S
    3. 這個問題的修改我也不是十分確定,我是這樣來思考的
    4. 看到 syscall-template.S 中 有 #include <sysdep.h>
    5. 去查看 ports/sysdeps/unix/sysv/linux/arm/sysdep.h
    6. 看到如下代碼
    7. #ifdef __ASSEMBLER__
    8. #undef PSEUDO
    9. #define PSEUDO(name, syscall_name, args) \
    10. .text; \
    11. ENTRY (name); \
    12. DO_CALL (syscall_name, args); \
    13. cmn r0, $4096;
    14. 猜測是__ASSEMBLER__宏未打開,以至於未能找到PSEUD0函數的聲明,則將
    15. #define PSEUDO(name, syscall_name, args) \
    16. .text; \
    17. ENTRY (name); \
    18. DO_CALL (syscall_name, args); \
    19. cmn r0, $4096;
    20. 這段代碼 添加至 ../sysdeps/unix/syscall-template.S 中
    1. LS_DTV_UNALLOCATED undeclared (first use in this function)
    2. vi ../nptl/allocatestack.c
    3. vi ../elf/dl-tls.c
    4. 這個錯誤會出現在編譯以上兩個文件的時候,這個宏的定義我grep了整個glibc的所有代碼,沒找到ARM相關的聲明及定義,按照其他指令集的定義猜測著修改如下
    5. 在以上兩個C文件中增加相應的定義
    6. #define TLS_DTV_UNALLOCATED ((void *) -1l)
    1. E_TOWARDZERO undeclared (first use in this function)
    2. E_INEXACT undeclared (first use in this function)
    3. 以上兩個錯誤會出現在以下兩個文件的的編譯過程中
    4. vi ../sysdeps/ieee754/dbl-64/s_fma.c
    5. vi ../sysdeps/ieee754/dbl-64/s_fmaf.c
    6. 參考 ports/sysdeps/arm/eabi/bits/fenv.h中的定義
    7. 在兩個文件中添加
    8. #define FE_TOWARDZERO 0xc00000
    9. #define FE_INEXACT 16
    1. mawk: scripts/gen-sorted.awk: line 19: regular expression compile failed
    2. 所以要 aptitude install gawk 所以也順帶著 aptitude remove mawk
    1. configure: error: forced unwind support is required
    2. configure 中增加配置參數 libc_cv_forced_unwind=yes
    1. error: the compiler must support C cleanup handlin
    2. configure 中增加配置參數libc_cv_c_cleanup=yes
    1. --enable-add-ons 為 C 庫 增加 thread 支持,目前默認使用的是 nptl 所以這裡沒有去下載 glibc-threads 相關的代碼
    1. --with-headers 指定內核頭文件所在的目錄
  • Copyright © Linux教程網 All Rights Reserved