You are here

Magic Linux开发入门指南(一)

Primary tabs

制作一个Linux发布难吗?
很难。
制作一个Linux发布版需要很高深的技术吗?
你能行。

好多人很想参与Magic Linux的开发,但多数不知从何入手。
其实很简单,你只需要一台供你支配的386以上配置且能够上网的电脑,
以及一个能够工作在其上的gcc环境。
对,这就够了,其他的软件都是在帮助你更快的、更简便的完成这个工
作。因为Linux源自于网络,发展于网络,能够上网才能得到Linux;Linux
自身及在其之上运行的大多数软件都是以源代码方式提供,且非gcc不能完成
内核的编译。拥有了这些,你就可以开始将这些源代码转化为可运行的内核、
Shell和一些应用软件,一点一点的就构成了一个完整的可用的Linux系统。
本文就是讲述如何开始这些工作的。我会假定你对Linux有一定的了解,
使用过如:cp、mv、rm等常用命令,曾经成功的在某个Linux系统中安装过某个
以源代码形式发布的软件,有一些C/C++或其他语言的经验。
另外,我说提到的gcc环境并不是单指gcc本身,而是一些了与gcc相交织
的软件集合,它们共同工作,完成从源代码到可执行程序的转换过程,这个过
程一般被称之为创建。

第一章 工具链的制作

在正式开始前,我还要让你了解一个重要的知识,那就是编译器、连接器
和程序库他们三者之间的关系,如果你已经非常了解了,可以略过这些内容。
编译器只是将源代码翻译成对应的机器代码,但是这个时候这些代码是不能执
行的,因为既没有排列好执行顺序也没有指定从哪里开始;程序库实现了一些
程序必要的行为,比如你要输出一些内容到屏幕或从键盘获得输入等;连接器
将编译器产生的机器代码进行排序并告诉计算机(严格来讲是操作系统)从什么
地方开始执行,当程序需要输出一些内容到屏幕或从键盘获得输入时,请求程
序库完成这些事情。虽然这些说法显得很不专业,但是足以帮助你理解它们三
者之间的关系了。如果要获得更为专业、详细的知识请阅读相关专业书籍。
一个能够正常工作的gcc环境,需要三个源代码包的支持:binutils、
gcc和glibc,它们分别提供了连接器、编译器和程序库。其实他们并不仅仅提
供了这些内容:
binutils是一个二进制工具集合,包含了汇编器、反汇编器、连接器、
elf可执行文件分析器等重要工具,这些工具在进行Linux各种应用的开发时,
发挥着巨大的作用。你可以在/usr/bin目录中找到他们。
gcc是一个编译器集合,包含了C、C++、Objective-C、Fortran、Java
和Ada语言,同时为这些语言提供了一些标准库,如:libstdc++、libgcj,
……。 gcc的C是Linux的标准编译器,linux内核完全依赖于gcc,其他编译
器不能编译linux内核。由于ABI(Application Binary Interface)的不兼
容,其他编译器也不适合Linux上的大多数软件的编译,尤其那些使用C++作为
开发语言的软件系统。目前Intel C/C++编译器开始兼容gcc的ABI,因此现在
可以采用Intel C/C++编译器创建Linux上使用C/C++开发的软件系统,但内核
不行。gcc被安装在/usr/bin、/usr/lib和/usr/include目录中。
glibc是提供系统调用和基本函数的C库,比如open,malloc,printf等
等,所有动态连接的程序都要用到它。它是用户程序与内核交流的标准接口。
这三个包在一起相互作用,来完成Linux的所有创建任务。除了glibc是自
包含(自己依赖于自己)的外,其他两个都要依赖于glibc,同时glibc会与具体
的内核版本有一定的依赖性,但这并不是绝对的。注意,他们都是用gcc编译,
并用binutils的连接器进行连接的。这里就比较有趣了,是先有鸡还是先有蛋
呢?计算机的发展史咱们就不必讨论了,在本章会详细介绍如何来让他们的代码
执行起来。但他们不是我们要的全部。

首先,你应该保证你有可用的gcc环境,能够用它让你的源代码变成可执行
程序。往往这需要你的计算机运行了某个版本的Linux发布。当然Windows也行,
不过会比较麻烦,我不建议你这么做,我也不会在这里讨论该怎么做。你也不要
指望你现在的这个gcc环境可以直接创建Magic Linux的所有,最后你得到的还
是属于你现在使用的这个发布。因为你现在的gcc创建产生后的程序,还是依赖
于你现有Linux发布版的glibc的。如果你说你现在就创建一个glibc不就行了
吗?不信你可以试试,当你安装完后,看看你的系统还能工作不?言归正传,你
现在急需的是能够帮助你产生MagicLinux的gcc。

1.准备环境
最好能在你的硬盘上划分出一个独立的分区,1G大小就够了。不过这个你都
嫌麻烦的话,你有1G以上的自由空间也行。现在我假设你划分了一个独立的分区。
来吧,创建/mnt/ml目录,并将你的新分区挂接到这上面(如果不了解挂接的
话,先找找资料,google一下mount)。

#mkdir /mnt/ml
#mount /dev/hda6 /mnt/ml (我假设你得心分区设备名为hda6)

cd到/mnt/ml目录并创建toolchain目录。

#cd /mnt/ml
#mkdir toolchain

在你的根目录创建一个连接到toolchain上(如果不了解,google一下ln)。

#ln -sv /mnt/ml/toolchain /toolchain

创建sources目录。

#mkdir sources

将binutils、gcc和glibc等的源代码复制到sources目录中。你可以在网络上找
到它们,google一下就行了。binutils的最新本版是2.18,源代码包可能是这样
的文件名:binutils-2.18.tar.bz2;gcc的最新本版是4.2.2,源代码包可能是
这样的文件名:gcc-4.2.2.tar.bz2;glibc的最新版本是2.7,源代码包可能是
这样的文件名:glibc-2.7.tar.bz2。
修改PATH环境变量。

#export PATH=/toolchain/bin:$PATH

PATH环境变量指定了shell命令的默认搜索路径。我们修改PATH环境变量使得在你
的gcc可用时,默认执行的是它,而不是系统自带的。
环境已经准备好了,我们开始吧。

2.创建新的gcc环境
为了创建完全独立于你现有系统的gcc环境,我们要创建两次binutils和gcc。
他们创建的次序是很重要的。我们现在进行第一次创建。进入sources目录。

#cd sources

2.1创建binutils
首先创建binutils,是因为在创建gcc和glibc时,它们会检测连接器和汇编器,
以便决定它们能够开启那些特性。整个过程大概需要5分钟(根据你机器的处理能力会
有很大的不同),占用200MB左右的磁盘空间。
解压缩源代码包,并进入解压后的目录:

#tar -jvxf binutils-2.18.tar.gz
#cd binutils-2.18

由于binutils在某些时候会有一点小问题,要修复它,需要下在一个补丁,对应2.18
版本的补丁是:binutils-2.18-configure-1.patch。

#patch –Np1 -i ../binutils-2.18-configure-1.patch

binutils的文档说应该在一个独立的目录中创建binutils。那就创建一个build目录。

#mkdir build
#cd build

现在为创建binutils做准备工作:

#CC=”gcc -B/usr/bin/”../configure \
--prefix=/toolchain --disable-nls --disable-werror

各选项的含义是:
CC=”gcc -B/usr/bin/”
告诉gcc使用你当前操作系统/usr/bin目录下的连接器。这个对于某些你使用的Linux
发布是很重要的,因为新创建的连接器ld可能与它所提供的gcc不兼容。
--prefix=/toolchain
这个参数告诉configure脚本,把binutils软件包中的程序安装到/toolchina目
录中,也就是
/mnt/ml/toolchain。
--disable-nls
这个参数禁止了国际化(通常简称i18n)。此时根本不需要国际化支持。
--disable-werror
这个参数可以防止由于你的系统提供的gcc在产生警告事件时停止创建过程。
准备好了,我们可以创建了:

#make

创建完成后,安装:

#make install

别着急,还没完事。还得调整一下:

#make –C ld clean
#make –C ld LIB_PATH=/toolchain/lib

make参数的含义是:
-C ld clean
告诉make,删除所有子目录ld中编译生成的文件。
-C ld LIB_PATH=/toolchain/lib
这个选项重新编译ld子目录中的所有文件。LIB_PATH是Makefile的一个变量,
在命令行里制定他,可以覆盖默认值,并让它指向/toolchain/lib目录。这个变
量的值指定了连接器的缺省库搜索路径。
手工将新的程序复制到/toolchain/bin目录:

#cp –v ld/ld-new /toolchain/bin

好了,binutils创建完成了,你现在可以删除build目录了。但是不要删除
binutils-2.18目录,因为还要编译一次呢。退回到sources目录,准备gcc的创建工
作。

#cd ../
#rm –rf build
#cd ../

2.2 创建gcc
连接器准备好了,但我们这次先不使用它,没有这个必要,因为我们还需要再次
创建gcc的,那时再用也不迟。这个过程大概会花费你50分钟的时间和650MB的磁盘空
间。
解压缩gcc的源代码包并进入源代码目录。

#tar –jvxf gcc-4.2.2.tar.bz2
#cd gcc-4.2.2

gcc与binutils一样,建议你在一个独立的目录中创建它。创建build目录。

#mkdir build
#cd build

为创建gcc做准备。

#../configure –prefix=/toolchain –with-local-prefix=/toolchain \
--disable-nls –enable-shared –enable-languages=c

各选项的含义是:
CC=”gcc -B/usr/bin/”
告诉gcc使用你当前操作系统/usr/bin目录下的连接器。也就是不使用你刚创建完
的那个连接器ld。这也是为了避免一些麻烦,可以参考创建binutils时对该选项的
说明。
--with-local-prefix=/toolchain
默认情况下,gcc会搜索两个include目录,一个是其安装目录下的include,这里是
/toolchian/include,另外一个是/usr/local/include。这个选项就是将
/usr/local/include这个默认搜索目录删除,而还是指向/toolchain/include。
--enable-shared
这个选项是为了创建出libgcc_s.so.1和libgcc_eh.a文件,因为下一个要创建的
glibc需要libgcc_eh.a,要是没有它就不会产生正确的结果。
--enable-languages=c
因为gcc是一个编译器集合,这个选项指定要创建何种语言的编译器。此时只需要C,
那就没什么可说的了。
准备好了,我们可以开始创建了:

#make

创建完成,安装:

#make install

最后你还应该创建一个符号连接cc到这个新的gcc,因为好多时候会用cc而不是gcc,这是为
了与Unix平台保持一致,便于程序的移植。

#ln –vs gcc /toolchain/bin/cc

好了,gcc创建完成了,接下来的创建过程会自动使用这个gcc的,因为你修改了PATH环境变
量。做些首尾工作,要不然你的磁盘可能吃紧了。

#cd ../
#rm –rf build
#cd ../

2.3创建glibc
前面我说过,glibc是自包含的,不会依赖于那个软件包。但是我也说过,它是用户程序与
内核交流的标准借口,因此对内核还是有一定依赖的。但是这并不相矛盾,因为只要是一个系
列的内核,基本上是没多少关系的,比如现今的2.6系列,它们会有提供统一的系统调用。
glibc需要了解内核的系统调用和这些调用相关的一些数据结构。Linux内核做得很好,不需
要有内核的二进制文件,一切都包含在了内核的公用头文件中了。这里说些题外话,如果你够
牛的话,其实完全可以不用glibc,只利用这些头文件就可以写出合适的用户程序的,甚至比利
用glibc的更为优秀。不过如果你的确那么牛,这篇文章也就不适合你了。
不多说了,下载一个内核源代码到你的source目录吧。最新的是2.6.23.12。
解压缩内核源代码包并进入源代码目录:

#tar –jvxf linux-2.6.23.12.tar.bz2
#cd linux-2.6.23.12

安装相关的头文件:

#make mrproper
#make headers_check
#make INSTALL_HDR_PATH=dest header_install
#cp –rv dest/include/* /toolchain/include
#cd ../

关于内核操作有什么不了解的,可以使用make help命令获得帮助。
解压缩glibc的源代码包并进入源代码目录:

#tar –jvxf glibc-2.7.tar.bz2
#cd glibc-2.7

与gcc一样,还需要单独的目录来创建,建立build目录:

#mkdir build
#cd build

由于glibc不再支持i386体系了,因此它的开发者们建议在创建glibc是,最好使用-march=i486编译选
项。的确如此,如果你不指定这个选项,会创建失败。但是毕竟现在i486用的已经很少了,我们
也可以不考虑兼顾,为了进一步提高性能,我建议使用-march=i686编译选项。你可以通过下面的
命令完成这些:

#echo “CFLAGS += -march=i686” > configparms

接着,为创建glibc做准备工作:

#configure –prefix=/toolchain –disable-profile –enable-add-ons \
--enable-kernel=2.6.0 –with-binutils=/toolchain/bin –without-gd \
--with=headers=/toolchain/include –without-selinux

各选项的含义如下:
--disable-profile
忽略掉profiling信息相关的库文件创建,这个时候一般不需要。
--enable-add-ons
这个指示glibc使用附加的NPTL(本地POSIX线程库)包作为线程库。
--enable-kernel=2.6.0
告诉glibc要支持2.6.x内核。
--with-binutils=/toolchain/bin
这个参数并不是必要的,只是为了防止在创建glibc时用错了binutils程序。这里保证使用刚才创建
好的binutils。
--without-gd
保证不生成memusagestat程序,这个程序会产生对你现有系统的依赖。
--with-headers=/toolchain/include
这个选项就是告诉glibc,使用刚刚安装的内核都文件创建自己。
--without-selinux
不提供SELinux特性的支持,因为toolchain是不需要的。
在这个阶段你要是看到下面的警告你就不用管它,跟你没有任何关系,也不会有什么影响的。

configure: WARNING:
*** These auxiliary programs are missing or
*** incompatible versions: msgfmt
*** some features will be disabled.
*** Check the INSTALL file for required versions.

创建软件包:

#make

在安装glibc的过程中,它会警告缺少/toolchain/etc/ld.so.conf文件。其实没什事,不会有什么影响,只要提
供一个空文件它就闭嘴了:

#mkdir –v /toolchain/etc
#touch /toolchain/etc/ld.so.conf

一切顺利就可以安装了:

#make install

恭喜你,又干了一件了不起的事情,不过别忘了首尾阿,空间有限。

#cd ../
#rm –rf build
#cd ../

(未完,待续......)

评论

期待您下一步的指南...

跟我思维非常相似
以前在WINDOWS平台做过一些游戏
初步会一点C++和JAVA
使用VC++和eclipse
应为我懒
没动力
在WINDOWS平台有很多娱乐就更没动力
靠网络资讯维持动力
最后MAGIC的易用性给了我动力
对LINUX的编程环境不熟悉
渴望并正在寻求更的多LINUX知识

第一处:
#make INSTALL_HDR_PATH=dest header_install
修正:
#make INSTALL_HDR_PATH=dest headers_install
第二处:
#configure –prefix=/toolchain –disable-profile –enable-add-ons \
--enable-kernel=2.6.0 –with-binutils=/toolchain/bin –without-gd \
--with=headers=/toolchain/include –without-selinux
修正:
#../configure –prefix=/toolchain –disable-profile –enable-add-ons \
--enable-kernel=2.6.0 –with-binutils=/toolchain/bin –without-gd \
--with-headers=/toolchain/include –without-selinux

谢谢.

我是 一个 程序盲,但是我想学习,并加入其中,不知道能否学会这些东西。
我是一个linux迷,magiclinux是 我 遇到的最好的linux软件,至少是简体中文中最好的

唉,机器有点老,要花N久才行。当时做LFS不得不停了。

写得很详细,读后有收获,不过有些语句读起来意思不怎么对,还有些错别字,希改进,以方便初看你文章的人