编译工具链制作神器 - crosstool-ng

来源:互联网 发布:java构造方法的重载 编辑:程序博客网 时间:2024/05/18 00:24

From: Linux hole

深呼吸,深呼吸 - XXXX

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、安装crosstool-ng

1.1、获取源码

crosstool-ng版本众多,这里我们选用最新的版本,版本号是1.22.0。

hole@hole-2016:~$ mkdir crosstool-ng-source hole@hole-2016:~$ cd crosstool-ng-sourcehole@hole-2016:~/crosstool-ng-source$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.22.0.tar.bz2
1.2、校检版本签名

此步骤可以跳过

1.3、配置
hole@hole-2016:~/crosstool-ng-source$ tar xvf crosstool-ng-1.22.0.tar.bz2hole@hole-2016:~/crosstool-ng-source$ mkdir crosstool-nghole@hole-2016:~/crosstool-ng-source$ cd crosstool-nghole@hole-2016:~/crosstool-ng-source/crosstool-ng$ ./configure --prefix=/usr/ct-ng/

此处如果不指定–prefix 那么默认目录是/usr/local

1.4、编译 && 安装
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

2、使用croostool-ng 制作工具链子

下面开始制作,我以x86_64 为demo;其它的工具链方法都一样。

2.1、查看已知示例工具链的配置
hole@hole-2016:~/crosstool-ng-source/crosstool-ng$ cd ..hole@hole-2016:~/crosstool-ng-soucrce$ mkdir x86_64-crosshole@hole-2016:~/crosstool-ng-soucrce$ cd x86_64-crosshole@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
2.2、选中一个cross 的配置

这里我们选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
2.3、编译制作工具链
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/.confighole@hole-2016:~/crosstool-ng-soucrce$ cd x86_64-crosshole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng  build

上述操作显然就块了很多。

最后全部完成后,会在当前目录的x86_64-bin 目录下生成我们需要的工具链:

2.4、测试工具链是否可用
hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$/x86_64-bin/bin$ lsx86_64-unknown-linux-gnu-addr2line     x86_64-unknown-linux-gnu-dwp         x86_64-unknown-linux-gnu-gcov       x86_64-unknown-linux-gnu-objcopyx86_64-unknown-linux-gnu-ar            x86_64-unknown-linux-gnu-elfedit     x86_64-unknown-linux-gnu-gcov-tool  x86_64-unknown-linux-gnu-objdumpx86_64-unknown-linux-gnu-as            x86_64-unknown-linux-gnu-g++         x86_64-unknown-linux-gnu-gprof      x86_64-unknown-linux-gnu-populatex86_64-unknown-linux-gnu-c++           x86_64-unknown-linux-gnu-gcc         x86_64-unknown-linux-gnu-ld         x86_64-unknown-linux-gnu-ranlibx86_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-readelfx86_64-unknown-linux-gnu-cc            x86_64-unknown-linux-gnu-gcc-ar      x86_64-unknown-linux-gnu-ld.gold    x86_64-unknown-linux-gnu-sizex86_64-unknown-linux-gnu-cpp           x86_64-unknown-linux-gnu-gcc-nm      x86_64-unknown-linux-gnu-ldd        x86_64-unknown-linux-gnu-stringsx86_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-crossexportPATH=PWD/x86_64-bin/bin:PATHhole@hole2016: /crosstoolngsoucrce/x8664cross x86_64-unkonw-linux-gnu-gcc -v
由于我们使用的是最新的LIB库,所以可能在我们自己的宿主机上编译出来的程序是无法使用;

3、Q & A

我们在做环境的时候经常会大大小小的遇见一些错误,上述我就遇到一个错误;
此错误只有在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$ ./configurehole@hole-2016:~/crosstool-ng-soucrce/crosstool-ng$  make && sudo make install

然后在重复上述制作交叉链子的步骤;

hole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$  ct-ng cleanhole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$  cp ../cross-srs/x86_64-config .confighole@hole-2016:~/crosstool-ng-soucrce/x86_64-cross$ ct-ng  build

好了,问题解决了;

啰嗦一点,在那个宿主机上生成的,就在那个宿主机上进行交叉编译。

* Ps.. *
一个交叉链子就这么容易的被我们制作成功了,那么下一步我们玩什么呢?
上述我们说如果在配合buildroot 或者 pdxditst 那么我们简直分分钟定制一个发行版的Linux 有木有;

说玩就玩,下一节我们就来看看buildroot怎么玩??;


附录Ⅰ - 上述安装所用安装包

源码包地址:戳这儿
密码: axs7

By: Keven - Linux Hole

0 0