CentOS之从源码到RPM包--概念篇
- /*首先在这里向大家深感抱歉。因我没钱开这个软件的会员,无法添加图片,只能复制命令行给大家演示*/
- 第一章:首先我们先了解什么是开放源码、编译程序和可执行文件
- 什么是可执行文件?
- 我们说过,在Linux系统上面,一个文件能不能被执行看的是有没有可执行的那个权限(具有xpermission)
- 不过,Linux系统上真正认识的可执行文件其实是二进制文件(binary program)
- 例如/usr/bin/passwd,/bin/touch这些个文件即为二进制程序代码。
- 或许你会说shell scripts不是也可以执行吗?
- 其实shell scripts只是利用shell(例如bash)这支程序的功能进行一些判断式,而最终执行的除了bash提供的功能外,仍是呼叫一些已经编译好的二进制程序来执行的呢!
- 当然啦,bash本身也是一支二进制程序
- 既然Linux操作系统真正认识的其实是binary program,那么我们是如何做出这样的一支binary的程序呢?
- 首先,我们必须要写程序,用什么东西写程序?就是一般的字处理器啊!
- 用vim来进行程序的撰写,写完的程序就是所谓的源代码啰!
- 这个程序代码文件其实就是一般的纯文本档。在完成这个原始码文件的编写之后,再来就是要将这个文件【编译】成为操作系统看的懂得binary program啰!而要编译自然就需要[编译程序】来动作,经过编译程序的编译与连结之后,就会产生一支可以执行的binary program啰。
- 举个例子:
- 在Linux上面最标准的程序语言为C,所以我使用C的语法进行源代码的书写,写完之后,以Linux|上标准的C语言编译程序gcc这支程序来编译,就可以制作一支可以执行的binary program啰。
- 整个的流程有点像这样:
- 利用已存在的函式库
- ||
- V
- 为纯文字档原始码 ==> 编译器编译 例如gcc编译器 ==> 产生可执行档为 binary file
- 事实上,在编译的过程当中还会产生所谓的目标文件(Objectfile),这些文件是以*o的扩展名样式存在的!至于C语言的原始码文件通常以*.c作为扩展名。
- 此外,有的时候,我们会在程序当中【引用、呼叫】其他的外部子程序,或者是利用其他软件提供的【函数功能】,这个时候,我们就必须要在编译的过程当中,将该函式库给他加进去,如此一来,编译程序就可以将所有的程序代码与函式库作一个链接(Link)以产生正确的执行档啰。
- 首先,我们必须要写程序,用什么东西写程序?就是一般的字处理器啊!
- 那么我怎么知道一个文件是否为binary呢?
- 这里我们就要用到 file 这个指令,我们现在来测试一下
- 先以系统的文件测试看看
- file ~/.bashrc
- [root@localhost ~]# file ~/.bashrc
- /root/.bashrc: ASCII text <==告诉我们是ASCII的纯文字档啊!
- file /bin/bash
- [root@localhost ~]# file /bin/bash
- /bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=9223530b1aa05d3dbea7e72738b28b1e9d82fbad, stripped
- <==看到了吧!如果是binary而且是可以执行的时候,他就会显示执行文件类别(ELF64-bit LSB executable),|同时会说明是否使用动态函式库(shared libs)
- file /var/lib/mlocate/mlocate.db
- ot@localhost ~]# file /var/lib/mlocate/mlocate.db
- /var/lib/mlocate/mlocate.db: data <==这是data档案!
- file ~/.bashrc
- 如果是系统提供的 /etc/init.d/network 呢?
- file /etc/init.d/network
- [root@localhost ~]# file /etc/init.d/network
- /etc/init.d/network: Bourne-Again shell script, ASCII text executable
- <==而如果是一般的script,那他就会显示出text executables之类的字样!
- network的数据显示出Bourne-Again..那一行,是因为你的scipts上面第一行有宣告#/bin/bash的缘故,如果你将script的第一行拿掉,那么不管/etc/init.d/metwork的权限为何,他其实显示的是 ASCII 文本文件的信息喔!
- file /etc/init.d/network
- 先以系统的文件测试看看
- 这里我们就要用到 file 这个指令,我们现在来测试一下
- 总结:
- 开放源码
- 就是程序代码,写给人类看的程序语言,但机器并不认识,所以无法执行;
- 编译程序
- 将程序代码转译成为机器看的懂得语言,就类似翻译者的角色;
- 可执行文件
- 经过编译程序变成二进制程序后,机器看的懂所以可以执行的文件。
- 开放源码
- 什么是可执行文件?
- 第二章:什么是 make 与 configure
- 那么问题来了,make是一个程序,会去找Makefile,那么Makefile怎么写呢?
- 通常软件开发者都会写一个侦测程序(一般叫 configure或 config)来侦测使用者的作业环境,以及该作业环境是否有软件开发商所需要的其它功能。该侦测程序侦测完毕后,就会主动的创建这个makefile的规则文件。
- 那为什么要侦测作业环境呢?
- linux的版本有很多,不同版本的核心所使用的系统呼叫可能不相同,而且每个软件所需要的相依的函式库也不相同,同时,软件开发者不会仅针对Linux开发,而是会针对整个Unix-Like(各种传统的UNIX系统)做开发啊!所以当然要侦测环境啊!
- 一般来说,侦测程序会侦测的数据大约以下几个:
- 是否有适合的编译程序可以编译本软件的程序代码;
- 是否已经存在本软件所需要的函式库,或其他需要的相依软件;
- 操作系统平台是否适合本软件,包括Linux的核心版本;
- 核心的表头定义档(header include)是否存在(驱动程序必须要的侦测)
- 为何需要原始码
- 由于不同的Linux distribution的函式库文件所放置的路径,或者是函式库的档名订定,或者是预设安装的编译程序,以及核心的版本都不相同,因此理论上,你无法在CentOS7.x上面编译出binary program后,还将他拿到不同版本的linux上面执行,这个动作通常是不可能成功的!因为呼叫的目标函式库位置可能不同,核心版本更不可能相同!所以能够执行的情况是微乎其微!所以同一套软件要在不同的平台上面执行时,必须要重复编译!所以才需要原始码嘛!
- 那么问题来了,make是一个程序,会去找Makefile,那么Makefile怎么写呢?
- 第三章:Tarball
- 我们知道所谓的源代码,其实就是一些写满了程序代码的纯文本文件。也了解了纯文本文件在网络上其实是很浪费带宽的一种文件格式。所以啦,如果能够将这些原始码透过文件的打包与压缩技术来将文件的数量与容量减小,不但让用户容易下载,软件开发商的网站带宽也能够节省很多很多啊!这就是Tarball文件的由来啰!
- 所谓的Tarball文件,其实就是将软件的所有原始码文件先以tar打包,然后再以压缩技术压缩,通常最常见的就是以gzip来压缩了。因为利用了tar与gzip的功能,所以tarball文件一般的扩展名就会写成 *.tar.gz 或 *.tgz 。不过,近来由于bzip2与xz的压缩率较佳,所以Tarball渐渐的以bzip2及xz的压缩技术来取代gzip啰!因此档名也会变成*tar.bz2,*tar.xz之类的。
- 所以说,Tarball是一个软件包,始将他解压缩之后,里面的文件通常就会有:
- 源代码文件;
- 侦测程序文件(可能是configure或config等名);
- 本软件的简易说明与安装说明(INSTALL或README)。
- /*其中最重要的是那个INSTALL或者是README这两个文件,通常你只要能够参考这两个文件*/
- 第四章:如何安装与升级软件
- 为何需要升级
- 需要新的功能,但旧有主机的旧版软件并没有,所以需要升级到新版的软件;
- 旧版本的软件上面可能有资安上的顾虑,所以需要更新到新版的软件;
- 旧版的软件执行效能不彰,或者执行的能力不能让管理者满足。
- 更新的方法分为两大类
- 直接以原始码透过编译来安装与升级;
- 直接以编译好的binary program来安装与升级。
- 那么一个软件的Tarball是如何安装的呢
- 1.将Tarball 由厂商的网页下载下来;
- 2.将Tarball解开,产生很多的原始码文件;
- 3.开始以gcc进行原始码的编译(会产生目标文件object files);
- 4.然后以gcc进行函式库、主、子程序的链接,以形成主要的binary file;
- 5.将上述的binary file 以及相关的配置文件安装至自己的主机上面。
- 上面第3,4步骤当中,我们可以透过make这个指令的功能来简化他,所以整个步骤其实是很简单的啦!只不过你就得需要至少有gcc以及make这两个软件在你的Linux系统里面才行喔!详细的过程以及需要的软件我们在后面继续介绍
- 为何需要升级
- 第五章:使用程序语言进行简单的编译
- 打印出 Hello World
- 我们以Linux上面最常见的C语言来撰写第一支程序!我们先安装gcc
- #include<stdio.h>
- int main(void)
- {
- printf("Hello World! \n")
- }
- 我们以Linux上面最常见的C语言来撰写第一支程序!我们先安装gcc
- 开始编译与测试执行
- 将源码编译成可执行文件
- [root@localhost ~]# vim hello.c
- [root@localhost ~]# gcc hello.c
- [root@localhost ~]# ll hello.c hello <==两行命令可以合并为: gcc -o a.out hello.c
- -rwxr-xr-x. 1 root root 8440 10月 19 20:34 hello <==此时会产生这样一个档名
- -rw-r--r--. 1 root root 65 10月 19 20:34 hello.c
- [root@localhost ~]# ./hello
- Hello World! <==输出结果
- /*那个hello.c就是原始码,而gcc就是编译程序,至于hello 就是编译成功的可执行 binary program啰!*/
- 那如果我想要产生目标文件(object file)来进行其他的动作,而且执行档的档名也不要用预设的a.out,那该如何是好?
- [root@localhost ~]# gcc -c hello.c
- [root@localhost ~]# ll hello* <==两行命令可以合并为: gcc -c -o hello.o hello.c
- -rwxr-xr-x. 1 root root 8440 10月 19 20:34 hello
- -rw-r--r--. 1 root root 65 10月 19 20:34 hello.c
- -rw-r--r--. 1 root root 1496 10月 19 20:43 hello.o <==就是被产生的目标文件
- 将源码编译成可执行文件
- 知道为什么要制作出目标文件吗?
- 示例:
- [root@localhost ~]# cat hello1.c
- #include<stdio.h>
- int main(void)
- {
- printf("Hello World! \n");
- hello2();
- }
- [root@localhost ~]# cat hello2.c
- #include<stdio.h>
- int hello2(void)
- {
- printf("Think You! \n");
- }
- [root@localhost ~]# gcc -c hello1.c hello2.c
- [root@localhost ~]# ll hello*
- -rw-r--r--. 1 root root 65 10月 19 20:34 hello1.c
- -rw-r--r--. 1 root root 1496 10月 19 20:57 hello1.o <== 产生的目标文件
- -rw-r--r--. 1 root root 63 10月 19 20:56 hello2.c
- -rw-r--r--. 1 root root 1496 10月 19 20:57 hello2.o <== 产生的目标文件
- [root@localhost ~]# gcc -o hello hello1.o hello2.o
- [root@localhost ~]# ll hello
- -rwxr-xr-x. 1 root root 8504 10月 19 21:05 hello <== 最终产生的
- [root@localhost ~]# ./hello
- Hello World! <==输出结果
- Think You!
- 由于我们的原始码文件有时并非仅只有一个文件,所以我们无法直接进行编译。这个时候就需要先产生目标文件,然后再以连结制作成为binary可执行文件。
- 另外,如果有一天,你更新了hello2.c这个文件的内容,则你只要重新编译 hello2.c来产生新的hello2.o,然后再以连结制作出新的binary可执行文件即可!而不必重新编译其他没有更动过的原始码文件。
- 示例:
- gcc的简单用法
- gcc为Linux上面最标准的编译程序,这个gcc是由GNU计划所维护的。既然gcc对于Linux上的Open source是这么样的重要,所以底下我们就列举几个gcc常见的参数,如此一来大家应该更容易了解原始码的各项功能吧!
- /*仅将原始码编译成为目标文件,并不制作链接等功能*/
- gcc-c hello.c
- 会自动的产生hello.o这个文件,但是并不会产生binary 执行档。
- /*在编译的时候,依据作业环境给予优化执行速度*/
- gcc-0 hello.c-c
- 会自动的产生hello.o这个文件,并且进行优化喔!
- /*在进行binary file制作时,将连结的函式库与相关的路径填入*/
- gcc sin.c-lm-L/lib-I/usr/include
- 这个指令较常下达在最终连结成 binary file的时候;
- -lm指的是libm.so或libm.a这个函式库文件;
- -L后面接的路径是刚刚上面那个函式库的搜寻目录;
- -l后面接的是原始码内的include 文件之所在目录。
- /*将编译的结果输出成某个特定档名*/
- gcc-o hello hello.c
- -O后面接的是要输出的binary file档名
- 在编译的时候,输出较多的讯息说明
- gcc-o hello hello.c-Wall
- 加入-Wall之后,程序的编译会变的较为严谨一点,所以警告讯息也会显示出来!
- 比较重要的大概就是这一些。另外,我们通常称-Wall或者-O这些非必要的参数为旗标(FLAGS),因为我们使用的是C程序语言,所以有时候也会简称这些旗标为CFLAGS,这些变量偶尔会被使用的喔!尤其是在后头会介绍的make相关的用法时,更是重要的很呐!^_^
- 打印出 Hello World