给RPM打包的软件加补丁
构建 RPM 软件包通常要求您以 root 用户登录。 其原因如下:
- RPM 在打包过程中安装软件,并且通常只有 root 用户可以写到安装目录中。
- RPM 需要读写 /usr/src/redhat(一般用户不能修改它)下的目录。
通过用 RPM 构建根(build root)来解决第一个问题。
要解决第二个问题,可以通过更改 %_topdir 设置来告诉 RPM 查找和创建不同目录集中的文件。按照下面的方法在您的主目录下创建一个名为 .rpmmacros的文件:
%_topdir /home/your_userid/rpm
这个文件会告诉 RPM:它先前在 /usr/src/redhat 下查找的所有目录应该改为在 /home/your_userid/rpm 下查找。 现在,您应该创建这样一个完整的目录树:~/rpm ~/rpm/SOURCES ~/rpm/SPECS ~/rpm/BUILD ~/rpm/RPMS ~/rpm/RPMS/i386 ~/rpm/SRPMS
~/rpm
~/rpm/SOURCES
~/rpm/SPECS
~/rpm/BUILD
~/rpm/RPMS
~/rpm/RPMS/i386
~/rpm/SRPMS
(如果愿意,可以通过在 RPM 中重新定义其它宏,来将其中任何目录放在您想放的任何地方。您可能需要考虑更改的一些宏包括 %_sourcedir 、 %_specdir 、 %_srcrpmdir 、 %_builddir 和 %_rpmdir 。 有关这些宏的缺省值,请查看 /usr/lib/rpm/macros。 对于这个示例,我们仅仅将它们都放在 ~/rpm 下。)
现在,将 indent-2.2.6.tar.gz 文件复制到 ~/rpm/SOURCES,这里 没有以 root 用户登录,运行 rpm -ba indent-2.spec 。RPM 将 把 indent 构建在 ~/rpm/BUILD 目录下,并将二进制的 RPM 包放在 ~/rpm/RPMS/i386 中,将源代码包放在 ~/rpm/SRPMS 中。
与之相对照,在没有构建根的情况下,尝试使用 spec 文件 indent-1.spec 。RPM 在尝试将 indent 安装到 /usr/local/bin 中时会失败。
使用构建根和设置 RPM 的 i%_topdir 使您能在不作为 root 运行的情况下构建许多软件包,但这并不总是很容易。
首先,一些包并不象 indent 那样可以容易地安装到构建根目录中。对于那些任何未用 GNU autoconf 来开发的包,您必须要仔细查看一下,看是否有一种方法,可以将包安装到另一个目录中, 这也许可以修改 Makefile 来强制这样做。 在下一部分中,我将向您演示如何使用 RPM 来构建已修改的程序。
其次,只有相当少部分包将在其正常安装期间试图做一些只有 root 用户才可以做的事情,如:
- 创建特殊文件(管道、设备文件等等)
- 修改系统配置文件`
您必须逐个处理这些问题。通常,您可以在 post-install 脚本(在安装 RPM 之后运行的脚本)中做一些必要工作。 我将在以后的文章中讨论它们,但简而言之,可以将“%post”节添加到 spec 文件中, 并在该节中放置一些 Linux 命令,以便在安装 RPM 之后运行这些命令。
假设您有一些要打成 RPM 包的软件, 但如果不对它做一些更改,就不能在 Linux 上构建它。 然而,您又没有拥有该软件,所以不能正式地更改它。
您所需要做的就是对该软件的正式版本进行 打补丁或做一些修改。 但是,对其他人的软件进行修改,然后再分发此修改过的版本通常被认为是不礼貌的,所以您希望您自己所做的更改对别人来说也是可用的。 这样,使用您的包的任何人都可以看到您做了哪些事情以及确定您所做的更改是否是可接受的。
这是常有的事,而且 RPM 也提供一些帮助。 您可以建立一个 RPM 包,以便二进制 RPM 文件包含您对程序所做的修改,并且源 RPM 不仅包含原始的源代码, 而且还包含您所做的更改以及有关如何应用和构建这些更改的所有详细信息。
这些步骤如下:
- 断定对源代码做哪些更改就可使软件工作。
- 创建一个 补丁文件来捕获您所做的更改。
- 将该补丁添加到 RPM spec 文件。
通常,要做的第一件事是,在没有 RPM 的情况下编译并运行软件。明了必须要更改的那些文件。 如果有必要,可创建一些新文件或除去与原始源代码一起交付的一些文件。
对于这个示例,我将代码抽取到目录 indent-2.2.6-working 中。我修改了 indent.c, 以便在程序启动时打印一条表示友好的消息,然后验证该程序是否仍可以构建以及该程序是否仍能工作。
现在,您希望创建一个仅捕获您所做更改的补丁文件。 这里有一种可以实现这的方法。虽然这有点儿乏味,但能够确保您捕获所有更改。
- 将软件完全抽取到一个新目录中,然后复制您已对其做过更改的文件,使其覆盖刚抽取出的那些文件。 这样,在本来应该在您先前构建和测试软件时创建的目录中就不会有任何多余的文件。 类似地,复制您创建的任何新文件,并删除任何您先前删除过的文件。
对于这个示例,我已完全抽取到目录 indent-2.2.6-my,并覆盖文件 indent.c。
- 再一次将软件抽取到另一个目录。这样就提供了一个原始软件的副本来与您的软件进行比较。对于这个示例,我是将软件抽取到 indent-2.2.6 目录。
现在,已有三个目录:
- indent-2.2.6-working
- 工作目录
- indent-2.2.6-my
- 经过更改的软件,其中含有我所做的更改
- indent-2.2.6
- 未更改的软件
- 从这三个目录的父目录中用类似于以下的命令生成补丁文件:
diff -uNr indent-2.2.6 indent-2.2.6-my >indent-2.2.6.patch
注意,使用 diff 时运用了选项 -uNr 。 -u 以 统一格式创建补丁文件,这种格式比缺省格式更紧凑些。 -N 确保补丁文件将正确地处理已经创建或删除文件的情况。 -r 比较命令行上所给出的两个目录的所有子目录中的所有文件。
另外还要注意:只要您完全按上述来做,这些目录名是无关紧要的。 补丁文件中将有这些目录名,但我们将通知补丁程序忽略它们。
现在,检查一下补丁文件 indent-2.2.6.patch。下面是我的示例:
清单 1. indent-2.2.6.patch
diff -uNr indent-2.2.6/indent.c indent-2.2.6-my/indent.c
--- indent-2.2.6/indent.cThu Nov 16 22:01:04 2000
+++ indent-2.2.6-my/indent.cWed Sep 26 14:33:11 2001
@@ -1864,6 +1864,8 @@
int using_stdin = false;
enum exit_values exit_status;
+ printf("Hello from Dan
");
+
#ifdef _WIN32
/* wildcard expansion of commandline arguments, see wildexp.c */
extern void wildexp (int *argc, char ***argv); |
有时候,您会注意到 diff 检查出了您无意要做的更改。 这时,您可能需要回过去,清除您的代码并再次生成补丁,直到获得一个干净的、令您满意的补丁文件为止。
一旦按您所希望的那种方式完成补丁之后,最好添加注释以说明您所做的更改。 在不损害任何内容的情况下,在补丁文件的开始处或结束处添加文本。
清单 2. 带注释的 indent-2.2.6.patch
Dan Poirier - 2001-09-26 - added a friendly greeting as indent starts.
This is just an example.
diff -uNr indent-2.2.6/indent.c indent-2.2.6-my/indent.c
--- indent-2.2.6/indent.cThu Nov 16 22:01:04 2000
+++ indent-2.2.6-my/indent.cWed Sep 26 14:33:11 2001
@@ -1864,6 +1864,8 @@
int using_stdin = false;
enum exit_values exit_status;
+ printf("Hello from Dan
");
+
#ifdef _WIN32
/* wildcard expansion of commandline arguments, see wildexp.c */
extern void wildexp (int *argc, char ***argv); |
现在,该让 RPM 使用您的补丁了。将该补丁文件复制到您的 SOURCES 目录(如果您遵循了先前的建议,则或许是 ~/rpm/SOURCES),然后对 spec 文件做下列更改:
清单 3. indent-3.spec:使用 indent-2.2.6.patch
Summary: GNU indent
Name: indent
Version: 2.2.6
Release: 3
Source0: %{name}-%{version}.tar.gz
Patch0: %{name}-2.2.6.patch
License: GPL
Group: Development/Tools
BuildRoot: %{_builddir}/%{name}-root
%description
The GNU indent program reformats C code to any of a variety of
formatting standards, or you can define your own.
%prep
%setup -q
%patch -p1
%build
./configure
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
/usr/local/bin/indent
%doc /usr/local/info/indent.info
%doc %attr(0444,root,root) /usr/local/man/man1/indent.1
%doc COPYING AUTHORS README NEWS
|
现在,用 rpm -ba indent-3.spec 命令构建您的包。 如果您密切关注构建过程的话,会看到在构建期间 RPM 应用了您的补丁。
%Patch0: %{name}-2.2.6.patch 这一行告诉 RPM 第一个补丁文件名。 如果有必要,可以添加 %Patch1 、 %Patch2 等。
在 %prep 部分中的 %patch -p1 行是一个 RPM 宏, 它将在您系统的构建目录中运行补丁程序,其中把第一个补丁文件作为输入。 需要将 -p1 传递给补丁程序,告诉它从补丁文件中的路径中剥去一层目录,因为该补丁文件包含 indent-2.2.6 目录名,而 RPM 将在该目录内运行该补丁文件。
既然,您理解了有关如何构建 RPM 包的基础知识,则可以通过研究一些示例来学习更多的知识。 最好的源代码示例之一是您自己的 Linux 分发版。例如,RedHat 带有包含源 RPM 包的整张 CD。 以下是如何使用它们。
源 RPM 包包含:
- 一个 .spec 文件
- 一个或多个源文件
- 所有使用过的补丁文件
与安装二进制 RPM 包类似,可以使用 rpm -i filename.rpm 安装源 RPM 包。 安装完之后,.spec 文件将在您的 %_specdir 目录中,源文件和补丁文件将在您的 %_sourcedir 目录中。 如果创建了上面描述的 .rpmmacros 文件,那么这些目录为 ~/rpm/SPECS 和 ~/rpm/SOURCES。
现在,可以读取 Red Hat 自己分发的这些包的 .spec 文件。 可以尝试用 rpm -ba foo.spec 构建这些 .spec 文件,并观察所发生的事情,以及摆弄 spec 文件以尝试一些新的事物。
对于 GNU indent 程序,一个好的方法是从 Red Hat 的源 RPM 包开始。看一下您是否可以想出为什么它们的 .spec 文件不同于本文中的 .spec 文件。
不幸的是,二进制 RPM 包在可移植性方面不是很好。多数情况下,构建在某个 Linux 分发版上的 RPM 不能应用到另一个 Linux 分发版。 更不要说应用到同一个分发版的另一个版本上!
原因有很多,包括基本内核版本、库版本和目录结构方面的差异。
这很不幸,但象 Linux Standard Base这样的组织正在尝试达到分发版之间的一致, 以解决难以移植的问题。也许有一天,构建在一个主流 Linux 分发版上的任何 RPM 都可以安装和运行在相同的处理器之上的任何 其它主流 Linux 分发版上。
至于现在,您应该做好计划,有多少个 RPM 将要在其上运行的分发版,就可能构建有多少个 RPM,或者寻找志愿者来为您完成这件事。
为了使其他人在尽可能多的分发版上构建您的软件,就要使 .spec 文件和补丁文件成为可用的文件。
如果有必要,最好的方法是直接更改软件,所以该方法将在 Linux 上进行构建,并将 .spec 文件包含在分发版中。 如果 .spec 文件在带有源码的 tar 压缩包(.tar.gz 文件)中,那么用户只需运行:
rpm -tb foo.tar.gz |
并构建该包的二进制 RPM ― 甚至无需解压该 tar 文件!
如果无法使 .spec 文件包含在软件中,则可以分发一个源 RPM 包。 有了这,用户就可以运行:
rpm --rebuild foo.src.rpm |
并在他们的系统上构建二进制 RPM。
责任编辑 赵毅 zhaoyi#51cto.com TEL:(010)68476636-8001
- · Informix动态服务器onstat选项
- · Informix SQL 的使用技巧
- · 在UNIX下的Informix-online中合理地组织表
- · 开发优质高效的Informix数据库应用程序(1)
- · Informix数据备份技巧
- · Informix 4GL写的转换成大写金额字串的函数
- · 一个批量删除临时表的sh用于informix
- · 影响CPU使用率的配置参数和环境变量
- · Ontape -r 恢复总结(1)
- · 用shell实现Informix的性能监控
- · Windows xp下的Informix connect配置方法
- · OnLine非正常结束后处理办法
- · OnLine进程被挂起后处理办法
- · Informix动态服务器表分片策略的计划和调整
- · 备份Informix-Online数据库三法
- · datetime类型简介
- · 配置Informix动态服务器中CPU虚处理器
- · online的备份详解
- · 配置和实现Informix ON-Bar的备份解决方案
- · Informix sysmaster表详解
- · JDBC连接Informix IDS
- · Sybase数据库死锁对策
- · SYBASE ASA数据库恢复方法
- · Sybase数据库简介(1)
- · SYBASE零售行业解决方案
- · SYBASE数据库日志详解
- · SQL Server 的通用分页显示存储过程
- · Oracle数据库中索引的维护(1)
- · Oracle9i的索引监视及注意事项
- · Oracle 的位图索引简述
- · 在ORACLE里按用户名重建索引的方法
- · Oracle数据库强制索引
- · 改善Oracle的索引
- · Oracle管理查询管用的sql语句
- · Oracle中的模糊查询
- · Oracle 中使用层次查询方便处理财务报表
- · 使用Oracle的Instr()与decode()函数进行多条件组合查询
- · MS SQL Server查询优化方法
- · Access使用查询
- · Access的跨库查询
- · Access 创建索引
- · 为数据库建立索引
- · 优化Microsoft Access提高速度
- · Sybase数据库的性能优化
- · 查询优化
- · 提高ORACLE数据库的查询统计速度
- · ORACLE SQL性能优化 (上)(1)
- · ORACLE SQL性能优化 (下)(1)
- · SQL Server性能分析参数
- · SQL Server 性能优化工具(1)
- · 使用索引调节向导调整应用程序的性能
- · 优化SQL Server服务器内存配置的策略
- · 影响SQL server性能的关键三个方面
- · MySQL性能优化的参数简介
- · MYSQL数据库的查询优化技术
- · 确定Oracle数据库表中重复的记录
- · Access数据库与SQLserver2000的数据互导
- · SQLServer和Access、Excel数据传输简单总结
- · SQL Server到Oracle连接服务器的实现
- · 使用SQL Server数据转换服务升迁Access数据库(1)
- · 将Access移植到SQL Server
- · 联系使用Excel和SQL(1)
- · 避免Access和SQL Server的空值冲突
- · 保护SQL Server:为安全性而安装
- · SQL Server 2000 客户端实用程序
- · 执行一个安全的SQL Server安装
- · SQL Server安全-加密术和SQL注入攻击
- · 指定文件位置优化性能
- · SQL Server备份的三个恢复模型
- · SQL Server的空值处理策略
- · 两个SQL Server维护技巧
- · 用SQL Server保持会话状态
- · 使用SQL服务器内置的错误寻找器寻找和剖析错误
- · 安装SQL Server 2000
- · SQL Server 2000 与 SQL Server 7.0 版兼容性问题
- · MS SQL Server 7.0 性能优化指南
- · MS SQL Server 7.0 的 SAP R/3 性能优化指南
- · 基于WEB的数据库查询
- · Sql Server全文搜索中文出错的问题
- · SQL Server7移动数据的6种方法

