# Tarball 的管理与建议
那么接下来我们要知道如何使用具有源码的 Tarball 来建立一个属于自己的软件
Tarball 的安装是可以跨平台的,只是需要的编译程序可能并不相同,例如 Linux 上用 gcc,而 windows 上也有相关的 c 编译程序。
如果万一没有编译成功,可以通过修改小部分的程序代码(通常是因为很小部分的不同)就可以跨平台的移植了
# 使用源码管理软件所需要的基础软件
从源码制作一个 binary program 需要很多软件的支持,包括以下基础的软件:
gcc 或 cc 等 c 语言编译程序(compiler)
编译程序也有很多,其中以 GNU 的 gcc 是首选的自由软件编译程序,在 Linux 平台上面发展的软件的源码,原本就是以 gcc 为底来设计的
需要 Kernel 提供的 Library 以及相关的 Include 文件
从前面的源码编译过程,我们知道函数库 library 的重要性,和 include 文件的存在。
很多软件在发展的时候都是直接取用系统核心提供的函数库与 include 文件,尤其是在驱动程序方面的模块,例如网卡、声卡、USB 等驱动程序在安装的时候,常常需要核心提供相关的信息。
在 Red Hat 系统中(包含 Fedora、CentOS 等系列),这个核心相关的功能通常都是被包含在 kernel-source 或 kernel-header 这些软件名称中,所以记得安装这些软件
一般来说 Tarball 的安装比较简单,只要顺着开发商提供的 README 与 INSTALL 文件的说明步骤来安装,基本上是很容易的,但是在论坛上还会发现很多人问提示 「没有 gcc 程序」、「无法使用 make」等问题,这些基本上都是以上基础软件没有安装的原因
目前的 Linux distribution 大多已经偏向与桌面计算机的使用(非服务器),所以默认不会安装这些偏向开发的软件,如果你希望未来可以安装一些以 Tarball 方式的软件时,请自行挑选想要安装的软件名称。例如在 CentOS 或死 Red Hat 中,需要选中 Development Tools 以及 Kernel Source Development 等相关字眼的软件群
如果你在安装 Linux 时,没有选择这些软件随机安装,也就是没有 make、gcc 等这些东西,那么可以使用 RPM (下章节讲解)的方式来安装软件,所以只要拿出当初安装 Linux 时的原本光盘,然后以 RPM 来一个一个安装到你的 Linux 主机里面,尤其是现在有 yum ,在线安装更方便了
在 CentOS 中,如果你已经联网的话,那么可以使用下一章会介绍到的 yum,通过 yum 的软件群组安装工功能,可以如下做:
- 安装 gcc 等软件开放工具:
yum groupinstall "Development Tools"
- 若待安装的软件需要图形接口支持,一般还需要:
yum groupinstall "X Software Development"
- 若安装的软件较旧,可能需要:
yum groupinstall "Legacy Software Development"
详细信息请参考后续章节
# Tarball 安装的基本步骤
步骤如下:
- 取得源码文件:将 tarball 文件在
/usr/local/src
目录下解压 - 取得步骤流程:进入新建立的目录下,查阅 INSTALL 或 README 等相关文件内容(很重要)
- 相依属性软件安装:根据 INSTALL/README 的内容查看并安装好一些相依的软件(非必要)
- 建立 makefile:用自动检测程序(configure 或 config)检测作业环境,并建立 Makefile 文件
- 编译:以 make 程序并使用该目录下的 Makefile 作为参考配置文件,进行 make 编译或其他的动作
- 安装:以 make 程序,并以 Makefile 作为参数配置文件,根据 install 这个目标(target)的指定来安装到正确的路径
下面简约介绍下大部分的 tarball 软件安装的指令下达方式:
./configure
程序开发者提供的一个 scripts 检查程序,并生成 Makefile 文件
make clean
会读取 Makefile 中关于 clean 的工作,该步骤不一定会有,但是希望之星下,因为他可以删除目标文件。至少能保证后续编译出来的 *.o 文件使我们自己机器编译出来的
make
会根据 Makefile 中预设的工作进行编译行为,主要工作是进行 gcc 来将源码编译为可以被执行的 object files。但是这些 object files 通常还需要一些函数库之类的 link 后,才能产生一个完整的执行文件。使用 make 就是将源码便以为可被执行的文件,该执行文件会放到目前所在的目录下,尚未被安装到预定安装的目录中
make install
通常这就是最后的安装步骤了,make 会根据 Makefile 文件里关于 install 的项目,将上一个步骤所编译完成的数据安装到预定的目录中,就安装完成了
以上步骤,只要前一个步骤没有成功,那么后续步骤就无法执行成功的。
如果安装成功,并且是安装在独立的一个目录中,例如 /usr/local/packages
目录中,那么你必须手动的将整个软件的 man page 给它写入到 /etc/man_db.conf
# 一般 Tarball 软件安装的建议事项(如何移除?升级?)
为什么前一个章节,Tarball 要在 /usr/local/src
下解压呢?基本上,在预设的情况下,原本的 Linux distribution 释出安装的软件大多是在 /usr
中,而用户自行安装的软件则建议放置 /usr/local
中。这是考虑到管理用户所安装软件的便利性
几乎所有的软件都提供联机帮助服务,就是 info 与 man 功能。在默认情况下,man 会搜索 /usr/local/man
中的说明文件,因此如果将软件安装在 /usr/local
下,那么安装完成后,该软件的说明文件就可以被找到了(笔者疑问:可没有说说明文件说明时候被安装到指定目录的?)
所以,通常建议将自己安装的软件放在 /usr/local/
下,至于源码(Tarball)则建议放到 /usr/local/src
下
再来看看 Linux distribution 默认的安装软件的路径会用到哪些?这里以 apache 软件来说明:
/etc/httpd
:配置文件/usr/lib
:函数库/usr/bin
:执行文件/usr/share/man
:联机帮助文件
会发现软件的内容大致上是放在 etc、lib、bin、man 目录中的。那么通过 tarbal 来安装时,如果是放在预设的 /usr/local
中,由于 /usr/local
原本默认这几个目录,所以你的数据就会被放在:
/usr/local/etc
/usr/local/bin
/usr/local/lib
/usr/local/man
如果你每个软件都选择在这个默认的路径下安装的话,那么所有的软件文件都将放在这 4 个目录中,那么未来再想要升级或移除的时候,就会比较难以追查文件的来源,而如果在安装的时候选择的是单独目录,例如我将 apache 安装在 /usr/local/apache
中,那么你的文件目录就会变成
/usr/local/apache/etc
/usr/local/apache/bin
/usr/local/apache/lib
/usr/local/apache/man
这样一来,移除软件就简单多了,只要将该目录移除就可以了。
当然,实际安装的时候,还需要看该软件的 Makefile 里 install 信息才能知道它的安装情况。因为例如 sendmail 的安装就很麻烦
此种方式虽然有利于软件的移除,但是在执行指令的时候,该指令是否在 PATH 环境变量所记录的路径有关。以上面的 Apache 软件安装为例,/usr/local/apache/bin
肯定不在 PATH 里面的,所以执行 apache 的指令,要么使用绝对路径,要么加入到 PATH 中,另外还需要将 /usr/local/apache/man
也加入到 man page 搜索的路径中
另外,Tarball 在升级的时候也挺困扰,以 apache 来说明,WWW 服务器为了考虑互动性,所以通常会将 PHP+MySql+Apache
一起安装,那么每个软件在安装的时候都有一定的顺序与程序,因为他们之间具有相关性,所以安装时必须要三者同时考虑到他们的函数库与相关的编译参数
假设今天只要升级 PHP呢?有时候因为只涉及动态函数库的升级,那么只要升级 PHP 即可,其他的部分或许影响不大。但是今天如果 PHP 需要重新编译的模块比较多,那么可能会连带的,连 Apahce 这个程序也需要重新编译过才行。所以使用 tarball 确实有它的优点,但是在这方面也确实麻烦
由于 Tarball 在升级与安装上面具有这些特色,即 Tarball 在反安装上面具有比较高的难度(如果你没有好好规划的话),所以为了方便 Tarball 的管理,通常作者会这样建议使用者:
最好将 tarball 的源码数据解压到
/usr/local/src
中安装时,最好安装到
/usr/local
这个默认路径下考虑未来的反安装步骤,最好可以将每个软件单独的安装在
/usr/local
下为安装到单独目录的软件的 man page 加入 man path 搜索
如果你安装的软件在
/usr/local/software/
那么 man page 搜索设置中,可能需要在/etc/man_db.conf
内的 40~50 行左右处,写入如下的一行MANPATH_MAP /usr/local/software/bin /usr/local/software/man
1这样才可以使用 man 来查询该软件的在下文件
TIP
时至今日,不太需要有 tarball 的安装了。 CentOS/Fedora 有个 RPM 补遗计划,就是俗称的 EPEL 计划,相关说明请参考 EPEL ,一般学界用到的软件都在里面,除非你要用的软件是专属收费软件,或则是比较冷门的软件,否则都有好心的网友帮我妈打包好了
# 一个简单的范例,利用 ntp 来示范
这里用时间服务器 ntp(network time protocol)软件来测试安装。下载网址请在此 网页中找到下载包链接 ,本次使用 http://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-4.2.8p14.tar.gz
这个版本。
假设我对这个软件的要求如下:
- 假设
ntp4.*.*.tar.gz
文件放到/root
目录下 - 源码解压在
/usr/local/src
下 - 安装到
/usr/local/ntp
目录中
解压文件,并阅读 README/INSTALL 文件
[root@study ~]# cd /usr/local/
[root@study local]# tar -zxv -f /root/ntp-4.2.8p14.tar.gz
[root@study local]# cd ntp-4.2.8p14/
[root@study ntp-4.2.8p14]# vi INSTALL
# 查看安装说明,使用 set nu 显示行号
# 然后阅读 28 ~ 54 行的安装步骤,大约就是如下的内容
28 The simplest way to compile this package is:
29
30 1. `cd' to the directory containing the package's source code and type
31 `./configure' to configure the package for your system. If you're
32 using `csh' on an old version of System V, you might need to type
33 `sh ./configure' instead to prevent `csh' from trying to execute
34 `configure' itself.
35
36 Running `configure' takes a while. While running, it prints some
37 messages telling which features it is checking for.
38
39 2. Type `make' to compile the package.
40
41 3. Optionally, type `make check' to run any self-tests that come with
42 the package.
43
44 4. Type `make install' to install the programs and any data files and
45 documentation.
46
47 5. You can remove the program binaries and object files from the
48 source code directory by typing `make clean'. To also remove the
49 files that `configure' created (so you can compile the package for
50 a different kind of computer), type `make distclean'. There is
51 also a `make maintainer-clean' target, but that is intended mainly
52 for the package's developers. If you use it, you may have to get
53 all sorts of other programs in order to regenerate files that came
54 with the distribution.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
检查 configure 支持的参数,并实际建立 makefile 规则文件
[root@study ntp-4.2.8p14]# ./configure --help | more
`configure' configures ntp 4.2.8p14 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
有很多参数,下面列出来比较重要的选项
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--enable-all-clocks + include all suitable non-PARSE clocks:
--enable-parse-clocks - include all suitable PARSE clocks:
[root@study ntp-4.2.8p14]# ./configure --prefix=/usr/local/ntp --enable-all-clocks --enable-parse-clocks
...
checking for gcc..gcc # 找到了 gcc 编译程序
...
configure: creating ./config.status
config.status: creating libevent.pc
config.status: creating libevent_openssl.pc
config.status: creating libevent_pthreads.pc
config.status: creating Makefile # 创建了一个 Makefile
config.status: creating config.h
config.status: creating evconfig-private.h
config.status: evconfig-private.h is unchanged
config.status: executing depfiles commands
config.status: executing libtool commands
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
一般来说 configure 设置参数比较重要的就是 --prefix=PREFIX
了,后面指定了该软件未来要安装到的目录
最后开始编译与安装
[root@study ntp-4.2.8p14]# make clean; make
[root@study ntp-4.2.8p14]# make check
...
============================================================================
Testsuite summary for ntp 4.2.8p14
============================================================================
# TOTAL: 1
# PASS: 1
# SKIP: 0
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
# 通过 check 后,会列出一个清单结果,这里是表示都成功了
[root@study ntp-4.2.8p14]# make install
# 安装成功后,就可以看到 ntp 目录下安装好的文件了
[root@study ntp]# cd /usr/local/ntp
[root@study ntp]# ll
total 0
drwxr-xr-x. 2 root root 189 Apr 6 03:49 bin
drwxr-xr-x. 2 root root 6 Apr 6 03:49 libexec
drwxr-xr-x. 2 root root 6 Apr 6 03:49 sbin
drwxr-xr-x. 5 root root 39 Apr 6 03:49 share
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 利用 patch 更新源码
所谓更新源码,通常是某一段代码有问题,因此通常只是更新部分文件的小部分内容。
好处则是:没有变动的文件的目标文件(object file)不需要重新编译,变动过的文件可以利用 make 来自动 update,如此一来,原先的设置(makefile 文件里面的规则)将不需要重新改写或检测,可以节省很多的宝贵时间
可以用 diff 指令将两个文件的差异性列出来,再以相关的指令来将旧版的文件更新,这是可以的,通常很多软件开发商在更新了源码之后,几乎都会放出所谓的 patch file,也就是直接将源码 update 的一个方式,使用 patch 指令来完成。
关于 diff 与 patch 的基本用法在第 11 章已经讲过了。下面通过一个简单的例子来讲解;之前章节的计算函数的例子,相关文件如下
# main-0.1 版本
[root@study main-0.1]# ll
total 20
-rw-r--r--. 1 root root 184 Apr 6 04:01 cos_value.c
-rw-r--r--. 1 root root 101 Apr 6 04:01 haha.c
-rw-r--r--. 1 root root 291 Apr 6 04:01 main.c
-rw-r--r--. 1 root root 142 Apr 6 04:02 Makefile
-rw-r--r--. 1 root root 186 Apr 6 04:02 sin_value.c
2
3
4
5
6
7
注意:以下文件,可能是由于复制过程中的编码问题,会导致部分与 patch 中的文件内容不一致,从而导致 patch 过程失败,请直接下载以下链接中的包,并解压到 /root/
下
wget http://linux.vbird.org/linux_basic/0520source/main-0.1.tgz
wget http://linux.vbird.org/linux_basic/0520source/main_0.1_to_0.2.patch
下载后,修改文件名为
main-0.1-to-0.2.patch
main.c
#include <stdio.h>
#define pi 3.14159
char name[15];
float angle;
int main(void)
{
printf ("\nversion 0.1");
printf ("\n\nPlease input your name: ");
scanf ("%s", &name );
printf ("\nPlease enter the degree angle (ex> 90): " );
scanf ("%f", &angle );
haha( name );
sin_value( angle );
cos_value( angle );
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
haha.c
#include <stdio.h>
int haha(char name[15])
{
printf ("\n\nHi, Dear %s, nice to meet you.", name);
}
2
3
4
5
sin_value.c
#include <stdio.h>
#include <math.h>
#define pi 3.14159
float angle;
void sin_value(void)
{
float value;
value = sin ( angle / 180. * pi );
printf ("\nThe sin(%f) is: %5.2f\n",angle, value);
}
2
3
4
5
6
7
8
9
10
11
cos_value.c
#include <stdio.h>
#include <math.h>
#define pi 3.14159
float angle;
void cos_value(void)
{
float value;
value = cos ( angle / 180. * pi );
printf ("The Cos is: %5.2f\n",value);
}
2
3
4
5
6
7
8
9
10
11
Makefile
# This make file is a test rule file
# # Version 0.1 2009/06/06
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
main: ${OBJS}
gcc -o main ${OBJS} ${LIBS}
clean:
rm -f main ${OBJS}
2
3
4
5
6
7
8
记得调整上面使用 tab 的语法部分
# 由 0.1 升级到 0.2 的 patch file
main-0.1-to-0.2.patch
diff -Naur main-0.1/cos_value.c main-0.2/cos_value.c
--- main-0.1/cos_value.c 2015-09-04 14:46:59.200444001 +0800
+++ main-0.2/cos_value.c 2015-09-04 14:47:10.215444000 +0800
@@ -7,5 +7,5 @@
{
float value;
value = cos ( angle / 180. * pi );
- printf ("The Cos is: %5.2f\n",value);
+ printf ("The cos(%f) is: %5.2f\n",angle, value);
}
diff -Naur main-0.1/main.c main-0.2/main.c
--- main-0.1/main.c 2009-06-12 00:39:38.000000000 +0800
+++ main-0.2/main.c 2009-06-12 00:45:38.000000000 +0800
@@ -5,7 +5,7 @@
int main(void)
{
- printf ("\nversion 0.1");
+ printf ("\nversion 0.2");
printf ("\n\nPlease input your name: ");
scanf ("%s", &name );
printf ("\nPlease enter the degree angle (ex> 90): " );
diff -Naur main-0.1/Makefile main-0.2/Makefile
--- main-0.1/Makefile 2009-06-12 00:34:53.000000000 +0800
+++ main-0.2/Makefile 2009-06-12 00:42:39.000000000 +0800
@@ -1,8 +1,12 @@
# This make file is a test rule file
-# Version 0.1 2009/06/06
+# Version 0.2 2009/06/11
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
main: ${OBJS}
gcc -o main ${OBJS} ${LIBS}
clean:
rm -f main ${OBJS}
+install:
+ cp -a main /usr/local/bin
+uninstall:
+ rm -f /usr/local/bin/main
diff -Naur main-0.1/sin_value.c main-0.2/sin_value.c
--- main-0.1/sin_value.c 2015-09-04 14:46:52.286444001 +0800
+++ main-0.2/sin_value.c 2015-09-04 14:47:17.665444020 +0800
@@ -7,5 +7,5 @@
{
float value;
value = sin ( angle / 180. * pi );
- printf ("\nThe Sin is: %5.2f\n",value);
+ printf ("\nThe sin(%f) is: %5.2f\n",angle, value);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
把这目录和文件放到 root 目录下
drwxr-xr-x. 2 root root 88 Apr 6 04:11 main-0.1
-rw-r--r--. 1 root root 1538 Apr 6 04:11 main-0.1-to-0.2.patch
2
在 0.1 版本中,有 main 与 clean 两个目标功能。而 0.2 版本则增加了 install 与 uninstall 的规则与设置。下面来进行升级
# 测试旧版程序的功能
[root@study main-0.1]# make clean main
rm -f main main.o haha.o sin_value.o cos_value.o
cc -c -o main.o main.c
cc -c -o haha.o haha.c
cc -c -o sin_value.o sin_value.c
cc -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
[root@study main-0.1]# ./main
version 0.1
Please input your name: mrcode
Please enter the degree angle (ex> 90): 45
Hi, Dear mrcode, nice to meet you.
The Sin is: 0.71
The Cos is: 0.71
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
与之前的结果类似,但是如果你下达 make install 时,系统会告知没有 install 的 target,如何更新到 0.2 版本呢?
# 查阅 patch file 内容
[root@study ~]# vim main-0.1-to-0.2.patch
diff -Naur main-0.1/cos_value.c main-0.2/cos_value.c
--- main-0.1/cos_value.c 2015-09-04 14:46:59.200444001 +0800
+++ main-0.2/cos_value.c 2015-09-04 14:47:10.215444000 +0800
2
3
4
diff -Naur main-0.1/cos_value.c main-0.2/cos_value.c
表示使用 diff 去比较时,比较的两个文件路径,该路径非常重要,因为 patch 的基本语法如下
patch -p 数字 < patch_file
-p: 与 patch_file 里列出的文件名有关的信息。假如 patch_file 里面累出的文件名有关的信息,假如第一行是写的 `*** /home/guest/example/expatch.old`
那么当下达 patch -p0 < patch_file 时,更新的文件是 /home/guest/example/expatch.old,
如果下达 patch -p1 < patch_file 时,更的文件是 home/guest/example/expatch.old
如果下达 patch -p4 < patch_file 时,更新的是 expatch.old
也就是说 -pxx xx 表示是拿掉几个斜线的意思
那么上面比较的文件是在 main-0.1/xxx 与 main-0.2/xxx 所以,如果你是在 main-0.1 下,并且想要处理更新时,就需要拿掉一个目录,因为并没有 main-0.2 的存在,我们是在当前的目录进行更新的,因此需要使用 -p1 才对
2
3
4
5
6
7
8
9
10
# 更新源码,并重新编译程序
[root@study main-0.1]# patch -p1 < ../main-0.1-to-0.2.patch
patching file cos_value.c
patching file main.c
patching file Makefile
patching file sin_value.c
# 请注意,目前所在的目录在 main-0.1 ,注意与 patch 文件的相对路径
# 虽然有 5 个文件,但是只有 4 个文件有修改过,上面显示有修改过的文件
[root@study main-0.1]# make clean main
rm -f main main.o haha.o sin_value.o cos_value.o
cc -c -o main.o main.c
cc -c -o haha.o haha.c
cc -c -o sin_value.o sin_value.c
cc -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
[root@study main-0.1]# ./main
version 0.2
Please input your name: mrcode
Please enter the degree angle (ex> 90): 45
Hi, Dear mrcode, nice to meet you.
The sin(45.000000) is: 0.71
The cos(45.000000) is: 0.71
[root@study main-0.1]# make install
cp -a main /usr/local/bin
# 可以看到,把执行程序复制到了 bin 下,所以就可以不加绝对路径运行了
[root@study main-0.1]# main
[root@study main-0.1]# make uninstall
rm -f /usr/local/bin/main
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
这个就是利用了 diff 和 patch 指令来完成的源码更新,然后重新编译安装的效果和流程。
如果你 patch 错误呢?可以通过 patch -R < ../main-0.1-to-0.2.patch
将已经更新过的还原。(笔者在复制笔记上的文件到虚拟机文件的时候,不知道哪里有问题,导致前 4 个文件可以 patch 成功,但是第 4 个文件显示失败,这种情况下,就可以通过这样的指令还原回去)
一个问题:如果有一个很旧版本的软件,该软件已经更新到最新版本,例如核心,我可以使用 patch file 来更新吗?
答:首先要确认有释放出 patch file 才行,以 kernel 2.2.xx 与 2.4.xx 来说,基本上的架构已经不同了,所以两者无法以 patch file 来更新的。不过 2.4.xx 与 2.4.yy 就可以。不过,因为 kernel 每次推出的 patch 文件都是针对前一个版本而已,假设你的内核是 kernel 2.4.20 要升级大 2.5.26,那么中间有 5 个文件,需要按顺序更新才可以。但是如果有朋友帮你对比过 2.4.20 与 2.4.26,那么你直接使用该 patch file 来直接一次更新也可以
← 用 make 进行宏编译 函数库的管理 →