2021-01-08


由于一些原因,学习了一下关于rpm的相关东西,简单的记录一下,初次了解,只是很浅显的东西,如果需要深入了解,建议去官网搜相关文档学习。

 

1.搭建rpm编包环境

在编rpm包之前需要安装一些工具包,可以直接通过Yum安装

yum -y install rpmdevtools

安装好工具包之后,可以手动建立主目录rpmbuild和次级目录BUILD、BUILDROOT、SOURCES、SPECS、RPMS、SRPMS;也可以使用rpmdev-setuptree自动生成。

 

2.Rpm编包目录结构

上面已经提到,rpm的编包目录其实是有一个主目录和多个次级目录组成,下面简单介绍一下各次级目录的作用:

BUILD:用于放置原压缩文件解压后的所有文件;

BUILDROOT:用于模拟安装环境下的ROOT目录,举个例子:编好的rpm需要在一个环境下安装,模拟环境下的*/BUILDROOT/etc目录等价于安装环境下的/etc;

SOURCES:用于放置需要编译成rpm的源文件,源文件呈现压缩状态

SPECS:用于放置编包脚本文件*.spec文件

RPMS:放置编包完成的.rpm包

SRPMS:放置源码包

 

3.spec文件编写

.spec文件是编写每个rpm包必需要自己写的文件,它有自己的一套语法结构,下面详细的介绍一下.spec文件的编写。

.spec文件可以自动生成,也可以自己用vim编写,建议初次写用自动生成方法,

自动生成命令:rpmdev-newspec  *.spec

下面给出个字段的含义:

##定义宏,后面用%{_bpath}引用

fine _bpath /opt/product/bin

##软件包的名称,用%{name}引用

Name:product

##简要的描述产品信息

Summary:describe the production a little

##产品的版本号

Version:3.9.0

##产品序列号

Release:*********

##产品分组,通常都是用标准分组

Group:Applications/Production

##产品的授权方式

License:GPL

##源代码,通常是.tar.gz形式的压缩包

Source:%{name}-%{version}.tar.gz

##这是下面make install时是用的虚拟根目录,%{_tpmpath}是系统的宏

BuildRoot:%{_tmppath}/%{name}-%{version}-%{release}

##软件主页地址

URL:http://baidu.com/

##发行商的信息

Vendor:baidu

##产品发行版标识

Distribution:*********

##罗列安装包时需要的依赖包,注:单独一个一个列,如下

Requires:   gcc-c++

Requires:   systemd

##产品的详细说明

description:********

##打包者信息

Packager:user

--------------------------------------------------------

##打包前的预处理,写脚本语言,%setup是把SOURCES的源代码解压到BUILD中

*****************************************************************

%pre 和 %post 分别定义了RPM包在被安装前后的处理,%preun 和 %postun 则定义了在卸载前后的操作。它们都带有一个参数,具体参数含义如下:

 

Install

Upgrade

uninstall

%pretrans

$1 == 0

$1 == 0

(N/A)

%pre

$1 == 1

$1 == 2

(N/A)

%post

$1 == 1

$1 == 2

(N/A)

%preun

(N/A)

$1 == 1

$1 == 0

%postun

(N/A)

$1 == 1

$1 == 0

%posttrans

$1 == 0

$1 == 0

(N/A)

 

*****************************************************************

%prep

%setup -n %{name}-%{version}

##开始构建包,编译源代码

%build

make

##将编译好的产品安装到虚拟的根目录,通常先清理,在写安装脚本,此步是模拟执行一遍安装的全过程(实际就是拷贝各种文件),

##拷贝到虚拟目录下,在虚拟目录下建议和真实安装一模一样的目录结构(与%files有极大的关系)

%install

Make install PREFIX=%{prefix} DESTDIR=%{buildroot}

##删除编译过程中的中间文件、目录

%clean

rm -rf $RPM_BUILD_ROOT

##分别是rpm包安装前后、卸载前后执行的脚本

%pre

%post

%preun

%postun

##定义哪些文件、目录将被打进rpm包,并制定安装文件的属性,需要列出所有的,但是需要指明哪些是配置文件等

##如果列出的目录或者文件不存在则会报错

#所有的BUILDROOT下的目录、文件都需要在%file中声明

%files

%attr(644,root,root) %dir /etc/dt.d

%attr(644,root,root) %config(noreplace) /etc/dt.d/*

当.spce文件编写好之后,可以使用rpmbuild -ba *.spec进行编译;

注:通常情况下,.spec文件会和Makefile文件同时使用,.spec文件只是由简单的安装的命令构成,而Makefile充当大批量的脚本语句文件。

 

4.Makefile文件编写

4.1 概述

Makefile文件由一系列规则(rules)构成。每条规则的形式如下:

:

[tab]  

上面第一行冒号前面的部分,叫做"目标"(target),冒号后面的部分叫做"前置条件"(prerequisites);第二行必须由一个tab键起首,后面跟着"命令"(commands)。

"目标"是必需的,不可省略;"前置条件"和"命令"都是可选的,但是两者之中必须至少存在一个。

每条规则就明确两件事:构建目标的前置条件是什么,以及如何构建。下面就详细讲解,每条规则的这三个组成部分。

4.2 目标(target)

一个目标(target)就构成一条规则。目标通常是文件名,指明Make命令所要构建的对象 。目标可以是一个文件名,也可以是多个文件名,之间用空格分隔。

除了文件名,目标还可以是某个操作的名字,这称为"伪目标"(phony target)。

clean:

      rm *.o

上面代码的目标是clean,它不是文件名,而是一个操作的名字,属于"伪目标 ",作用是删除对象文件。

用法:make  clean

但是,如果当前目录中,正好有一个文件叫做clean,那么这个命令不会执行。因为Make发现clean文件已经存在,就认为没有必要重新构建了,就不会执行指定的rm命令。

为了避免这种情况,可以明确声明clean是"伪目标",写法如下。

.PHONY: clean

clean:

        rm *.o temp

声明clean是"伪目标"之后,make就不会去检查是否存在一个叫做clean的文件,而是每次运行都执行对应的命令。像.PHONY这样的内置目标名还有不少,可以查看手册。

如果Make命令运行时没有指定目标,默认会执行Makefile文件的第一个目标。

用法:make

上面代码执行Makefile文件的第一个目标。

4.3 前置条件(prerequisites)

前置条件通常是一组文件名,之间用空格分隔。它指定了"目标"是否重新构建的判断标准:只要有一个前置文件不存在,或者有过更新(前置文件的last-modification时间戳比目标的时间戳新),"目标"就需要重新构建。

result.txt: source.txt

    cp source.txt result.txt

上面代码中,构建 result.txt 的前置条件是 source.txt 。如果当前目录中,source.txt 已经存在,那么make result.txt可以正常运行,否则必须再写一条规则,来生成 source.txt 。

source.txt:

    echo "this is the source" > source.txt

上面代码中,source.txt后面没有前置条件,就意味着它跟其他文件都无关,只要这个文件还不存在,每次调用make source.txt,它都会生成。

$ make result.txt

$ make result.txt

上面命令连续执行两次make result.txt。第一次执行会先新建 source.txt,然后再新建 result.txt。第二次执行,Make发现 source.txt 没有变动(时间戳晚于 result.txt),就不会执行任何操作,result.txt 也不会重新生成。

如果需要生成多个文件,往往采用下面的写法。

source: file1 file2 file3

上面代码中,source 是一个伪目标,只有三个前置文件,没有任何对应的命令。

$ make source

执行make source命令后,就会一次性生成 file1,file2,file3 三个文件。这比下面的写法要方便很多。

$ make file1

$ make file2

$ make file3

4.4 命令(commands)

命令(commands)表示如何更新目标文件,由一行或多行的Shell命令组成。它是构建"目标"的具体指令,它的运行结果通常就是生成目标文件。

每行命令之前必须有一个tab键。如果想用其他键,可以用内置变量.RECIPEPREFIX声明。

.RECIPEPREFIX = >

all:

> echo Hello, world

上面代码用.RECIPEPREFIX指定,大于号(>)替代tab键。所以,每一行命令的起首变成了大于号,而不是tab键。

需要注意的是,每行命令在一个单独的shell中执行。这些Shell之间没有继承关系。

var-lost:

    export foo=bar

    echo "foo=[$$foo]"

上面代码执行后(make var-lost),取不到foo的值。因为两行命令在两个不同的进程执行。一个解决办法是将两行命令写在一行,中间用分号分隔。

var-kept:

    export foo=bar; echo "foo=[$$foo]"

另一个解决办法是在换行符前加反斜杠转义。

var-kept:

    export foo=bar; \

    echo "foo=[$$foo]"

最后一个方法是加上.ONESHELL:命令。

.ONESHELL:

var-kept:

    export foo=bar;

    echo "foo=[$$foo]"

注:详细的Makefile文件请参看文末的参考文献[2]

5.常用宏

一些常用autoconf的宏:

%{_sysconfdir}        /etc

%{_prefix}            /usr

%{_exec_prefix}       %{_prefix}

%{_bindir}            %{_exec_prefix}/bin

%{_libdir}            %{_exec_prefix}/%{_lib}

%{_libexecdir}        %{_exec_prefix}/libexec

%{_sbindir}           %{_exec_prefix}/sbin

%{_sharedstatedir}    /var/lib

%{_datarootdir}       %{_prefix}/share

%{_datadir}           %{_datarootdir}

%{_includedir}        %{_prefix}/include

%{_infodir}           /usr/share/info

%{_mandir}            /usr/share/man

%{_localstatedir}     /var

%{_initddir}          %{_sysconfdir}/rc.d/init.d

 

路径的其他宏和变量:

These macros should be used for paths that are not covered by the macros mimicking autoconf variables. The %{buildroot} macro or the $RPM_BUILD_ROOT variable is the directory that should be assumed to be the root file system when installing files. It is used as the value for the DESTDIR variable.

%{_var}               /var

%{_tmppath}           %{_var}/tmp

%{_usr}               /usr

%{_usrsrc}            %{_usr}/src

%{_lib}               lib (lib64 on 64bit multilib systems)

%{_docdir}            %{_datadir}/doc

%{buildroot}          %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch}

$RPM_BUILD_ROOT       %{buildroot

 

构建flags宏和变量:

These macros should be used as flags for the compiler or linker

%{__global_cflags}   -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4

%{optflags}          %{__global_cflags} -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables

$RPM_OPT_FLAGS       %{optflags}

 

RPM编包目录的宏:

The macros are usually used with rpmbuild --define to specify which directories rpmbuild should use, it is unusual to use them within SPEC files.

%{_topdir}            %{getenv:HOME}/rpmbuild

%{_builddir}          %{_topdir}/BUILD

%{_rpmdir}            %{_topdir}/RPMS

%{_sourcedir}         %{_topdir}/SOURCES

%{_specdir}           %{_topdir}/SPECS

%{_srcrpmdir}         %{_topdir}/SRPMS

%{_buildrootdir}      %{_topdir}/BUILDROOT

 

参考文献:  

[1].https://fedoraproject.org/wiki/Packaging:RPMMacros?rd=Packaging/RPMMacros#RPM_directory_macros

[2].https://www.kancloud.cn/kancloud/make-command/45593

[3].http://ftp.rpm.org/max-rpm

[4].http://ftp.rpm.org/max-rpm/

[5].http://rpm-guide.readthedocs.io

[6].http://www.rpm.org/wiki/Docs#PackagerDocumentation

[7].https://fedoraproject.org/wiki/How_to_create_an_RPM_package

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值