当前位置:Linux教程 - Linux综合 - 精通RPM之--制作篇(中)

精通RPM之--制作篇(中)

  一个RPM的软件包描述文件,可以仅生成一个父包或一个子包,也可以生成一个父包和多个子包。通过设定子包选项,可以使生成的子包采用"软件名-子包名" 的标准命名,也可使生成的子包采用自己的名字。一个子包,通常是按照其包含的文件的用途或类型来归并文件进而打成包裹的。象前面的LZE描述文件很简单, 它将所有文件都包含进了父包中。我们也可以将文件分类作成子软件包,如可分成执行程序子包(lze-bin),配置文件子包(lze-config)和说明文档包(lze-doc)。我们还可以只分出一个配置文件子包(lze-config),其余文件均打入父包中(lze)。通过这样详细地分类,有助于用户管理软件包,避免安装多余的东西,同时也有助于升级。 要想创建子软件包,必须描述以下内容: 1. %package : 用此段创建一个子包。其名字由子包选项控制。子包选项为"[-n] 子包名",不选-n时,生成的子包文件为"软件名-子包名-版本号-释出号.体系.rpm";选-n时,生成的子包文件为"子包名-版本号-释出号.体系.rpm"。其应用格式为: %package 子包选项 2. Summary 此域必须在%package下面,它定义子包功能简介(一句话说明)。格式为: Summary : 子包简介 3. Group 此域必须在%package下面,其定义子包所属软件类别(软件类别请参见<<精通RPM之五--查询篇>>)。格式为: Group : 软件类别 4. %description : 此描述段的内容是较为详细的子包功能介绍,介绍为文本形式,格式不作要求,可任意换行或分段。格式为: %description 子包选项 ...介绍子包功能的内容... 5. %files : 此文件段的内容是子包所要包含的文件列表。文件列表中,一个文件占用一行,还可使用多种文件修饰符。(详见<<精通RPM之七--制作篇(上)>>) 段名应用格式为: %files 子包选项 [-f 文件名] 注意: 上述%description与%files段所用的子包选项形式,必须与%package所用的子包选项形式一致,否则的话,它们定义的不是同一个子包,RPM检查时将报错退出。如定义过%package name后,描述段名须用%description name,文件段名须用%files name方可。而用%description -n name则不行,%files -n name也不行。 子软件包也可使用%pre,%post,%preun,%postun,%triggerin,%triggerun和%triggerpostun等七个可选的功能段,因为它们都可使用子包选项。当使用子包选项时,它们的段内容就是用来管理子软件包的脚本程序。要注意的是,这些段使用的子包选项形式也必须与%package段使用的子包选项形式一致。 条件语句的使用 在软件包描述文件中,可以灵活地使用条件语句,位置不限制。这些语句,用于当前体系与操作系统的判断,当条件为真或为假时,RPM均会引用其相应的描述内容。 条件语句有两种格式: 1. {%ifarch,%ifnarch,%ifos,%ifnos} 值1 [值2] ... 描述内容 %endif 注: {}所括内容必选其中之一,[]所括为可选项,各个值之间以空格分隔,%endif表示条件语句结束。 此语句的含义是: 1) 使用%ifarch时,表示如果当前体系为值1或值2...,则引用描述内容。 2) 使用%ifnarch时,表示如果当前体系不为值1或值2...,则引用描述内容。 3) 使用%ifos时,表示如果当前操作系统为值1或值2...,则引用描述内容。 4) 使用%ifnos时,表示如果当前操作系统不为值1或值2...,则引用描述内容。 如果想在LZE包描述文件的文件段增加只适用于sparc体系的文件/etc/sparc.lze和 /etc/sparc.ime,则可在文件段内加入如下语句: %ifarch sparc /etc/sparc.lze /etc/sparc.ime %endif 这样做以后,如果当前体系为sparc,则RPM在打包时会加入这两个文件。 2. {%ifarch,%ifnarch,%ifos,%ifnos} 值1 [值2] ... 描述内容1 %else 描述内容2 %endif 注: {}所括内容必选其中之一,[]所括为可选项,各个值之间以空格分隔,%else表示另外一种情况,%endif表示条件语句结束。 此语句的含义是: 1) 使用%ifarch时,表示如果当前体系为值1或值2...,则引用描述内容1,否则引用描述 内容2。 2) 使用%ifnarch时,表示如果当前体系不为值1或值2...,则引用描述内容1,否则引用描述内容2。 3) 使用%ifos时,表示如果当前操作系统为值1或值2...,则引用描述内容1,否则引用描述内容2。 4) 使用%ifnos时,表示如果当前操作系统不为值1或值2...,则引用描述内容1,否则引用描述内容2。 如果想根据当前操作系统来确定LZE包的名字,则可在描述文件头使用如下语句定义Name域:
[1] [2] [3] [4] [5] 下一页 

%ifos Linux Name : lzeforlinux %else %ifos aix Name : lzeforaix %else Name : lzeforothersys %endif %endif 本例中使用了嵌套的条件语句,它说明的情况是:如果操作系统为linux,则软件名定为lzeforlinux,如果操作系统为aix,则软件名定为lzeforaix,如果不是上述两个操作系统,则将软件名定为lzeforothersys。 如何在描述文件中使用宏(macros) 1. 宏是什么? 学过C语言的人都知道,宏是用来实现文本替换的,即定义了宏名与宏体后,文件中所有有宏名的地方在预处理时将被宏体替换掉。使用宏可以减少文字的录入量,方便了编程人员。在软件包描述文件中使用宏,也是基于这个目的,只不过这个宏与C语言的宏定义格式不同而已。 2. 宏的定义 描述文件中宏的定义格式为: %define [(opts)] 注: []所括为可选项。为宏名,宏名可用字母,数字和下划线(_),并且其长度最小为3。opts为一个或多个选项,各选项之间无分隔,选项采用getopt函数要求的形式,即选项为单个字符,如果某个选项需要参数,则需要在这个选项后加个冒号(:)。为宏体,它周围的空字符将被删掉。宏体的内容须在一行上。 如没有选项的宏定义: %define aaa "This is my software" 如仅有一个选项的宏定义: %define xxx(p:Z) echo %{-p:%{-p*}} %{-Z} 3. 宏的使用 宏的使用格式为: % [opt1] [opt2]... [arg1] [arg2]... 或 %{} [opt1] [opt2]... [arg1] [arg2]... 注: []所括为可选项;为所应用的宏名,宏名可以用{}括住;opt1,opt2...为选项,均须以减号(-)开头,并且如果选项需要参数,则必须提供一个选项参数;arg1,arg2...则为宏的参数。 如上面定义的xxx宏,可这样使用: %xxx -p zhsoft hello world< br> 例子中,xxx宏使用一个选项-p,zhsoft为-p选项的参数,还有两个宏的参数hello和world。 注意: 宏使用时最好多换一行(即宏下面空一行),因为宏在扩展后并不换行,这样如果不多换行,则下面一行若有内容的话,宏扩展后的内容将和下面一行的内容合并在一起,极容易出现错误。这也是笔者发现RPM宏的问题之一。还有一个问题,如果注释行上存在宏,则这个宏也将扩展,错矣!因为注释本来就是要忽略掉的,有宏也不必再扩展了。这两个问题都需要引起RPM开发者的注意,并切实加以解决。 4. 宏体专用的宏 宏体中可使用如下专用的宏:(类似SHELL形式的宏) 1) %0 : 表示所在宏的宏名; 2) %* : 表示宏的所有参数; 3) %# : 表示宏的参数个数; 4) %{-f} : 表示如果宏使用了-f选项,则它表示-f及其选项参数; 5) %{-f*} : 表示如果宏使用了-f选项,则它表示-f所带的参数; 6) %{-f:X} : 表示如果宏使用了-f选项,则它表示X; 7) %{!-f:Y} : 表示如果宏没有使用-f选项,则它表示Y; 8) %1,%2,... : 表示宏的参数1,参数2... 如,上例中xxx宏执行时,若宏体中有上述专用的宏,则专用宏将会扩展为: 1) %0扩展为xxx; 2) %*扩展为hello world; 3) %#扩展为2; 4) %{-p}扩展为-p zhsoft; 5) %{-p*}扩展为zhsoft; 6) %{-p:good}扩展为good; 7) %{!-Z:bad}扩展为bad; (因为xxx宏未使用-Z选项) 8) %1为hello,%2为world,没有其它参数。 5. 系统内置的宏 系统内置的宏可分如下三类: 5.1 定义类 1) %define ... : 定义一个宏;(原来,%define也是一个宏啊) 2) %undefine ... : 取消一个宏;(宏取消后,此语句下面的描述文件就不能再使用这个宏了,即使使用,该宏也不会被扩展了) 5.2 调试类 1) %trace : 打印宏扩展前后的调试信息; 2) %dump : 打印活动的宏(宏名及宏体); 3) %{echo:...} : 打印...到标准错误设备; 4) %{warn:...} : 打印...到标准错误设备; 5) %{error:...} : 打印...到标准错误设备,并且返回BADSPEC值; 5.3 特殊类 这类宏的默认值通常放在/usr/lib/rpm/macros文件中,用户通过编辑自己主目录(HOME)下的.rpmmacros文件(~/.rpmmacros),可重定义这类宏,改变其默认值,以供RPM在软件包制作,安装及查询时使用自己的定义。 这类宏的定义格式为:
上一页 [1] [2] [3] [4] [5] 下一页 

% 注: 为宏名,为宏体。 1) %packager,%vendor,%distribution : 这三个宏用于定义描述文件中Packager,Vendor,Distribution三个可选域的默认的域值,即如果这三个域中有哪个未在描述文件中定义,且其相对应的宏有定义,则RPM会采用其对应的宏的宏体。 如我的~/.rpmmacros文件中有这样三行: %vendor 纵横软件制作中心 %packager 雨亦奇 %distribution 小赵'2001 这样,软件包描述文件中再也不用定义那三个域了,由此制作出来的软件包在查询时,其打包者(Packager),销售商(Vendor)及发行版(Distribution)均自动搞定了,一劳永逸。 2) %buildroot,%_provides : 这两个宏定义软件包建包时用的根目录及软件包所提供的功能。它们在打包时不会象 上面那三个宏一样主动被RPM采用,而是必须在描述文件中写那么几行。即: %vendor 纵横软件制作中心 %packager 雨亦奇 %distribution 小赵'2001 Buildroot : %buildroot Provides : %_provides 3) %_topdir,%_builddir,%_rpmdir,%_sourcedir,%_specdir,%_srcrpmdir : 这六个宏都是RPM制作软件包时要用的,它们在/usr/lib/rpm/macros文件中的默认值为: %_topdir %{_usrsrc}/dist %_builddir %{_topdir}/BUILD %_rpmdir %{_topdir}/RPMS %_sourcedir %{_topdir}/SOURCES %_specdir %{_topdir}/SPECS %_srcrpmdir %{_topdir}/SRPMS %_topdir宏定义的是RPM制作软件包时所用目录的顶层目录,一般为/usr/src/dist(%{_usrsrc} 宏的值为/usr/src)。在顶层目录下面,又有五个子目录: * 编译连接源程序时用的目录,由%_builddir宏定义,常用BUILD; * 生成的RPM执行程序包存放的目录,由%_rpmdir宏定义,常用RPMS; * 软件源程序存放的目录,由%_sourcedir宏定义,常用SOURCES; * 软件包描述文件存放的目录,由%_specdir宏定义,常用SPECS; * 生成的RPM源程序包存放的目录,由%_srcrpmdir宏定义,常用SRPMS。 由于宏的递归特性,我们可以通过只定义%_topdir宏来达到改变%_builddir等五个宏的目的。 (注意:%_builddir等五个宏的宏体如无特殊要求,尽量不要改变,它们是标准的定义,应该采用)这对于普通用户来说,意义非常重大。因为RPM默认的顶层目录/usr/src/dist并不是每个用户都可以随便使用的,普通用户更想在自己所有的目录下用RPM来制作些软件包。我也有这种想法,所以在~/.rpmmacros文件里加上这么一行: %_topdir /usr/zzz/rpm 同时,在此宏定义的目录下面建立了RPM所需的子目录,使用命令为: $ cd /usr/zzz $ mkdir -p rpm/{BUILD,RPMS/i386,SOURCES,SPECS,SRPMS} $ 命令中的i386是RPM默认的体系名,RPM生成的执行程序包是存放在“RPMS/体系名”目录下面的。这么做以后,我就可以在自己的目录下制作RPM软件包了,象超级用户一样自由。 4)%_excludedocs,%_FTPport,%_ftpproxy,%_httpport,%_httpproxy,%_netsharepath : 这六个宏对RPM软件包的安装和查询起作用。 * %_excludedocs : 如果其值定义为1,则RPM安装软件包时,对说明文档的默认作法是不安装; * %_ftpport : 此宏用于定义RPM默认的FTP端口; * %_ftpproxy : 此宏用于定义RPM默认的FTP代理服务器; * %_httpport : 此宏用于定义RPM默认的HTTP端口; * %_httpproxy : 此宏用于定义RPM默认的HTTP代理服务器; * %_netsharepath : 此宏用于定义RPM默认的网络共享目录,适用于网络文件系统(NFS)。 6. 一种特殊的宏 这种宏的用法是: %(SHELL命令及其参数) 它的结果是取指定的SHELL命令的标准输出的结果作为描述文件内容的一部分。如软件包描述文件的某个部分需要加上当前日期,则可以用: %(date +%Y-%m-%d) 执行后,该宏将扩展为类似2001-10-31的日期数据。用户不妨在自己的描述文件的预处理段(%prep)内加上这么两行试试:
上一页 [1] [2] [3] [4] [5] 下一页 

%(date +%Y-%m-%d) exit 1 注: exit 1用于中止RPM的执行。 描述文件模板 以下所有描述文件模板均以LZE软件包制作为例,以源程序现场编译后产生的文件为准生成软件包。描述文件中一般只描述必要的部分。另外,如果文件段的所有文件已存在于系统中,并且想直接利用打包,则可以去掉Source域,去掉RPM建包用功能段(%prep,%build,%install,% clean)。 1. 只有父包,没有任何子包: 此描述文件见<<精通RPM之七--制作篇(上)>>。此文件中还可以去掉几个可选的功能段, 如%pre,%post,%preun,%postun,%triggerin,%triggerun,%triggerpostun。这几个段在此文件中无实质用途,执行时仅显示RPM开始执行某个脚本程序的信息。此描述文件仅生成软件包lze-6.0-2.i386.rpm(父包)。 2. 有父包,也有子包: 描述文件如下: 1 # 文件名称: lze-6.0-2.spec1 2 # 文件功能: lze软件包描述信息 3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利 4 # 修改时间: 2001.10.31 5 6 Name: lze 7 Version: 6.0 8 Release: 2 9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用) 10 Group: Applications/Editors 11 License: Share 12 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz 13 14 %description 15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗 16 口中英文多功能编辑器。 17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十 18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特 19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎 20 添翼。10.即时翻译,按到即译。 21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。 22 它将在工作中助您一臂之力,轻松上阵,游刃有余! 23 24 %prep 25 echo "预处理脚本程序(prep)开始执行" 26 %setup 27 28 %build 29 echo "编译连接脚本程序(build)开始执行" 30 make 31 32 %install 33 echo "安装脚本程序(install)开始执行" 34 make install 35 36 # 配置文件子包 37 %package config 38 summary : 小赵编辑器LZE的配置文件 39 group : Applications/Editors 40 41 %description config 42 小赵编辑器用配置文件包括功能键定义文件与 43 输入法控制文件,用户可根据实际情况加以修改。 44 45 %files config 46 %config /etc/funkey.def 47 %config /etc/inputme.def 48 49 # 说明文档子包 50 %package doc 51 summary : 小赵编辑器LZE的说明文档 52 group : Applications/Editors 53 54 %description doc 55 小赵编辑器说明文档,详细介绍了该编辑器的 56 命令行用法及内置的各项菜单的功能与操作,对用 57 户熟悉小赵编辑器有很大作用。 58 59 %files doc 60 %doc /usr/doc/lze-6.0/README 61 %doc /usr/doc/lze-6.0/LICENSE 62 63 # 父包文件段 64 %files 65 %defattr (-,root,root) 66 /usr/bin/lze 67 /usr/bin/lzeime.py 68 /usr/bin/lzeime.wb 69 /etc/wbzc.dat 70 此描述文件生成软件包有:lze-6.0-2.i386.rpm(父包),lze-config-6.0-2.i386.rpm(配置文件子包)和lze-doc-6.0-2.i386.rpm(说明文档子包)。 3. 没有父包,只有子包: 没有父包,意味着描述文件中可以没有父包的文件段(%files),请看下面的描述文件: 1 # 文件名称: lze-6.0-2.spec2 2 # 文件功能: lze软件包描述信息 3 # 文件作者: 纵横软件制作中心雨亦奇 国防大学研究生二队赵建利 4 # 修改时间: 2001.10.31 5 6 Name: lze 7 Version: 6.0
上一页 [1] [2] [3] [4] [5] 下一页 

8 Release: 2 9 Summary: 小赵全屏幕中英文多窗口多功能编辑器(LINUX/UNIX系统适用) 10 Group: Applications/Editors 11 License: Share 12 Source: http://zhsoft.myetang.com/lze-6.0-2.src.tgz 13 14 %description 15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗 16 口中英文多功能编辑器。 17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十 18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特 19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎 20 添翼。10.即时翻译,按到即译。 21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。 22 它将在工作中助您一臂之力,轻松上阵,游刃有余! 23 24 %prep 25 echo "预处理脚本程序(prep)开始执行" 26 %setup 27 28 %build 29 echo "编译连接脚本程序(build)开始执行" 30 make 31 32 %install 33 echo "安装脚本程序(install)开始执行" 34 make install 35 36 # 配置文件子包 37 %package config 38 summary : 小赵编辑器LZE的配置文件 39 group : Applications/Editors 40 41 %description config 42 小赵编辑器用配置文件包括功能键定义文件与 43 输入法控制文件,用户可根据实际情况加以修改。 44 45 %files config 46 %config /etc/funkey.def 47 %config /etc/inputme.def 48 49 # 说明文档子包 50 %package doc 51 summary : 小赵编辑器LZE的说明文档 52 group : Applications/Editors 53 54 %description doc 55 小赵编辑器说明文档,详细介绍了该编辑器的 56 命令行用法及内置的各项菜单的功能与操作,对用 57 户熟悉小赵编辑器有很大作用。 58 59 %files doc 60 %doc /usr/doc/lze-6.0/README 61 %doc /usr/doc/lze-6.0/LICENSE 62 63 # 执行程序子包 64 %package bin 65 summary : 小赵编辑器LZE的执行程序 66 group : Applications/Editors 67 68 %description bin 69 小赵编辑器执行程序为lze,五笔输入法服务器执行程序 70 为lzeime.wb,拼音输入法服务器执行程序为lzeime.py。 71 72 %files bin 73 %defattr (-,root,root) 74 /usr/bin/lze 75 /usr/bin/lzeime.py 76 /usr/bin/lzeime.wb 77 /etc/wbzc.dat 78 此描述文件生成三个软件包:lze-config-6.0-2.i386.rpm(配置文件子包),lze-doc-6.0-2.i386.rpm(说明文档子包),lze-bin-6.0-2.i386.rpm(执行程序子包)。

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4] [5] 

38 summary : 小赵编辑器LZE的配置文件 39 group : Applications/Editors 40 41 %description config 42 小赵编辑器用配置文件包括功能键定义文件与 43 输入法控制文件,用户可根据实际情况加以修改。 44 45 %files config 46 %config /etc/funkey.def 47 %config /etc/inputme.def 48 49 # 说明文档子包 50 %package doc 51 summary : 小赵编辑器LZE的说明文档 52 group : Applications/Editors 53 54 %description doc 55 小赵编辑器说明文档,详细介绍了该编辑器的 56 命令行用法及内置的各项菜单的功能与操作,对用 57 户熟悉小赵编辑器有很大作用。 58 59 %files doc 60 %doc /usr/doc/lze-6.0/README 61 %doc /usr/doc/lze-6.0/LICENSE 62 63 # 执行程序子包 64 %package bin 65 summary : 小赵编辑器LZE的执行程序 66 group : Applications/Editors 67 68 %description bin 69 小赵编辑器执行程序为lze,五笔输入法服务器执行程序 70 为lzeime.wb,拼音输入法服务器执行程序为lzeime.py。 71 72 %files bin 73 %defattr (-,root,root) 74 /usr/bin/lze 75 /usr/bin/lzeime.py 76 /usr/bin/lzeime.wb 77 /etc/wbzc.dat 78 此描述文件生成三个软件包:lze-config-6.0-2.i386.rpm(配置文件子包),lze-doc-6.0-2.i386.rpm(说明文档子包),lze-bin-6.0-2.i386.rpm(执行程序子包)。

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4] [5] [6] 

13 14 %description 15 小赵编辑器,是为使用SCO UNIX,LINUX多用户系统的广大用户专门设计的全屏幕多窗 16 口中英文多功能编辑器。 17 它主要有以下十大特点:1.全屏幕菜单操作。2.显示方式多样。3.块操作丰富。4.十 18 字制表功能强大。5.多窗口操作灵活自如。6.文件操作功能齐全。7.解释输出功能独具特 19 色。8.自带中文输入法(增强五笔和增强拼音),实用方便。9.十六进制编辑功能,如虎 20 添翼。10.即时翻译,按到即译。 21 总之,小赵编辑器会成为您在UNIX,LINUX系统上编制程序和书写一般性文稿的好帮手。 22 它将在工作中助您一臂之力,轻松上阵,游刃有余! 23 24 %prep 25 echo "预处理脚本程序(prep)开始执行" 26 %setup 27 28 %build 29 echo "编译连接脚本程序(build)开始执行" 30 make 31 32 %install 33 echo "安装脚本程序(install)开始执行" 34 make install 35 36 # 配置文件子包 37 %package config 38 summary : 小赵编辑器LZE的配置文件 39 group : Applications/Editors 40 41 %description config 42 小赵编辑器用配置文件包括功能键定义文件与 43 输入法控制文件,用户可根据实际情况加以修改。 44 45 %files config 46 %config /etc/funkey.def 47 %config /etc/inputme.def 48 49 # 说明文档子包 50 %package doc 51 summary : 小赵编辑器LZE的说明文档 52 group : Applications/Editors 53 54 %description doc 55 小赵编辑器说明文档,详细介绍了该编辑器的 56 命令行用法及内置的各项菜单的功能与操作,对用 57 户熟悉小赵编辑器有很大作用。 58 59 %files doc 60 %doc /usr/doc/lze-6.0/README 61 %doc /usr/doc/lze-6.0/LICENSE 62 63 # 执行程序子包 64 %package bin 65 summary : 小赵编辑器LZE的执行程序 66 group : Applications/Editors 67 68 %description bin 69 小赵编辑器执行程序为lze,五笔输入法服务器执行程序 70 为lzeime.wb,拼音输入法服务器执行程序为lzeime.py。 71 72 %files bin 73 %defattr (-,root,root) 74 /usr/bin/lze 75 /usr/bin/lzeime.py 76 /usr/bin/lzeime.wb 77 /etc/wbzc.dat 78 此描述文件生成三个软件包:lze-config-6.0-2.i386.rpm(配置文件子包),lze-doc-6.0-2.i386.rpm(说明文档子包),lze-bin-6.0-2.i386.rpm(执行程序子包)。

(出处:http://www.sheup.com/)


上一页 [1] [2] [3] [4] [5] [6] [7]