1.RPM目录结构
- rpmbuild
- SOURCES 源码、图标等文件
- SPECS 用于管理rpm制作进程的spec文件
- BUILD 解压后的文件
- RPMS 由rpmbuild制作好的二进制包
- SRPMS 由rpmbuild制作好的源码包
2.spec文件综述
- spec文件有什么用?
- spec文件有两个用途:构建和打包。构建即将源码转换为构建工件(java构建工具一般为Ant, Maven, Gradle; C语言构建工具为makefile)。打包即确定需要安装在目标机器上的构建产物。
注意:#
字符表示注释,但需要避免注释宏(以 %
开头),因为它们会首先被替换展开。使用 %%
注释宏。另外,还要避免在脚本命令的相同行中使用行内注释。
%{name}
,%{version}
和 %{release}
代表 Name, Version 和 Release 这三个标签。只要更改标签,宏就会使用新值。
spec文件主要标签:
Name: 软件包名,应与 SPEC 文件名一致。
Version: 版本号。
-
Release: 发行编号,初始值为 1%{?dist} ,每次制作新包时,递增该数字。
- 什么是 1%{?dist} : 如果%{dist}未定义返回1,否则返回1%{dist},
- 用法:
- if判断:
如果if 0%{?flag}; then foo fi
%{flag}
被定义了,条件语句为:0%{flag}
,执行if block; 反之,条件语句为:0, 不执行if block。
注意:%{?flag}
前必须加0,否则如果%{?flag}
未定义,if语句停止执行并退出。 -
%{?flag: ...}
:如果%{flag}
被定义,则展开"..."部分;
- if判断:
Patch0: 用于源码的补丁名称。如果需要在源码包解压后对一些代码做修改,应该修改代码并使用
diff
命令生成 patch 文件,然后放在~/rpmbuild/SOURCES
目录下。一个 Patch 应该只做一种修改,所以可能会包含多个 patch 文件。BuildRoot: 在
%install
阶段(%build
阶段后)文件需要安装至此位置。默认情况下,根目录为%{_topdir}/BUILDROOT/
。%description: 程序的详细/多行描述。每行必须小于等于 80 个字符。
%prep: 打包准备阶段执行一些命令(如,解压源码包,打补丁等),以便开始编译。
%build: 包含构建阶段执行的命令,构建完成后便开始后续安装。
-
%install: 包含安装阶段执行的命令。命令将文件从
%{_builddir}
目录安装至%{buildroot}
目录。可以使用$RPM_BUILD_ROOT
代替%{buildroot}
,两者都可以使用。术语:
-
%{_builddir}
(即"build目录"),与%{buildroot}
(即"build root目录")是不同的目录。在%{_builddir}
中进行编译,并将需要打包的文件从%{_builddir}
中复制到%{buildroot}
中。 -
%install
阶段的命令不会在用户安装RPM包时执行,此阶段只在打包时执行。
一般在%install
阶段执行make install
之类的命令。%make_install
命令等同于DESTDIR=%{buildroot}
,该命令会将文件安装到%{buildroot}
目录中。如果程序不支持DESTDIR
,可手动执行安装:需要在%{buildroot}
下创建必要的目录,并从%{_builddir
}复制文件至%{buildroot}
目录。
-
%clean: 清理安装目录。一般只包含:
rm -rf %{buildroot}
-
%files:
%files
指令列出需要安装的文件和目录。-
%defattr
用于设置默认文件权限,一般在%files
开头设置。格式为:%defattr(<文件权限>, <用户>, <用户组>, <目录权限>)
常规用法为:
%defattr(-, user, group, -)
必须在
%files
部分列出该软件所拥有的所有文件,注意不要使用如 /usr/bin/ 的硬编码,尽量使用宏代替目录名。如果路径以"/"开头(或从宏扩展),则认为文件在%{buildroot}目录中。否则,默认文件在当前目录中。
【问题:如果软件包仅安装一个文件,那么该文件会安装在哪里?】
【答:必须有一个路径】若要软件包不受上游改动影响,可使用通配符匹配所有文件。
【问题:不受上游改动影响是什么意思?】
注意:%{somedir}/*
不会声明软件包拥有%{somedir}
目录,而只包含其中的文件。如果列出一个目录,则该软件包拥有整个目录,以及该目录内所有的文件和子目录,因此要小心处理可能和其他软件共享的目录。-
如果存在以下情况,可能引发错误:
- 通配符未匹配任何文件或目录
- 文件或目录被多次列出
- %{buildroot}中有文件未列出(空文件目录不会报错)
- 使用通配符来列出全部文件时,可使用 %exclude 来排除文件。注意如果未匹配到任何文件也会造成失败。
-
3. %files指令
%files列表包括多种指令,主要用于:
- 识别文档和配置文件
- 确定文件有正确的权限和拥有组
- 设置哪些文件需要在打包验证时进行校验
- 精简语法
两个%files指令可同时作用于同一个文件,例如:%foo %bar baz
I 文件相关指令
RPM需要根据文件类型分别处理不同类型的文件,然而,rpm并没有自动识别文件类型的功能。因此,需要由打包者适当的对不同类型的文件进行标识。
注意:并非所有文件都需要被标识,在大多数包中,大多数文件都不需要被标识。
-
%doc
指令:
rpm会跟踪其数据库中的文档文件,以便用户查找已安装包信息。
此外,rpm可在安装期间创建包的文档目录,并将文档复制其中。添加该步骤方法如下:
build期间,README 文件位于顶级目录;软件包install完成后,rpm将在软件包同名的文档目录(即<software>-<version>-<release>)创建目录,并将 README 文件拷贝其中。新创建的目录和 README 文件将在rpm数据库被作为文档进行标识。默认的文档目录是%doc README %doc /usr/local/foo/README
/usr/doc
,可在rpmrc文件中更改。 -
%config
指令:用于标识文件作为配置文件。(只能一个配置文件) -
%attr
指令:用于设置文件权限。例:%attr(<file_mode>, <user>, <group>) filename
-
%defattr
指令: 用于设置文件默认权限,一般写在%files
头部。例:%defattr(<file_mode>, <user>, <group>, <dir_mode>)
-
%ghost
to be continue... -
%verify
to be continue...
II 目录相关指令
-
%docdir
指令:向文档目录列表添加目录。rpm的%docdir
列表默的认目录有:/usr/doc
,/usr/info
,/usr/main
。例:%docfir /usr/test ,
任何
/usr/test
目录下的文件都会自动被标识为文档文件。 %dir
指令:之前提到,如果在%files
下列出文件夹,则该文件夹下的所有文件或子文件夹都会被打包到软件包中。%dir
指令可设置rpm只打包自身,而忽略其中的文件或子文件夹。-f <file>
:从<file>中读取%files
列表。
Tips
- shell脚本错误
Syntax error near unexpected token `fi`
:缺少then
- spec文件内的标签必须有值,标签前不能有空格;
- spec文件必须要有
%description
- spec文件的当前目录为
/BUILD
-
%{buildroot}
是%install
阶段,/BUILDROOT
下自动创建的子目录/name-version-release
-
%{buildroot}
内的所有文件都必须在%files
中列出,空目录可不必列出 -
/BUILDROOT
目录会在%install
阶段自动创建
代码参考
package.sh:
CUR_DIR=$(cd `dirname $0`; pwd)
if [ -d ${CUR_DIR}/rpmbuild ]; then
rm -rf ${CUR_DIR}/rpmbuild
fi
mkdir -p ${CUR_DIR}/rpmbuild
mkdir -p ${CUR_DIR}/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
cp ${CUR_DIR}/*.spec ${CUR_DIR}/rpmbuild/SPECS/
rpmbuild --define "_topdir ${CUR_DIR}/rpmbuild" -bb ${CUR_DIR}/rpmbuild/SPECS/web.spec
web.spec:
Name: web
Version: 1.0.0
Release: 1%{?dist}
Summary: test
License: GPL
URL: http://gitlabsec.huawei.com/h00416865/web
%description
%define PROJECT_ROOT %{_builddir}/../../..
%prep
%build
echo "begin to mvn install..."
cd %{PROJECT_ROOT}/web_console
mvn clean install
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/opt/weiee
mkdir -p %{_builddir}/webapp
cp -r %{PROJECT_ROOT}/web_console/target/*.war %{_builddir}
unzip -oq %{_builddir}/*.war -d %{_builddir}/webapp
cp -r %{_builddir}/webapp %{buildroot}/opt/weiee
%files
%defattr(-,root,root,-)
/opt/weiee/
%post
%clean
rm -rf %{buildroot}
%changelog
参考文章
http://ftp.rpm.org/max-rpm/index.html
How to create an RPM package/zh-cn