From: Linux hole
Hello,大家好。
最近一直忙着调试Bug,一直无果。很让人伤心,多模块糅合,Ps. 驱动 用户态 硬件全方位定位,搞的人很累。所以一直没有写点东西;
以前我一直以为要写东西就必须写的高大上的东东,后来才发现,高大上的东东搞起来除了很费力以外,反而可能让人觉得你不也是COPY过来的吗?你不是也是TS过来的吗? 拽什么拽啦。。
鉴于此,我决定写点通俗易懂,能引来吃西瓜观众的tech文章。
始于此吧,今天我们来讲一下怎么制作自己的交叉链子。
做嵌入式开发的小伙伴可能对“交叉工具链子”这个词很敏感,可能是一道面试题啊(也许会和编译原题一来聊出来)。那么究竟什么是交叉工具链子呢?工具链子是软件开发项目中的一个重要组成部分,其会将正在开发的代码进行编译、汇编和链接。一些工具链中的碎片将最终在生成的二进制:譬如静态库。简而言之就是可以在宿主机上,编译生成可在目标机上的运行的,可执行程序的编译器统称(集编译,链接,汇编,调试,反汇编等等)。所以呢,工具链子本身是一个非常敏感的工具。
在实际开发中,很多人可能都没有遇见过让自己去做一个链子的情况,毕竟链子基本上都是现成的,编译脚本也是现成的,配置也是现成的。就算要做,网上也有一些零零散散的制作过程,那么我为什么还要写这么制作文章呢? 岂不是显得脱裤子放屁;以上已知存在的制作链子的方法有以下几点限制:
- 1、虽然这些链子可以通用,但是由于配置文件一致,它不能为您优化某些特定场景,
- 2、它们可以编写一个特定的目标,
- 3、它们可能使用的是比较老的组件(C 库,配置等等),无法支持较新CPU的特性;
但是呢,这些链子还是有一些好处:
- 1、已经准备好,方便配置和使用,
- 2、既然能被广泛使用,也说明它们的稳定性;
但是如果你想把你的程序运行在指定的硬件上,那么你最起码要学会如何制作工具链;
有很多种方法可以做链子,这里我推荐一个制作交叉链子神器 - crosstool-ng
ct-ng 告别了过去制作交叉链子复杂的过程,把制作交叉链子做成了一套自动化部署工具,没有门槛,想怎么改就怎么改。
如果在配合buildroot 或者 ptxdist,简直分分钟做出一套属于自己的Linux Embedded 发行版呀有木有。
咳咳,制造发行版的这个事情我们后面在来care,下面我们来看看怎么利用神器制作自己的交叉链子。
crosstool-ng版本众多,这里我们选用最新的版本,版本号是1.22.0。
hole@hole-2016:~$ mkdir crosstool-ng-source
hole@hole-2016:~$ cd crosstool-ng-source
hole@hole-2016:~/crosstool-ng-source$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2
此步骤可以跳过
hole@hole-2016:~/crosstool-ng-source$ tar xvf crosstool-ng-1.22.0.tar.bz2
hole@hole-2016:~/crosstool-ng-source$ mkdir crosstool-ng
hole@hole-2016:~/crosstool-ng-source$ cd crosstool-ng
hole@hole-2016:~/crosstool-ng-source/crosstool-ng$ ./configure --prefix=/usr/ct-ng/
此处如果不指定–prefix 那么默认目录是/usr/local
hole@hole-2016:~/crosstool-ng-source/crosstool-ng$ make && sudo make install
上述如果指定了–prefix,记得添加到环境变量
hole@hole-2016:~/crosstool-ng-source/crosstool-ng$ export PATH=/usr/ct-ng/bin:$PATH
下面开始制作,我以x86_64 为demo;其它的工具链方法都一样。
hole@hole-2016:~/crosstool-ng-source/crosstool-ng$ cd ..
hole@hole-2016:~/crosstool-ng-soucrce$ mkdir x86_64-cross
hole@hole-2016:~/crosstool-ng-soucrce$ cd x86_64-cross
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng list-samples
然后就会列出下面推荐的已知工具链的名称:
Status Sample name
[G..] alphaev56-unknown-linux-gnu
[G..] alphaev67-unknown-linux-gnu
[G..] arm-bare_newlib_cortex_m3_nommu-eabi
[G..] arm-cortex_a15-linux-gnueabi
[G..] arm-cortex_a8-linux-gnueabi
[G.X] arm-cortexa5-linux-uclibcgnueabihf
[G.X] arm-cortexa9_neon-linux-gnueabihf
[G..] arm-unknown-eabi
[G..] arm-unknown-linux-gnueabi
[G.X] arm-unknown-linux-musleabi
[G..] arm-unknown-linux-uclibcgnueabi
[G.X] arm-unknown-linux-uclibcgnueabihf
[G..] armeb-unknown-eabi
[G..] armeb-unknown-linux-gnueabi
[G..] armeb-unknown-linux-uclibcgnueabi
[G..] armv6-rpi-linux-gnueabi
[G..] armv7-rpi2-linux-gnueabihf
[G..] avr
[G..] i586-geode-linux-uclibc
[G..] i586-mingw32msvc,i686-none-linux-gnu
[G..] i686-nptl-linux-gnu
[G.X] i686-w64-mingw32
[G..] m68k-unknown-elf
[G..] m68k-unknown-uclinux-uclibc
[G..] mips-ar2315-linux-gnu
[G..] mips-malta-linux-gnu
[G..] mips-unknown-elf
[G..] mips-unknown-linux-uclibc
[G..] mips64el-n32-linux-uclibc
[G..] mips64el-n64-linux-uclibc
[G..] mipsel-sde-elf
[G..] mipsel-unknown-linux-gnu
[G.X] i686-w64-mingw32,nios2-spico-elf
[G..] powerpc-405-linux-gnu
[G..] powerpc-860-linux-gnu
[G..] powerpc-e300c3-linux-gnu
[G..] powerpc-e500v2-linux-gnuspe
[G..] powerpc-unknown-linux-gnu
[G..] powerpc-unknown-linux-uclibc
[G..] powerpc-unknown_nofpu-linux-gnu
[G..] powerpc64-unknown-linux-gnu
[G.X] s390-ibm-linux-gnu
[G..] s390x-ibm-linux-gnu
[G..] sh4-unknown-linux-gnu
[G..] sparc-unknown-linux-gnu
[G.X] x86_64-w64-mingw32,x86_64-pc-linux-gnu
[G..] x86_64-unknown-linux-gnu
[G..] x86_64-unknown-linux-uclibc
[G.X] x86_64-w64-mingw32
[G..] xtensa-unknown-linux-uclibc
L (Local) : sample was found in current directory
G (Global) : sample was installed with crosstool-NG
X (EXPERIMENTAL): sample may use EXPERIMENTAL features
B (BROKEN) : sample is currently broken
这里我们选x86_64-unknown-linux-gnu 的吧。
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng show-x86_64-unknown-linux-gnu
会显示此工具链子的一些库信息:
[G..] x86_64-unknown-linux-gnu
OS : linux-4.3
Companion libs : gmp-6.0.0a mpfr-3.1.3 mpc-1.0.3 expat-2.1.0 ncurses-6.0
binutils : binutils-2.25.1
C compilers : gcc | 5.2.0
Languages : C,C++
C library : glibc-2.22 (threads: nptl)
Tools : gdb-7.10
下面让我们生成配置文件
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng x86_64-unknown-linux-gnu
这样子会在目录下生成.config 文件。
我们可以和配置内核代码一样对此配置进行修改
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng menuconfig
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng build
这个过程时间比较长(取决于您的网速),因为还要下载相应的源码包。
为了节省时间,我这里提供源码包以及配置文件,具体链接在后面的附录中,只需要将源码包放在您的工作区即可。
hole@hole-2016:~/crosstool-ng-soucrce$ cp -rf cross-src/src x86_64-cross/
hole@hole-2016:~/crosstool-ng-soucrce$ cp cross-src/x86_64-config x86_64-cross/.config
hole@hole-2016:~/crosstool-ng-soucrce$ cd x86_64-cross
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng build
上述操作显然就块了很多。
最后全部完成后,会在当前目录的x86_64-bin 目录下生成我们需要的工具链:
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$/x86_64-bin/bin$ ls
x86_64-unknown-linux-gnu-addr2line x86_64-unknown-linux-gnu-dwp x86_64-unknown-linux-gnu-gcov x86_64-unknown-linux-gnu-objcopy
x86_64-unknown-linux-gnu-ar x86_64-unknown-linux-gnu-elfedit x86_64-unknown-linux-gnu-gcov-tool x86_64-unknown-linux-gnu-objdump
x86_64-unknown-linux-gnu-as x86_64-unknown-linux-gnu-g++ x86_64-unknown-linux-gnu-gprof x86_64-unknown-linux-gnu-populate
x86_64-unknown-linux-gnu-c++ x86_64-unknown-linux-gnu-gcc x86_64-unknown-linux-gnu-ld x86_64-unknown-linux-gnu-ranlib
x86_64-unknown-linux-gnu-c++filt x86_64-unknown-linux-gnu-gcc-5.2.0 x86_64-unknown-linux-gnu-ld.bfd x86_64-unknown-linux-gnu-readelf
x86_64-unknown-linux-gnu-cc x86_64-unknown-linux-gnu-gcc-ar x86_64-unknown-linux-gnu-ld.gold x86_64-unknown-linux-gnu-size
x86_64-unknown-linux-gnu-cpp x86_64-unknown-linux-gnu-gcc-nm x86_64-unknown-linux-gnu-ldd x86_64-unknown-linux-gnu-strings
x86_64-unknown-linux-gnu-ct-ng.config x86_64-unknown-linux-gnu-gcc-ranlib x86_64-unknown-linux-gnu-nm x86_64-unknown-linux-gnu-strip
简单测试一下是否可用;
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross
exportPATH=
PWD/x86_64-bin/bin:
PATHhole@hole−2016: /crosstool−ng−soucrce/x8664−cross
x86_64-unkonw-linux-gnu-gcc -v
由于我们使用的是最新的LIB库,所以可能在我们自己的宿主机上编译出来的程序是无法使用;
我们在做环境的时候经常会大大小小的遇见一些错误,上述我就遇到一个错误;
此错误只有在32位的环境上编译64位链子的时候才会产生。
1、错误信息
[INFO ] Installing GMP for host
[EXTRA] Configuring GMP
[ERROR] configure: error: Oops, mp_limb_t is 32 bits, but the assembler code
[ERROR]
[ERROR] >>
[ERROR] >> Build failed in step 'Installing GMP for host'
[ERROR] >> called in step '(top-level)'
[ERROR] >>
[ERROR] >> Error happened in: CT_DoExecLog[scripts/functions@257]
[ERROR] >> called from: do_gmp_backend[scripts/build/companion_libs/100-gmp.sh@92]
[ERROR] >> called from: do_gmp_for_host[scripts/build/companion_libs/100-gmp.sh@62]
[ERROR] >> called from: do_companion_libs_for_host[scripts/build/companion_libs.sh@36]
[ERROR] >> called from: main[scripts/crosstool-NG.sh@646]
[ERROR] >>
[ERROR] >> For more info on this error, look at the file: 'build.log'
[ERROR] >> There is a list of known issues, some with workarounds, in:
[ERROR] >> '/usr/local/share/doc/crosstool-ng/crosstool-ng-1.22.0/B - Known issues.txt'
[ERROR]
[ERROR] (elapsed: 1:51.70)
[01:52] / /usr/local/bin/ct-ng:152: recipe for target 'build' failed
根据提示我们发现是在安装GMP这个包的时候报错,提示信息也很明确;我首先就想到是GMP这个包的配置步骤有BUG,寻找一下最开始我们安装crosstool-ng的目录有没有关于gmp相关的信息;
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ cd ../crosstool-ng
hole@hole-2016:~/crosstool-ng-soucrce/crosstool-ng$ find -name *gmp*
./config/companion_libs/gmp.in
./scripts/build/companion_libs/100-gmp.sh
./patches/ppl/0.11.2/200-fix-build-with-local-gmp.patch
./patches/ppl/0.11.2/400-fix-build-with-gmp-5.1.patch
./patches/ppl/0.10.2/200-fix-build-with-local-gmp.patch
./patches/ppl/0.10.2/100-fix-configure-with-gmp-5_0_1.patch
./patches/ppl/0.11.1/200-fix-build-with-local-gmp.patch
./patches/ppl/0.11/200-fix-build-with-local-gmp.patch
./patches/gmp
上述和build 以及配置相关只有
./scripts/build/companion_libs/100-gmp.sh
根据此脚本我们锁定了gmp 文件夹目录
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross/.build/src/gmp-6.0.0a
根据提示我们修改了GMP 的配置选项
添加一个配置选项到 ./scripts/build/companion_libs/100-gmp.sh
--disable-assembly
让我们在重复上述安装crosstool-ng的步骤,
hole@hole-2016:~/crosstool-ng-soucrce/crosstool-ng$ make distclean
hole@hole-2016:~/crosstool-ng-soucrce/crosstool-ng$ ./configure
hole@hole-2016:~/crosstool-ng-soucrce/crosstool-ng$ make && sudo make install
然后在重复上述制作交叉链子的步骤;
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng clean
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ cp ../cross-srs/x86_64-config .config
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng build
好了,问题解决了;
啰嗦一点,在那个宿主机上生成的,就在那个宿主机上进行交叉编译。
* Ps.. *
一个交叉链子就这么容易的被我们制作成功了,那么下一步我们玩什么呢?
上述我们说如果在配合buildroot 或者 pdxditst 那么我们简直分分钟定制一个发行版的Linux 有木有;
说玩就玩,下一节我们就来看看buildroot怎么玩??;
附录Ⅰ - 上述安装所用安装包
源码包地址:戳这儿
密码: axs7