工具链技术分析与实现
GNU工具链(下面简称 工具链)是一个包含了由GNU项目所产生的各种编程工具的集合。这些工具形成了一条工具链,用于开发应用程序和操作系 统。GNU工具链在针对LFS、嵌入式系统的Linux内核、BSD及其它软件的开发中起着至关重要的作用。
在LFS中,工具链是整个过程的核心,可以说,没有做好工具链就一定做不成一个完整的系统。工具链在这里是研究的主题,你可以通过认识工具链来深刻了解到Linux系统内部的依赖关系,从而对以后构建一个完整的Linux系统掌握的游刃有余。下面我们来逐步了解工具链的各个细节。
概览
1、工具链的组成结构
2、工具链的使用方式
3、工具链的制作方式
4、制作工具操作系统
5、总结工具链的特点
第一、工具链的组成结构
GNU工具链的组件有:
- GNU make:用于编译和构建的自动工具;
- GNU编译器集(GCC):一组多种编程语言的编译器;
- GNU Binutils:包含链接器、汇编器和其它工具的工具集;
- GNU调试工具(GDB):代码调试工具;
- GNU自动化生成工具(autotools):自动化检查软件编译过程的工具。
前面简单介绍了工具链的相关概念与结构,为了对工具链实施完整的分析,本文选取LFS的工具链来说明工具链体系内的软件包组成及依赖关系。
所需的软件包有:
- Binutils:
- 包含的程序:addr2line,ar,as,c++filt,elfedit,gprof,ld,ld.bfd,nm,objcopy,objdump,ranlib,readelf,size,strings 和 strip
- 包含的库:libiberty,libbfd 和 libopcodes
- GCC:
- 包含的程序:c++,cc(到 gcc 的链接),cpp,g++,gcc,gcc-ar,gcc-nm,gcc-ranlib,gccbug 和 gcov
- 包含的库:libgcc,libgcov,libgomp,liblto_plugin,libmudflap,libquadmath,libssp,libstdc++,libsupc++
- 依赖的包:gmp,mpfr,mpc
- Linux API Headers:(这个是可选包,如果是为了做一个通用工具链,必须将其换成相应平台的头文件包)
- 包含的头文件:/usr/include/asm/*.h,/usr/include/asm-generic/*.h,/usr/include/drm/*.h,/usr/include/linux/*.h,/usr/include/mtd/*.h,/usr/include/rdma/*.h,/usr/include/scsi/*.h,
/usr/include/sound/*.h,/usr/include/video/*.h,/usr/include/xen/*.h
- 包含的头文件:/usr/include/asm/*.h,/usr/include/asm-generic/*.h,/usr/include/drm/*.h,/usr/include/linux/*.h,/usr/include/mtd/*.h,/usr/include/rdma/*.h,/usr/include/scsi/*.h,
- Glibc:(可以根据标准LFS系统的制作方法来安装Glic,这是个很有用的建议)
- 包含的程序:catchsegv,gencat,getconf,getent,iconv,iconvconfig,ldconfig,ldd,lddlibc4,locale, localedef,makedb,mtrace,nscd,pcprofiledump,pldd,pt_chown,rpcgen, sln, sotruss, sprof, tzselect, xtrace, zdump 和 zic
- 包含的库:ld.so,libBrokenLocale,libSegFault,libanl,libbsd-compat,libc,libcidn,libcrypt,libdl,libg,libieee,libm,libmcheck,libmemusage,libnsl,
libnss,libpcprofile,libpthread,libresolv,librpcsvc,librt,libthread_db,libutil
以下属于工具环境所要用到的包,与工具链无关。
- Ncurses:(与命令行相关的程序都会用到libncurses库)
- 包含的程序:captoinfo(到 tic 的链接), clear, infocmp, infotocap (到 tic 的链接), ncursesw5-config, reset (到 tset 的链接), tabs, tic, toe, tput 和 tset
- 包含的库:libcurses,libncurses,libform,libmenu,libpanel
- Bash:(bash是从宿主环境切换到工具环境要用到的,处理方式在制作过程中有相关阐述)
- 包含的程序:bash,bashbug 和 sh (到 bash 的链接)
- Coreutils:(Coreutils 程序包包含用于显示和设置基本系统属性的工具,属于工具环境的主要部分)
- 包含的程序:base64, basename, cat, chcon, chgrp, chmod, chown, chroot, cksum, comm, cp, csplit, cut, date, dd, df, dir, dircolors, dirname, du, echo, env, expand, expr, factor, false, fmt, fold, groups, head, hostid, id, install, join, link, ln, logname, ls, md5sum, mkdir, mkfifo, mknod, mktemp, mv, nice, nl, nohup, nproc, od, paste, pathchk, pinky, pr, printenv, printf, ptx, pwd, readlink, realpath, rm, rmdir, runcon, seq, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, shred, shuf, sleep, sort, split, stat, stdbuf, stty, sum, sync, tac, tail, tee, test, timeout, touch, tr, true, truncate, tsort, tty, uname, unexpand, uniq, unlink, users, vdir, wc, who, whoami 和 yes
- 包含的库:libstdbuf.so
- Diffutils:
- 包含的程序:cmp, diff, diff3 和 sdiff
- File:
- 包含的程序:file
- 包含的库:libmagic
- Findutils:
- 包含的程序:bigram, code, find, frcode, locate, oldfind, updatedb 和 xargs
- Gawk:
- 包含的程序:awk (到 gawk 的链接), dgawk, gawk, gawk-4.0.1, grcat, igawk, pgawk, pgawk-4.0.1 和 pwcat
- Gettext:(按照LFS手册的观点,工具环境中并不需要这个软件包太多的程序,事实上可以依据制作标准LFS系统的方法来安装)
- 包含的程序:autopoint, config.charset, config.rpath, envsubst, gettext, gettext.sh, gettextize, hostname, msgattrib, msgcat, msgcmp, msgcomm, msgconv, msgen, msgexec, msgfilter, msgfmt, msggrep, msginit, msgmerge, msgunfmt, msguniq, ngettext, recode-sr-latin 和 xgettext
- 包含的库:libasprintf,libgettextlib,libgettextpo,libgettextsrc,preloadable_libintl
- Grep:
- 包含的程序:egrep、fgrep 和 grep
- M4:
- 包含的程序:m4
- Make:
- 包含的程序:make
- Patch:
- 包含的程序:patch
- Perl:(FreeBSD系统中并不附带perl,可见perl并不是系统必须的部分,但是工具环境在编译某些包时需要用perl编译perl相关的模块)
- 包含的程序:a2p, c2ph, config_data, corelist, cpan, cpan2dist, cpanp cpanp-run-perl, enc2xs, find2perl, h2ph, h2xs instmodsh, json_pp, libnetcfg, perl, perl5.16.2 (到 perl 的链接), perlbug, perldoc, perlivp, perlthanks (到 perlbug 的链接), piconv, pl2pm, pod2html, pod2latex, pod2man, pod2text, pod2usage, podchecker, podselect, prove, psed (到 s2p 的链接), pstruct (到 c2ph 的链接), ptar, ptardiff, ptargrep, s2p, shasum, splain, xsubpp 和 zipdetails
- Sed:
- 包含的程序:sed
- Textinfo:
- 包含的程序:info、infokey、install-info、makeinfo、pdftexi2dvi、texi2dvi、texi2pdf 和 texindex
- Tar、Gzip、Bzip2、Xz:(LFS手册很像是按照字母顺序来编译的,没有发现顺序要求,推荐tar最后安装)
- 各自包含的程序:Tar { rmt,tar },Bzip2 { bunzip2 (到 bzip2 的链接),bzcat (到 bzip2 的链接),bzcmp (到 bzdiff 的链接),bzdiff,bzegrep (到 bzgrep 的链接),bzfgrep (到 bzgrep 的链接),bzgrep,bzip2,bzip2recover,bzless (到 bzmore 的链接) 和 bzmore },Gzip { gunzip, gzexe, gzip, uncompress, zcat, zcmp, zdiff, zegrep, zfgrep, zforce, zgrep, zless, zmore, and znew },Xz { lzcat (到 xz 的链接)、lzcmp (到 xzdiff 的链接)、lzdiff (到 xzdiff 的链接)、lzegrep (到 xzgrep 的链接)、lzfgrep (到 xzgrep 的链接)、lzgrep (到 xzgrep 的链接)、lzless (到
xzless 的链接)、lzma (到 xz 的链接)、lzmadec、lzmainfo、lzmore (到 xzmore 的链接)、unlzma (到 xz 的链接)、unxz (到 xz 的链接)、xz、xzcat (到 xz 的链接)、xzcmp (到 xzdiff 的链接)、xzdec、xzdiff、xzegrep (到 xzgrep 的链接)、xzfgrep (到 xzgrep 的链接)、xzgrep、xzless、xzmore } - 各自包含的库:Bzip2(libbz2*),Xz(liblzma*)
- 各自包含的程序:Tar { rmt,tar },Bzip2 { bunzip2 (到 bzip2 的链接),bzcat (到 bzip2 的链接),bzcmp (到 bzdiff 的链接),bzdiff,bzegrep (到 bzgrep 的链接),bzfgrep (到 bzgrep 的链接),bzgrep,bzip2,bzip2recover,bzless (到 bzmore 的链接) 和 bzmore },Gzip { gunzip, gzexe, gzip, uncompress, zcat, zcmp, zdiff, zegrep, zfgrep, zforce, zgrep, zless, zmore, and znew },Xz { lzcat (到 xz 的链接)、lzcmp (到 xzdiff 的链接)、lzdiff (到 xzdiff 的链接)、lzegrep (到 xzgrep 的链接)、lzfgrep (到 xzgrep 的链接)、lzgrep (到 xzgrep 的链接)、lzless (到
第二、工具链的使用方式
工具链的目的是提供一个临时可用的编译工作环境,通过chroot来完成在工具环境中进行开发、编译、制作工作。为了制作出干净、可移植的工具环境,建议创建一个专用于制作工具链的用户,这也是LFS推荐的。本文并不仅限于LFS的工具链的使用,仅以此为范例,如果你所使用的发行版有完整的工具链环境,你就不需要下面的代码了,只需要按照软件编译方法去做即可。
在使用工具链之前,你的身份应该是root,首先挂载虚拟文件系统,然后进入到chroot环境中。下面提供了LFS的脚本示例可以使过程更加简便。
挂载虚拟文件系统
#!/bin/bash mount -o bind /dev $LFS/dev mount -t devpts devpts $LFS/dev/pts -o gid=5,mode=620 mount -t proc proc $LFS/proc mount -t sysfs sysfs $LFS/sys if [ -h $LFS/dev/shm ]; then link=$(readlink $LFS/dev/shm) mkdir -p $LFS/$link mount -t tmpfs shm $LFS/$link unset link else mount -t tmpfs shm $LFS/dev/shm fi
进入到Chroot环境
#!/bin/bash chroot "$LFS" /tools/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='\u:\w\$ ' \ PATH=/tools/bin:/tools/sbin:/bin:/usr/bin:/sbin:/usr/sbin \ /tools/bin/bash --login +h
将以上代码保存为相应的Shell脚本文件,添加执行权限即可使用,使用顺序是先挂载虚拟文件系统、后进入chroot环境。上述代码只适用于LFS的构建,可根据需求做适当的变量替换,原理和步骤是相同的。
在进入工具环境后,可供使用的命令在第一节已经给出了。解压软件包源码后,应该创建一个build目录,保持源码目录的干净,在出现问题后可以直接在build目录中分析而不至于破坏源代码。