基本步骤包含如下:
- 依照rpmbuild规范创建目录结构
- 将源代码和附带文件放到目录中合适位置
- 创建spec文件
- 编译rpm
本文以编译swoole扩展为例说明。
建立目录结构
1 2 3 |
mkdir rpmbuild cd rpmbuild mkdir BUILD RPMS SOURCES SPECS SRPMS |
把下载的swoole源码swoole-src-1.8.6-stable.zip放到BUILD目录中。
创建SPEC文件
在SPECS目录中创建swoole.spec文件。在这个文件中已经生成了现有的模板,我们只需要在模板上修改就行。
1 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 |
Name: Version: Release: 1%{?dist} Summary: Group: License: URL: Source0: BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRequires: Requires: %description %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc %changelog |
一个spec文件可以分为几个”段”:定义段,描述段,预处理段,构建段,安装段和打包段等。 我们先来介绍下定义段。
- Name:软件包名称,这里相当于变量定义,当使用此变量时,可以使用%{name}
- Version:软件包版本号
- Release:编译RPM包时的版本号。可以看到在引用dist变量时,多了个’?’,这个意思时如果已经存在dist变量就是dist变量,否则以空值代替
- Summary: 软件包简单说明
- Group: 软件包分类
- License: 软件分发证书
- URL: 软件包官网
- Source0: 软件包源文件地址。这是地址默认在BUILD目录。这里的Source0相当于Source,有时候会有多个源文件,可以用Source0,Source1区分。
- BuildRoot:规定了rpm在什么地方找到编译好的二进制文件或其他需要安装的文件,并打包到.rpm文件中去。在编译过程中,这个目录会临时生成。
- BuildRequires,Requires:软件包依赖关系
重点介绍下Source0,这规定了源代码的名称或来源。在本例中,就是swoole-src-1.8.6-stable.zip。一般这样定义%{name}-%{version}.zip。在本例中,name可以对应swoole-src,version对应1.8.6-stable,但是这样会报错,version字段不支持,就改变了swoole-src-1.8.6-stable.zip变成swoole-1.8.6.zip。
%description
描述段,这里可以写rpm包的详细信息
预处理段
“%prep”代表预处理段开始。这个段的作用就是整理代码,比如解压缩源代码包,给源代码打补丁等。”%setup -q”是以静默方式解压源代码包,并生成到BUILD目录中。使用”rpmbuild -bp”可以查看预处理过程
构建段
在这里进行编译源代码。在”make三部曲”的过程中,这里实现”configure”和”make”过程。make命令后面出现了%{?_smp_mflags}变量,这代表了make的并行编译选项,不用随意更改。
安装段
这里与正常安装软件的方式不同,要求将软件安装到rpm指定的目录中。这就是使用DESTDIR=$RPM_BUILD_ROOT的原因。 $RPM_BUILD_ROOT变量实际上是”BuildRoot”标签的值。”DESTDIR”实际上是Makefile中的一个变量,代码将编译好的程序安装到什么什么位置。这与configure脚本中的”–prefix”选项不同,”DESTDIR”代表了更高层级的目录。假设DESTDIR值为”abcd”,”–prefix”的值是”efg”,软件最终的安装路径为”abcd/efg”。
打包段
实际上是要打包的文件列表。”%defattr”宏描述了各文件的默认权限,一共有四个参数,分别对应了文件权限,所属用户,所属组和目录权限。
需要注意的是,编写文件文件列表的时候,使用的路径是相对于BuildRoot的。当然在使用rpm实际安装时,是去掉BuildRoot的。所以在编译生成安装目录时,BuildRoot后面对应的是实际安装目录。
编译swoole
swoole是一个php扩展,我们在编译php扩展时,与正常的make三部曲不太一样。生成php扩展,一般需要四步:phpize,configure,make, make install。在make install过程中,会把编译好的so文件放到php对应的扩展目录中,在编译rpm过程中,并不需要这一步,我们需要把so文件编译到rpm中即可。
1 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 |
%define _topdir /home/dingjing/downloads/rpmbuild Name: swoole Version: 1.8.6 Release: 1%{?dist} Summary: A high performance framework Group: Development/Tools Prefix: /usr/lib64/php/modules License: Apache License Version 2.0 URL: http://www.swoole.com/ Source0: %{name}-%{version}.zip BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRequires: php-devel Requires: php-devel %description %prep %setup -q %build phpize %configure ./configure --prefix=%{prefix} make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{prefix}/ cp %{_topdir}/BUILD/%{name}-%{version}/modules/*.so $RPM_BUILD_ROOT%{prefix}/ # make install DESTDIR=$RPM_BUILD_ROOT %clean #rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{prefix}/*.so %doc %changelog |
%define _topdir /home/dingjing/downloads/rpmbuild 这里定义了我们的根目录。
我们重点关注下%install段。上面提到,我们并不需要实际的make install过程。我们最终的目的是把so文件放到php扩展目录中,在本例中就是/usr/lib64/php/modules。源码编译时在BUILD目录生成的,编译成功时会包含so文件。我们把so文件放到了$RPM_BUILD_ROOT%{prefix}下面。
在%files段中,rpm安装时,会执行这里的文件列表,把这里的文件列表安装到对应的目录中去。在实际的安装过程中会去掉$RPM_BUILD_ROOT。所以我们把Prefix定义成了/usr/lib64/php/modules。
在制作rpm报时,一定要清楚明白整个源码的编译过程,这样相应的安装路径也变得很清晰。
使用”rpmbuild -ba SPECS/swoole.spec”就可以生成rpm包了,包放到了RPMS目录下。通过”rpm -ivh”就可以安装了。
自定义操作
在包安装或者卸载的过程中,有时会自定义脚本去执行。有四个阶段可以设置执行自定义操作。安装包之前(%pre)或者之后(%post),卸载包之前(%preun)后者之后(%postun)。在我们的例子中,在安装swoole之后,会修改php.ini文件,添加swoole.so引用。这里我们只用到%post。读者可以自行实现卸载操作。
1 2 3 4 5 6 7 8 9 |
# %define phpini /home/admin/php-fpm/lib/php.ini 在定义段,定义了phpini变量 %post grep -q swoole %{phpini} if [ $? = 1 ] ;then echo "[swoole]" >> %{phpini} echo "extension=swoole.so" >> %{phpini} fi |