|
|
楼主 |
发表于 2025-1-8 11:29:15
|
显示全部楼层
5 S5 J: M5 F. i- U" F7 b
第 1 章 RPM 打包入门
6 N1 U! x. `' i! e6 S复制链接+ f% |4 M& Q% [, L' o- }
下面的部分介绍了 RPM 打包的概念及其主要优点。' }9 \+ C: b8 o9 z; U
- l: y$ Z! T1 \2 c' q( J# O1 S+ {
1.1. RPM 打包简介 - Y: ~7 J* C- m9 K0 G) T
复制链接4 \) d" y0 I' I' V
RPM 软件包管理器(RPM)是运行在 RHEL、CentOS 和 Fedora 上的软件包管理系统。您可以使用 RPM 为上述任何所述操作系统分发、管理和更新创建的软件。+ P/ c, \. _! W( b$ D: Z4 h
$ r2 ~ J3 I* W' h9 R8 T6 O9 J
1.2. RPM 优点 3 W" g3 d8 {4 H
复制链接0 m3 {1 \' {0 C" d0 ~
与传统存档文件中软件分发相比,RPM 软件包管理系统带来了一些优势。
p+ |3 F! ?0 c; Q* T$ J2 p9 o' i# t6 r6 x c
RPM 可让您:( m% V4 N$ g. B
: V- `' d3 v: D q1 ^使用标准软件包管理工具(如 Yum 或 PackageKit)安装、重新安装、删除、升级和验证软件包。% K6 `7 B& ?( f1 Y* a7 _
使用已安装软件包的数据库查询和验证软件包。
" F0 e4 K! K, i- N2 [使用元数据描述软件包、安装说明和其他软件包参数。
1 A! N) j; X& c$ \& E将软件源、补丁和完成构建指令打包为源代码和二进制软件包。
4 V" l3 n7 a" p9 a) i将软件包添加到 Yum 存储库。" J. \1 K; r p/ a1 l
使用 GNU Privacy Guard(GPG)签名密钥来数字签名您的软件包。
* l1 t/ B( b3 |. A5 M6 T1.3. 创建第一个 rpm 软件包 N2 O' V* h2 c- ~
复制链接
' |9 Q" Z% p; U( @+ X. t/ `! p I9 E创建 RPM 软件包可能会很复杂。下面是一个完整的、可正常工作的 RPM Spec 文件,其中包含一些跳过和简化的内容。- s4 C2 G$ W, x' H0 B% Z
# b' R9 y% f; l8 c
Name: hello-world
9 C0 W7 N3 c* r. YVersion: 13 O9 i: W2 _6 f3 g2 G) c) L
Release: 17 M# T/ N% l! q0 E3 r$ b; f
Summary: Most simple RPM package& | @$ f* C. e( Z: _4 _6 G+ z5 g
License: FIXME3 n9 K7 C4 A" d5 P' b
0 C! S2 [! q1 Y3 R
%description+ R9 W. t1 Z8 _4 s: N; @2 d" r5 q
This is my first RPM package, which does nothing.
) q4 X! T5 f( D+ {+ H5 H
. B6 h% Z5 M, g' Z%prep
* V0 F5 z0 M/ L# we have no source, so nothing here& y$ m. V1 R t8 M L
, N7 e& { t1 p6 U$ {; f$ T; E
%build: L5 I, C1 ~$ c1 i( K
cat > hello-world.sh <<EOF5 c5 J( a; C1 L1 W; b
#!/usr/bin/bash0 N# y( {; H4 G4 Q- M1 z+ M8 y
echo Hello world5 {. e. k6 F, t! k
EOF( ?* I- y0 v( ]# {- Z
/ F4 B9 k) ]1 I/ P5 X3 g) \9 y
%install
% J8 Y; g# B4 I+ p& b8 ~0 Zmkdir -p %{buildroot}/usr/bin/
) P: E& o4 q' X* _install -m 755 hello-world.sh %{buildroot}/usr/bin/hello-world.sh) s2 u7 c# m, F5 V0 p5 Z
9 g; O3 u1 S1 `7 D0 |, {: e%files( } P0 |. ?* K* i, U T% D& i. ~
/usr/bin/hello-world.sh
# x+ n2 Q9 }+ n; D2 L1 P4 K% F4 E" \: H& [! Y6 y3 {
%changelog5 z6 R. z$ T& f: Z* |) I A
# let's skip this for now
4 m/ ~. b, v `4 K# i将文件保存为 hello-world.spec。- y. n% `( C) k, O
, k3 O/ a9 p. S4 I5 F# h. G% k
现在使用这些命令:
. n: u9 z$ F2 I. a& l( Y b0 O% ?. [; P) W( N
$ rpmdev-setuptree
7 H, E* a" y( G: E: {2 q$ rpmbuild -ba hello-world.spec
6 i4 ]* N- K% j4 i: N- {* s命令 rpmdev-setuptree 会创建几个工作目录。由于这些目录永久存储在 $HOME 中,因此不需要再次使用此命令。* O2 O7 n4 ~6 H1 h
! P7 W/ o8 `) ~( H7 p# g/ `命令 rpmbuild 创建实际的 rpm 软件包。这个命令的输出类似如下:
5 {0 s( c+ c- E J
/ c* G) q4 C! O/ m5 B$ U... [SNIP]
# j3 A. i# _: f8 q4 i3 i; ^Wrote: /home/<username>/rpmbuild/SRPMS/hello-world-1-1.src.rpm7 _' o: x z* t! p
Wrote: /home/<username>/rpmbuild/RPMS/x86_64/hello-world-1-1.x86_64.rpm/ m) P! ]( T$ l# F
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.wgaJzv
. U- v5 L9 V& W) B0 v1 |* Q5 J+ umask 022
7 s( g; i" {) `% b9 w+ u9 G _+ cd /home/<username>/rpmbuild/BUILD
: ^* L- P+ v v9 P7 s/ e4 v) t. `1 `+ /usr/bin/rm -rf /home/<username>/rpmbuild/BUILDROOT/hello-world-1-1.x86_64# F: O4 j9 ~) K
+ exit 0: N. S' _& r2 E% ]+ W
文件 /home/<username>/rpmbuild/RPMS/x86_64/hello-world-1-1.x86_64.rpm 是您的第一个 RPM 软件包。它可以安装到系统中,并经过测试。
9 R M4 C( M- A$ |" g+ s
% D& U' R$ A" ]( i1 ^$ e5 Z第 2 章 为 RPM 打包准备软件
9 B6 G& W" L, L) z0 Q; K1 u& Q复制链接
8 w8 w) `4 x7 @ I# B本节介绍如何为 RPM 打包准备软件。为此,了解如何执行代码。但是,您需要了解基本概念,如 什么是源代码以及构建过程。4 ^9 R' G8 S& k1 U- o
: j3 ]% s v% M6 Z) q' M$ S2.1. 源代码是什么
8 e! g5 k6 _2 |1 [0 k复制链接8 K2 L" {2 ]) e7 g% R3 P
这部分解释了什么是源代码,并显示了使用三种不同编程语言编写的程序的源代码示例。0 g. ~. n3 W5 f" o
: k, p( A/ B2 }/ B, o0 ^+ M源代码是对计算机的人类可读指令,描述如何执行计算。源代码使用编程语言表达。; c2 s( r& Q1 r: j; Q* A, f
# c) G- _7 {8 Y6 c# Z2.1.1. 源代码示例
' c# Y% @4 K7 O0 V, z& M复制链接7 _% c3 `) Z1 Y% [% T9 d) B
本文档提供三个使用三种不同编程语言编写的 Hello World 程序版本:
9 e; w7 J# d! C1 z0 y. P
9 k$ m0 d- C1 W第 2.1.1.1 节 “使用 bash 编写的 hello World”7 Z8 m; c e7 v9 z
第 2.1.1.2 节 “使用 Python 编写 hello World”
* w. H* @- U( V" K- b2 n第 2.1.1.3 节 “使用 C 语言编写的 hello World”8 f8 b5 f% f* D7 K
每个版本都以不同的方式进行打包。 G! B3 b1 p, F8 T0 e' E
5 \* Z c# `$ Z# c2 m* h. k这些版本的 Hello World 程序涵盖了 RPM 软件包器的三个主要用例。( ^% y6 n' {2 S! C1 u6 v( V
4 `' Q, t1 a5 J9 x/ A2.1.1.1. 使用 bash 编写的 hello World 5 A: G- z) L1 ]" O6 O0 N
复制链接
$ \. q. L, k; Tbello 项目在 bash 中实施 Hello World。该实施仅包含 bello shell 脚本。程序的目的是在命令行中输出 Hello World。& e( [/ g3 {4 t7 [+ d, o
% f7 t8 f6 m& u$ jbello 文件使用以下语法:
1 b8 @+ p% F ?* d7 U% F$ U
( s# ^6 F V: i/ m; X#!/bin/bash6 ]) o1 a! a5 S% b
: f$ k! H0 C8 |
printf "Hello World\n"1 `& H6 g' Y7 B8 c+ b: U
2.1.1.2. 使用 Python 编写 hello World 3 D3 a: ~5 ^& J9 r/ U2 W
复制链接2 b7 P+ {, Z2 ~: f
pello 项目使用 Python 实施 Hello World。该实施仅包含 pello.py 程序。程序的目的是在命令行中输出 Hello World。
, |; J" T0 ?, Y8 i# I: l0 {# \5 B( Q$ T
pello.py 文件的语法如下:: q) d1 V+ _" N, m8 w
" T$ a' a2 p: q
#!/usr/bin/python3 r$ x% |4 [* V# s; ?0 {
, g% z# T' d Y1 i: Z) d
print("Hello World")& B. X8 k& \" S" m. O
2.1.1.3. 使用 C 语言编写的 hello World
; R0 T3 v0 D: J' U7 K复制链接$ O" L% {3 s$ v8 f' d# |
cello 项目使用 C 实施 Hello World。实施仅包含 cello.c 和 Makefile 文件,因此生成的 tar.gz 存档除了 LICENSE 文件外有两个文件。
3 c+ f9 F, n) ?7 s. ]
5 d- X T1 q' }程序的目的是在命令行中输出 Hello World。/ E( z( c7 v* C2 @ u8 M% C* L
G2 p4 E6 w. Aunito.c 文件使用以下语法:
: H$ i* d2 E1 V1 j9 ~
5 N/ a, E6 C! A# w$ V, _8 s#include <stdio.h>! Z& r0 G }* A2 Q; I; {; `
$ ^1 {$ l9 v( q$ Nint main(void) {
3 j" T; O% S6 {/ P! C7 g printf("Hello World\n");
7 \9 h/ |' Y7 ~# ?7 k, [" f return 0;' k2 N) v" |4 W: y8 V; |
}
- T5 I' i! u [- b6 F& G2.2. 如何提交程序
& v0 g3 X1 V/ B0 r% i复制链接
7 p5 r& B7 n8 E. E从人类可读源代码转换为机器代码(计算机遵循执行程序)的方法包括:
. r! U; k( Q' e, X& K
4 h5 V' s2 [! K& D程序被原生编译。
1 ^9 I1 x( `7 q; k' q4 g- W# w6 F程序由原始解释进行解释。' t4 u- Z! w- `7 a2 _
程序通过字节编译来解释。6 A2 T. {: [' i' m* }( i
2.2.1. 原生编译代码 , _; z' c1 s! K# ?
复制链接0 K5 ^- R- D5 C6 m# D M( Z# Y7 A
原生编译的软件是使用编程语言编写的软件,使用生成的二进制可执行文件编译到机器代码中。这些软件可以独立运行。
- J) {/ z$ V; p* g; c9 f! e$ z$ u! f( P' w7 h+ h: l, f
以这种方式构建的 RPM 软件包是特定于架构的。. K* C( u' n/ H
( {( A7 {" L0 U: [! y如果您在使用 64 位(x86_64)AMD 或 Intel 处理器的计算机中编译此类软件,则无法在 32 位(x86)AMD 或 Intel 处理器上执行。生成的软件包的名称指定了架构。5 B1 F2 \$ ?, Q& e; l; n( a; k, v
]" m7 k6 m$ n
2.2.2. 解释代码 % G7 X* y8 S8 w+ Q C0 P
复制链接
; c6 }4 `5 F& q* ]0 T有些编程语言(如 bash 或 Python )不编译到机器代码中。相反,其程序的源代码是在无需进行提前处理的情况下,按步骤直接执行源代码。这是通过相关语言的解析器或一个语言虚拟机实现的。6 S0 \; i+ r4 h' r* ?0 I
1 A- E9 T, A* Z
完全使用解释编程语言编写的软件特定于架构。因此,生成的 RPM 软件包的名称中包含 noarch 字符串。
^) e$ Q& I+ y8 ?4 M: A* J3 U' \! I r! I" s# N o0 r9 i. m
解释语言为 Raw-interpreted 程序,也可以是 编译程序。这两种类型的程序构建过程和打包过程会有所不同。+ u% Q# b+ O7 p( F& O7 R$ _
0 ?9 M4 y; D- J' p
2.2.2.1. Raw-interpreted 程序 0 {( F5 O6 D1 m: O- D p$ E
复制链接1 [6 @& i5 V+ s, B9 u* l
原始解释的语言程序不需要编译,并由解释器直接执行。$ q% [) q G$ L: a
4 _1 x" S9 u& A, B* R" X
2.2.2.2. comp-compiled 程序
: x5 M6 G1 t2 o$ \: U' u复制链接, h+ e( ?+ k; ^' u- d0 \: Z1 p
字节编译型语言需要编译成字节代码,然后由语言虚拟机执行。" d0 L+ A1 H& m% j5 \8 V
( h8 @, X) r8 T# G$ h0 I7 w注意$ H/ g. }6 N9 {( y# U; j
有些语言提供了一个选择:它们可以是原始解释的形式或字节编译的形式。# I& R I& Q7 j% X9 R4 e! n6 ?5 m
( X* M8 d( Q9 c* _2.3. 从源构建软件
) ]9 h; ]: o& P: S* a复制链接
( m( L7 r C8 T$ t这部分描述了如何从源代码构建软件。
+ l. h5 G( T/ H& R8 J
) \+ Y1 p) F3 p$ ^. B. ^2 y对于使用编译语言编写的软件,源代码将通过构建流程生成机器代码。这个过程通常称为编译或转换,不同的语言会有所不同。所生成的构建软件可以被运行,使计算机执行程序员指定的任务。8 t [7 K, g/ d, o2 ?
, I4 J* ?; Y+ D p% \5 c
对于使用原始解释语言编写的软件,源代码不会被构建,而是直接执行。
) ~7 z( R9 H: b+ P4 _7 R
! X2 k; I) ^6 M+ @& B9 ]( v2 C' d对于以字节编译的解释语言编写的软件,源代码将编译成字节代码,然后由语言虚拟机执行。
" `9 X9 g! _; P) Q1 U3 Z' g* B
. N" c* q4 B# e. o6 a2.3.1. 原生编译代码
1 k0 A' Z% A8 T) |5 C3 c( q复制链接
9 _+ s0 e* |8 V6 h8 o' }本节演示了如何将 C 语言编写的 cello.c 程序构建成可执行文件。
' N* N p& W4 e/ p. Y$ P- {% i
$ a- [4 G% s2 j5 e4 icello.c2 V6 S n. S0 V7 |: W4 r/ n
+ B7 V8 m9 Q1 c! E" s
#include <stdio.h>
, M1 ^* P5 u5 [- D8 d1 L. X7 ]' j
int main(void) {
7 ~3 X' A. `8 z% g% F, |* F3 S0 i printf("Hello World\n");
( T0 i" x5 R- x |' z" W0 ~ return 0;8 ]& ~3 l* r% ?+ U1 Z
}
5 E" |/ c+ N* o8 @: W6 n- p; h2.3.1.1. 手动构建 5 I7 Q N3 w( w6 _: {4 p9 n
复制链接# |' a/ `- J% J$ i+ \3 b
如果要手动构建 cello.c 程序,请使用此流程:
$ m" ]6 D2 O7 H* s5 o8 j9 G; g- ` f6 K0 c
步骤+ I A2 \6 l. O' A; e" M2 W
# Q4 m$ t: U" `8 N7 `! L7 c从 GNU Compiler Collection 调用 C 编译器,将源代码编译到二进制中:
0 w) J/ X6 H4 S' V1 V3 D- D/ o) t3 D$ C# k4 b/ O1 J
gcc -g -o cello cello.c5 `# c1 u3 M4 F: a, j
执行生成的输出二进制 cello :4 k( W5 q7 N1 ~$ }
5 W* G9 o1 w' x8 r( Z$ ./cello) e4 O% m# N, N4 }
Hello World
1 ?. N1 [! y: _: n2.3.1.2. 自动化构建 2 t. c$ |5 L% A
复制链接0 S7 l" M6 d% ?4 }
大规模软件通常使用自动化构建,方法是创建 Makefile 文件,然后运行 GNU make 实用程序。
/ W; X- B! V: _& V: T5 _9 O
! @. i. i% D" U" _. ]如果要使用自动构建来构建 cello.c 程序,请使用以下步骤:5 Y6 a e) y7 k# x" y% p
! k8 G% W" m8 W1 l8 C7 U, D
步骤
' G+ k* C8 L5 k* L9 {+ o4 s( e$ f% n4 ?; A. W/ Z: p& Z
要设置自动化构建,请在与 cello.c 相同的目录中使用以下内容创建 Makefile 文件。& N: N' a5 j1 |1 B. A7 B( @1 b
) S: P/ x5 n7 W: C; `! ^
Makefile# W: o+ [+ P+ h4 \
" Q' z3 i2 _+ k$ H% b' U/ icello:5 G; b+ Y! g( Z5 `3 T
gcc -g -o cello cello.c* t1 t% y& Q. A7 i) L9 @' D& y
clean:0 \" f& Y- z' A
rm cello
' a: R# N" ~$ U$ d请注意,cello: 和 clean: 下的行必须以一个 tab 空间开头。
, a: Z0 K0 q p
8 A& {" f. s# T3 X6 h8 R9 T要构建软件,请运行 make 命令:
( n$ T) U$ R- V# Z: r6 l7 y
- u+ L- y* ?, r7 I% k$ make
2 i* h! w9 e' a* jmake: 'cello' is up to date., E8 G* z- F* g8 ?! h( Y
因为已有可用的构建,请运行 make clean 命令,然后再次运行 make 命令:
! O5 L8 I# t+ H
9 _1 Q6 q7 @( E, k' u3 p# |$ make clean* E- c( L& J: F9 r
rm cello
% ~8 v3 H. t2 V/ s9 h8 f& f& U) G& s& [$ r0 X- c7 ~/ n% V4 q
$ make
3 @7 V3 d. X; ]9 Ggcc -g -o cello cello.c
9 `4 g4 N- ]& h4 [; K注意1 N9 ?. o W; j5 v! P) y
在另一个构建之后尝试构建程序无效。4 R5 X9 e5 U: @6 f' q
: Z& x" Z7 p: b7 ^: F# `" |
$ make! t. D' G9 @9 U F& ?3 A
make: 'cello' is up to date.
1 Y, L- `8 l% a执行程序:
. t, u' R1 [0 b# W" V# G+ ^) e
7 A* p2 M( X# { v$ ./cello" {3 a3 V& C1 K
Hello World% _6 T) h. x" K! R. S' Y: E
您现在已手动编译程序并使用构建工具。
7 C6 Z% ?8 O7 h4 Q: D- y
0 m, E0 ]8 e: a3 [2.3.2. 解释代码
% `" Y5 i- ?; D0 F3 A, ~3 [复制链接: E; v" h% j' h8 p* i0 F
本节演示了如何对 Python 编写的程序进行字节编译,以及使用 bash 编写的程序的原始解析。
. ~9 Y" k7 e3 t$ `9 Y% \" J
/ E6 I: V% Z4 A9 E* l1 T注意* @2 x0 g7 B4 u
在下面的两个示例中,文件顶部的 #! 行称为 shebang,不是编程语言源代码的一部分。" P7 C6 C* h7 Y2 a: w. a6 Z$ |
5 z3 l; S/ e& H# m- h! I
shebang 启用文本文件作为可执行文件:系统程序加载程序解析包含 shebang 的行以获取二进制可执行文件的路径,然后用作编程语言解释器。功能要求将文本文件标记为可执行文件。
. v& G# K1 D6 \! P9 K( ?, y' B" n" E1 G7 e
2.3.2.1. 字节编译代码
# H5 T* j. u% p+ B9 z复制链接: o x, U4 Q/ u/ t+ I
本节演示了如何将 Python 编写的 pello.py 程序编译成字节代码,然后由 Python 语言虚拟机执行。( e" D5 F3 y( d' b# [3 Y( n1 p
& F ^- `$ H4 V0 o
Python 源代码也可以是原始解释器,但编译的版本速度更快。因此,RPM Packagers 更喜欢将字节版本打包为最终用户发布。
6 V6 J, _3 S9 h! l0 L$ E H* V8 K' o6 D7 h- q3 f0 x/ u+ O4 x* c
pello.py
( k0 s, N& q# D! l$ ~4 C
7 L. r8 t/ W+ d! o2 m- p3 D' n#!/usr/bin/python3
- ]3 ?( h% V) c- p* Z% r# _' x7 X& L1 Z' H( l( L8 z7 D0 @* O
print("Hello World")% S% d# V5 }2 @( B; i
字节程序的流程因以下因素而异:2 A3 l* t# q( O- w) _ L
6 [7 `& q& {6 r& K: {/ F$ q
编程语言
4 [8 U1 I% ~! P1 k2 n2 q语言虚拟机
; q) ~9 x9 q% a" I与该语言一起使用的工具和流程
O) O" l+ X" n3 M( g注意
6 e3 x4 S( W; I3 ]; s2 n4 J2 N* {Python 通常进行字节编译,但不采用这里描述的方式。以下过程的目的并不是满足社区标准,而是为了简单过程。有关实际工作环境中的 Python 指南,请参阅打包和发布。
3 D: Q) K2 A" M6 m6 D9 @2 \" [# l0 @
使用这个步骤将 pello.py 编译成字节代码:
) g8 Y# h& c9 T" h9 m9 L$ L4 X0 H7 a, v% M: f3 Z
步骤
. n. |$ |* ~0 z0 |4 m! K4 N+ s. G: y& T- H' Q/ ^
字节编译 pello.py 文件:
g3 J0 N- ~, J" j5 y2 m
+ o! X) E0 Y% r$ a% E0 t. P$ python -m compileall pello.py4 ^1 f) X/ p- P% A; a o- {
1 _7 [0 g- l5 [% c6 V6 P
$ file pello.pyc1 M4 @) L5 r0 r) k
pello.pyc: python 2.7 byte-compiled
, P8 @2 B) U) |! `7 W6 `% q$ }在 pello.pyc 中执行字节代码:2 p( T) R, n6 n3 A# Y' c9 \5 I
3 e" b% H' l' `+ W% K/ S, N$ python pello.pyc% l7 Y' p! E; u9 z$ X1 ]
Hello World, V% l3 ?8 z T; w: g) c! ^% k/ ]! V
2.3.2.2. 原始解析代码
2 F3 O3 ^. ~4 s7 Y+ X复制链接" q) a' _/ ?. f/ n! B. a
本节介绍如何使用 bash shell 内置语言编写的 bello 程序。4 n# z9 q4 h. D/ C, Z9 [
4 u& y; M' c- E- @$ A- B3 k
bello4 [8 a6 O* Q' v% ^8 @
) Y X; z& A& S% W, y- d
#!/bin/bash6 k+ b6 @- l6 y: e% l
) \# U8 l. |/ r* Tprintf "Hello World\n"
, `; e8 e" g$ M1 j1 j使用 shell 脚本语言(如 bash )编写的程序是原始的解释。2 X1 R& K4 V% e" H3 X( X( v
5 a5 ?, O' T/ l' b0 `: J9 }' Q
步骤
* f$ h# l- `" C
# _! `# W5 X# y使含有源代码的文件可执行并运行它:
5 \- y4 k9 f, m2 M
$ q. k9 W# P+ X$ chmod +x bello
! C/ X" o8 ?# I, Q8 ?$ ./bello
' C: v L9 L& ]- n, `Hello World+ j) }( S3 g2 w/ H& ]5 U- \: q) h
2.4. 修复软件
0 m$ h) G, u6 z- }% ^5 R& ~复制链接& b. |; W# j1 N3 Q- v/ [
本节介绍如何修补软件。! L* P5 v& l$ U$ o: v! Z) K' G: ]
7 V. n4 t6 c% y! e; b在 RPM 打包中,而不是修改原始源代码,我们保留它,并在上面使用补丁。2 }$ _, e, O; i$ a+ a1 k' Y* d1 ]
; B) A0 T) y& V K. p8 A, Z补丁(patch)是用于更新其他源代码的源代码。它被格式化为 diff,因为它代表文本的两个版本之间的区别。使用 diff 实用程序创建 diff,然后使用 patch 实用程序应用到源代码。( U& f, M7 p, h4 h
+ T6 V; Q$ w" ~0 a1 o! f
注意
- Z, }6 b( w' g/ X, m2 K- L1 G软件开发人员通常使用版本控制系统(如 git )来管理其代码库。这些工具提供自己创建 diffs 或 patching 软件的方法。! U" |/ ?' k7 u: p
( T* K% t; |( x- \
以下示例演示了如何使用 diff 从原始源代码创建补丁,以及如何使用 patch 应用补丁。创建 RPM 时会在后面的章节中使用补丁 ; 请参阅 第 3.2 节 “使用 SPEC 文件”。
, g6 G5 s: E: Q- N3 X7 }8 ?
# J: F- x/ U6 h8 N此流程演示了如何从原始源代码为 cello.c 创建补丁。
- M% l1 l/ ?% \
) H3 k/ Z* a( u8 @3 t5 H) ~. T步骤8 y0 E' f4 V3 ]1 G
. y$ s+ a' l' j; f; [7 Q保留原始源代码:/ ?& F* F1 U9 w
0 a' N2 q( [2 X' i, F
$ cp -p cello.c cello.c.orig
1 }1 ?6 N/ {; k-p 选项用于保留模式、所有权和时间戳。4 v! w; M" k' v Y$ i" x4 i! j; y
0 I3 f2 M1 V# x8 o; e. v根据需要修改 cello.c :8 v7 @8 S& e0 \/ S
* ?# ~; I" u7 |
#include <stdio.h>
" D! ~0 u& Z# O# T4 C& T0 d( u8 e1 } v
int main(void) {& n, a2 x% S+ z/ a; z3 S
printf("Hello World from my very first patch!\n");
9 }7 X7 p& \7 H1 W return 0;
3 F" l1 I) K2 F' p! z5 R} X, H& b- \- v _( N4 r; G5 H+ K
使用 diff 实用程序生成补丁:" a& U3 p' x- j( O; o
; E" O% f9 ] V! l6 N$ diff -Naur cello.c.orig cello.c
' W( @, v; ^* Z* ? @: O y( B" A--- cello.c.orig 2016-05-26 17:21:30.478523360 -0500" {3 @- y2 c, w) `
+ cello.c 2016-05-27 14:53:20.668588245 -05006 C R# c& n+ v- b9 @8 K
@@ -1,6 +1,6 @@
7 K; f" p& W) g #include<stdio.h>
6 K y, H3 l A A2 p
! E P" b+ `2 {: X int main(void){. k+ R! s2 x8 |4 y" a
- printf("Hello World!\n");
5 K( x' o8 X/ \0 w0 F E, V1 }+ printf("Hello World from my very first patch!\n");
$ x+ y7 `9 C [) r: \: v; g8 B! O- J return 0;0 Y+ n+ H: F \. }
}
) S6 X, d6 J0 u0 Q' i" \% e/ y0 {: B\ No newline at end of file
6 g# o. i* S! |' I0 h以 - 开头的行将从原始源代码中删除,并替换为以 + 开头的行。9 u; W3 `6 J: |6 `+ ~ v' }: N; G3 N
5 U8 ~5 L$ Q- l% n8 G建议将 Naur 选项与 diff 命令一起使用,因为它符合大多数常见用例。然而,在这种情况下,只需要 -u 选项。具体选项可确保:2 b3 l' N( ]7 `- v( _
3 i ?: z# G! ^6 i
-N (或 --new-file)- 处理缺少的文件,就像它们是空文件一样。
9 ~- j2 A* p! P7 {9 v& x-a (或 --text)- 将所有文件作为文本文件。因此,被 diff 认为是二进制的文件不会被忽略。
- `0 T, P$ L! s2 D. G+ B% w! Y-u (or -U NUM 或 --unified[=NUM]) - 以统一上下文的输出 NUM(默认为 3)行返回输出。这是一个易于阅读的格式,允许在将补丁应用到更改的源树时进行模糊匹配。/ a, I; q$ {5 i
-r (or --recursive) - 递归比较任何找到的子目录。3 ]6 q K: W% ^ f8 X+ o% Q+ T
. L) L+ L0 Q. m4 F4 |( W有关 diff 实用程序通用参数的更多信息,请参阅 diff 手册页。
, G; S9 S" ?: O3 S, Z) E/ ^; N w$ o9 r
将补丁保存到文件中:3 w. i0 _# V& S+ Y- l3 g: z! c6 l
% T& O* q8 u; H% o' ?5 p$ diff -Naur cello.c.orig cello.c > cello-output-first-patch.patch- H: R* o5 y5 E' h% d* O3 r
恢复原始 cello.c :& e+ ^/ W# u3 N. ?* g) v9 M
* s: [6 P2 r9 L5 L: v" s
$ cp cello.c.orig cello.c
0 U8 d# u/ e6 y) R% ~; b8 z7 r必须保留原始 cello.c,因为当构建 RPM 时,将使用原始文件,而不是修改的原始文件。更多信息请参阅 第 3.2 节 “使用 SPEC 文件”。
4 {$ \1 J+ z6 M ^ z
& o" g, N0 _' G: {. B以下步骤演示了如何使用 cello-output-first-patch.patch 对 cello.c 进行补丁,构建补丁的程序并运行它。6 m, x" a7 X% s- m: l+ D/ _6 J
3 m% z7 j* F3 ]3 N7 ]6 m: w/ ]将补丁文件重定向到 patch 命令:* ?! H6 q8 u5 @1 n; F
& ]4 v7 u) d$ h$ A. v% J$ patch < cello-output-first-patch.patch
; c. V$ w2 X- }2 r! _patching file cello.c9 f0 S! E$ A" H$ z. ~8 d
检查 cello.c 的内容现在是否反映了这个补丁:
9 X3 ~$ w& O3 ~) U. B; Y2 _: z+ p7 Y" H9 B
$ cat cello.c5 f4 O& G5 g+ U9 e
#include<stdio.h>
" {8 e0 v' k' p( q& P( N( ]" N: J& E, c- c- F: J4 \
int main(void){0 E/ |$ C& A. I. z5 A" u1 g
printf("Hello World from my very first patch!\n");/ e \# D& E: ~* P) ^2 x0 o. ~0 `
return 1;
6 B$ Q6 O; J. w}
, Z g& Y. U/ d& k( P$ d) L( M构建并运行补丁的 cello.c :0 B0 k8 u+ R% f' U* T: e
* ~6 y6 P/ x* Y7 c$ make clean
$ K4 T' j1 m' H- frm cello1 f! C, Y! Q0 u8 y& v: e5 ]
( _/ h1 p7 a5 T; E2 a
$ make6 \' E9 ^! z9 ]* `& v; ~; w1 q! e" \8 K
gcc -g -o cello cello.c9 Y" c0 R9 F) L* ~8 h$ L6 g i1 J
. \7 {4 E- x5 N4 X4 U+ ~
$ ./cello" S% }& {4 d- R
Hello World from my very first patch!
3 k3 }4 K5 @6 F( E. ] ^2.5. 安装任意工件
3 N* r/ I2 _( e3 C' J+ v复制链接
7 u9 o' @, k5 J/ f. z! a与 UNIX 类似的系统使用文件系统层次结构标准(FHS)指定适合特定文件的目录。 G t% p4 z$ X
+ \+ x0 @/ C0 B4 c1 o从 RPM 软件包安装的文件按照 FHS 放置在其中。例如,可执行文件应进入一个位于系统 $PATH 变量中的目录。
9 j% ]" v. |! q( `& i. m m2 Q0 {& r, i
; p; U5 P. A! F0 {; b) Q在本文档的上下文中,Arbitrary Artifact(任意工件) 代表从 RPM 安装到系统的项。对于 RPM 和系统,它可以是脚本、从软件包的源代码编译的二进制代码、预编译二进制文件或任何其他文件。3 u) b) g$ Z% q4 U% r
( K+ L" q) r/ }这部分论述了将 Arbitrary Artifacts 放置到系统的两个常用方法: U+ u9 B7 T4 L
" X1 w& s [, d; H ~) c第 2.5.1 节 “使用 install 命令”
! g7 V$ d; R" w& P- W第 2.5.2 节 “使用 make install 命令”
# v" d3 E/ Q" W9 \5 R! R8 B2.5.1. 使用 install 命令 3 d/ o- n/ ?% s$ z9 q2 E
复制链接
) f0 C' v+ F P$ s7 ]在构建自动化工具(如 GNU make )进行构建自动化工具时,打包程序通常使用 install 命令;例如,打包程序不需要额外的开销。3 h- w8 s% J$ Z! U
; s$ z- x- x# W/ _8 S: E
install 命令由 coreutils 向系统提供,后者将工件放置在文件系统中具有指定权限集的文件系统中。
- s4 j# ^- U) u* V9 f( \: N
4 \1 m. N% {# k以下流程使用之前作为此安装方法创建的任意工件的 bello 文件。
; H1 a4 g5 U" U/ P* Y' y+ r# N
6 D" Z, Q! h8 L$ [ Z2 H* @步骤. _8 p- u5 U. J+ f- ]9 |7 ~+ ]
" G6 b( b% W( Q: ?! Y$ y$ o运行 install 命令,将 bello 文件放入 /usr/bin 目录中,权限为可执行脚本: u0 t6 V6 e$ j& T. N& C @0 E- k* D
; b, v/ r. G% o
$ sudo install -m 0755 bello /usr/bin/bello: y; W& I }! Y- n
现在,stllo 位于 $PATH 变量中列出的目录中。
0 d% v4 C& _0 t% E4 B, n6 s# }/ s1 j! f, i$ h( r7 o. M4 C
从任何目录中执行 bello,而不指定其完整路径:
/ \5 m3 G( Q7 ?4 x6 e) U+ ?& e0 F' E2 U1 l7 n9 Y
$ cd ~9 ~5 l B* n3 D5 Y( E& D4 R+ B$ P5 ]
6 h& b+ d1 S; a$ l" S! S1 R
$ bello
$ x# E6 g, R( d& A3 X" DHello World
6 e1 I* h4 o a6 \) {: _0 D* |' N6 }2.5.2. 使用 make install 命令
" J" U6 [* K/ I复制链接3 n% n2 `1 C9 e6 X& [. _
使用 make install 命令是自动安装构建软件到系统的方法。在这种情况下,您需要指定如何在由开发人员编写的 Makefile 中向系统安装任意工件。# ?$ ~4 q$ m* W+ r& O
8 [+ k/ I7 B& G
此流程演示了如何将构建工件安装到系统中所选位置。9 o* m9 B. r' x# [$ \4 R4 c
0 r" N1 m. C9 ?) o1 C6 [9 d: t步骤2 D6 n0 H/ r2 F
$ f n- ^6 x$ H, y. u. w将 install 部分添加到 Makefile 中:) r: D- _- I. @( m' i
) L( S, F8 |2 eMakefile
$ T& a% t; f! i6 W: Z
0 J' L5 [; p, v9 P! {0 Gcello:
) V* h' L2 R4 K* V gcc -g -o cello cello.c
" ]+ h1 G0 _0 A
% {$ W/ U: L* c5 `; U6 N3 Rclean:+ `" c. `% l) R. U8 g: C
rm cello: D" q+ H, X" R* p d' I, Q
1 ^; X; p6 Y$ ?install:
6 W% [; ?8 y6 j9 C& c mkdir -p $(DESTDIR)/usr/bin
% C9 x0 t( r. q/ g install -m 0755 cello $(DESTDIR)/usr/bin/cello! l+ |& S5 M1 R3 H% G% d/ y
请注意,cello:, clean:, and install: 下的行需要以一个 tab 空间开头。; J& O" `* d1 `/ \9 ^
6 |4 f6 Y7 s3 M+ `1 S8 _, V
注意, M1 s. Z1 o7 t! b5 ]/ Q/ R2 V( J
$(DESTDIR) 变量是一个 GNU make 内置变量,通常用于将安装指定到与根目录不同的目录中。
5 F t _2 y' ~7 F7 F, j4 G D$ I- M' Y& T6 n" G
现在,您只能使用 Makefile 来构建软件,也可以将其安装到目标系统。
9 v/ X3 G0 g m2 ^& h' X
4 o$ y+ Y6 @: M' O构建并安装 cello.c 程序:. {# t9 N: L" q/ L
Y4 [& }0 \; p! L" L2 _' @$ d$ make! z) S9 l7 p, |7 P( S; Q+ z5 x0 h
gcc -g -o cello cello.c. b! |# q. O# m% [& F: F
3 ]: f' k4 S/ ~% J/ `' c" {$ sudo make install, h7 Z% d0 j& z% l$ v1 ?$ k1 w& {+ d
install -m 0755 cello /usr/bin/cello
9 I% w7 g: t- W, f- t因此,cello 现在位于 $PATH 变量中列出的目录中。) W1 ]4 f% u* T0 h% J& [
1 J( h6 n# X; C" \3 [. @" J8 ~从任何目录中执行 cello,而不指定其完整路径:" ?) F* r+ z% c8 Y$ |) q; T; i; j
3 e8 h3 a" @" Z& y$ cd ~
{- \; E6 f! T" R3 H Q& N9 I
" Z9 ~: @, ?- \0 V$ `& [: |# {$ cello
$ i8 x6 y' y7 S3 ~2 p$ g/ m1 m: AHello World
" j7 r" ^; l. a2.6. 为打包准备源代码
- g8 g$ x/ `+ r3 I3 _: h( l复制链接
; D' ?$ q9 \- Z! ~6 d9 w开发人员通常会将软件作为源代码的压缩存档分发,然后用于创建软件包。RPM 软件包程序与可用的源代码存档配合使用。
, a" W8 s+ u% P3 ~; ]9 R, h) D) {
/ ?, ^. {! |5 s/ O软件应通过软件许可证发布。
2 r: D; o- |( ]1 @- h! p# q s: |7 A; u
此流程使用 GPLv3 许可证文本,作为 LICENSE 文件示例内容。
* I: @3 x& L) |$ w- z% R0 u; u }
( b- C, z- t( V0 U' b步骤* n. P# ?% n: _+ g. e0 y
3 k% }- ]8 V5 U# @& R
创建 LICENSE 文件,并确保它包含以下内容:; _4 r, f6 t" Y; w- n
- `. }0 Q0 `4 r' A* t% A! [9 }$ cat /tmp/LICENSE; m: p# d% r- R
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.: U2 \" I! b( N9 e3 T. M
2 L0 Z+ H' m* D" ?4 K. ]
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.9 I" p8 E( u/ n4 y
. i* S: ]7 A# S* n! |
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.4 `, s7 A9 O* o1 ]$ `1 r, P. w
其他资源2 j8 [. f+ Y* K( E" L3 ~, Z( u
; Q# K% P& ^; j& l. M8 m$ `0 }
本节中创建的代码 可在此处找到。 k' j2 ?! e' B, b- c9 D- M
2.7. 将源代码放入 tarball
+ G( _6 T6 ~- F5 ~$ n复制链接
: j0 V n" }7 F& k这部分论述了如何将 第 2.1.1 节 “源代码示例” 中引入的三个 Hello World 程序放在 gzip压缩 tarball 中,这是发布软件以后打包在一起的通用方法。
9 ?; k7 Q# u8 {7 K ^* u8 Q8 N2 p0 v( u+ B) g& g( G" U
2.7.1. 将 bello 项目放入 tarball ) G! _7 ~ G1 G6 O3 ?
复制链接% ^/ E) _& w! d S; k( b
bello 项目在 bash 中实施 Hello World。该实施仅包含 bello shell 脚本,因此生成的 tar.gz 存档除 LICENSE 文件外仅有一个文件。
2 t) g+ e3 f/ T% _- ?, K' I9 C6 E @- t0 l: p7 ~& ?, h& ~ E
此流程演示了如何准备要分发的 bello 项目。
8 x) ?" x* [6 B0 V0 C# `" Y2 z. q* T2 T' N0 p4 w+ Q. U
先决条件
" t4 ^$ C2 d t5 w% w: t9 U" }4 C. e; V$ W7 b% I, X! A0 H
在这里,这是计划的 0.1 版。
- x. M9 R8 n) g, G' H# K0 h( A |" P: x
步骤4 t: s: p* N7 N6 q; C5 }6 m
$ q6 ~. N1 i7 \. v9 j将所有需要的文件放入一个目录中:4 g+ I. l- Y m( _1 f
' H, [+ {0 @( X$ mkdir /tmp/bello-0.12 h% Z- ]# t- ]9 H- V2 I9 H8 @
" L* ?! r; o& Y* O$ mv ~/bello /tmp/bello-0.1/% v2 Q& T `1 x0 I( q5 c. q% C
1 m# m3 X& N. _7 h' H4 s
$ cp /tmp/LICENSE /tmp/bello-0.1/
: o# D' [6 v7 @9 j/ n. ?. o$ Z为分发创建存档并将其移动到 ~/rpmbuild/SOURCES/ 目录,这是 rpmbuild 命令存储构建软件包的默认目录:
( A' y# S: I) K C
( K n2 T: i& d' w, u2 f0 ]1 D$ cd /tmp/
! r: n- L1 [6 H9 s# U# O5 b* C9 a8 ^. T8 P% f
$ tar -cvzf bello-0.1.tar.gz bello-0.1
Y# K7 U" ?8 _6 a; d* L: B d& bbello-0.1/
9 j# | @0 x ` y, J- Ybello-0.1/LICENSE6 s: F* J( ^, p7 ]$ M
bello-0.1/bello n5 T3 v: K; v
U$ F y* ]& j1 ?5 t. G$ mv /tmp/bello-0.1.tar.gz ~/rpmbuild/SOURCES/$ ^% u: v: w* i/ y L- c
有关 bash 编写的示例源代码的详情请参考 第 2.1.1.1 节 “使用 bash 编写的 hello World”。
9 {3 f. u, z5 N
" R3 E7 G/ G7 Z8 g+ c2.7.2. 将 pello 项目放入 tarball
* {9 E8 _/ a9 e+ E复制链接
$ W( a" K& L" c9 a4 ^' z6 @pello 项目使用 Python 实施 Hello World。该实施仅包含 pello.py 程序,因此生成的 tar.gz 存档除 LICENSE 文件外有一个文件。
- w$ [$ Y% M; {4 N4 G3 d6 V; y8 |, R
此流程演示了如何准备用于分发的 pello 项目。# _. u5 f( h9 R/ p/ h
9 v8 g9 t! A9 d7 U: I! m* B6 e
先决条件 d2 l7 j, `& m7 q' d
, P0 x( N$ f( ]) i: P$ S8 M
在这里,这是计划的 0.1.1 版本。
6 L4 _ @( \- D9 F. ]
J! }! v" @$ n& {6 ]! y步骤" e8 F$ h+ M" h3 q% q$ r, l
( F% a% B0 I2 V! m1 Z9 J( S将所有需要的文件放入一个目录中: p9 E# O Y4 F# p
5 P( S5 D) K4 L$ r9 D) B# A
$ mkdir /tmp/pello-0.1.2% X2 }2 J/ s. \, I
8 W& J% Y9 d' P- b- ~$ mv ~/pello.py /tmp/pello-0.1.2/4 E6 J i4 K5 C0 ?
8 |, u: G4 U0 m; J! h/ u4 u
$ cp /tmp/LICENSE /tmp/pello-0.1.2/3 a$ o1 ?- E6 E x& r, T: u! R
为分发创建存档并将其移动到 ~/rpmbuild/SOURCES/ 目录,这是 rpmbuild 命令存储构建软件包的默认目录:2 [2 x9 Z- \/ @' v: v# I
, y2 T2 D1 Q& {2 g Q5 R
$ cd /tmp/
# q' G$ p2 U& v5 G% K7 Z& H7 Y* a! N6 T5 @. T6 \/ h7 }
$ tar -cvzf pello-0.1.2.tar.gz pello-0.1.24 c4 J" S7 Z1 D( y% V: W
pello-0.1.2/4 _- ~' S2 f4 D* \
pello-0.1.2/LICENSE9 w6 e' G. G* g' O; D
pello-0.1.2/pello.py/ h$ P3 l! G) C- w- k% m) \
5 i3 B% q$ u6 V8 H _+ y$ mv /tmp/pello-0.1.2.tar.gz ~/rpmbuild/SOURCES/6 {9 F" K, Q+ N& U
有关 Python 编写的示例源代码的更多信息,请参阅 第 2.1.1.2 节 “使用 Python 编写 hello World”。
% u1 E. Q6 g' I7 |: h& D4 N* _' d" N
2.7.3. 将 cello 项目放入 tarball
" t6 ]; [$ L- q+ Q复制链接
' ]9 v- \6 Z' l7 Zcello 项目使用 C 实施 Hello World。实施仅包含 cello.c 和 Makefile 文件,因此生成的 tar.gz 存档除了 LICENSE 文件外有两个文件。
8 F J9 O( ^1 ]. _$ G
) h9 ?% E( ~' m7 e6 L5 ^( r; r注意+ d" C( d$ G( z% z- ?: n* ~
补丁文件 不会在程序的归档中发布。构建 RPM 软件包时,RPM 软件包程序应用补丁。补丁和 .tar.gz 存档一起放置在 ~/rpmbuild/SOURCES/ 目录中。1 H* K) e. ~: u
! E# ?' u/ _3 a此步骤演示了如何准备用于分发的 cello 项目。4 J, E$ m$ \8 i' G" ~/ c
, O, k d. I1 ]- |! a1 d2 c
先决条件
% H: z+ ^8 _; z5 C1 G* G
" P1 F# H" X; P. Y: k认为这是程序版本 1.0。
' _) f9 \' O# x0 e8 @* m3 R1 p5 o0 o0 d8 G _1 F* _% ~
步骤
$ p' s; R1 n+ N, e
- N0 g7 o+ } X" l! Q2 ], U, h将所有需要的文件放入一个目录中:- H$ Y0 A8 w* U) j0 T
7 I [$ p1 @* O* N2 t$ mkdir /tmp/cello-1.0% g3 R8 G$ C6 |6 Z
/ I: X; @' D% [ Y7 Q$ mv ~/cello.c /tmp/cello-1.0/
2 I y8 _. }- I' `2 _+ L% }, n: ~" ^& L6 N) q
$ mv ~/Makefile /tmp/cello-1.0/, `. b1 Q9 a# h- r; R5 {
3 Q3 [8 g: Q! {$ cp /tmp/LICENSE /tmp/cello-1.0/
+ I) K. _* {3 w为分发创建存档并将其移动到 ~/rpmbuild/SOURCES/ 目录,这是 rpmbuild 命令存储构建软件包的默认目录:9 L4 T. D% P# c# |5 z" N
: S, U5 Z" [; M% l
$ cd /tmp/6 s8 N Y* M' A5 j/ }1 q
! J! v, G A0 K$ b0 S5 r, }$ tar -cvzf cello-1.0.tar.gz cello-1.0
3 s4 G" p' i1 Ncello-1.0/6 D! M4 {2 ?% a6 L+ C
cello-1.0/Makefile8 p2 L1 w. f" f, b, {, f) d
cello-1.0/cello.c) }$ F2 K- |8 h
cello-1.0/LICENSE& w6 @6 J! D7 v$ J) k' h$ G
2 o" p* s+ A4 L/ d' {. J
$ mv /tmp/cello-1.0.tar.gz ~/rpmbuild/SOURCES/
5 P0 R7 W2 g; ]3 o添加补丁:
8 m% _5 K" W$ j$ d. `$ }$ w' M; m, r5 ~# d0 p" `9 P
$ mv ~/cello-output-first-patch.patch ~/rpmbuild/SOURCES/6 t v5 h" e1 j+ \& E
有关使用 C 编写的示例源代码的详情请参考 第 2.1.1.3 节 “使用 C 语言编写的 hello World”。3 H. p1 C/ \( X! K* z$ s5 X+ I
: S% z2 Z) w1 a3 J( g( @+ S
第 3 章 打包软件 ! t% V8 w0 ?& r" Y/ C2 W
复制链接9 u' Z/ @, g. |
3.1. RPM 软件包 ; S K% D* U1 T( D1 v
复制链接& n0 A: q1 e& y6 Q
本节介绍 RPM 打包格式的基础知识。0 c2 q2 t( K( l* O: H Z# ]
. g7 j8 F$ m& P5 n3.1.1. RPM 是什么
. s. t0 m' E8 B' E' I复制链接
+ }/ S+ p. a" |5 C }9 tRPM 软件包是包含其它文件和元数据的文件(系统所需文件的信息)。. s2 B$ U/ O o. y& |% l B! F
; n# C9 g& t8 b3 ?7 [. }
特别是,RPM 软件包由 cpio 归档组成。
" D- M# F) s) |0 O L% j. ]% F9 P _7 M& j2 E( ~$ T( ^
cpio 归档包含:
4 Y6 R3 l* W, ?# d: k7 V0 m w
d; ]# g1 C" P6 U: Z9 h) u3 U文件1 a3 S8 d0 m6 ?' b/ t$ J, B, B
RPM 标头(软件包元数据)
( ~0 U, q$ r* y3 s# Q- x% S& N$ g9 D& R
rpm 软件包管理器使用此元数据来确定依赖项、安装文件的位置和其他信息。
/ d/ `! @: x$ M4 m$ i+ G$ V8 w8 O+ d# Z% v% Z4 E: e
RPM 软件包的类型
/ G# F/ m9 A# }2 E/ S& F2 y7 vRPM 软件包有两种类型。这两种类型都共享文件格式和工具,但内容不同,并实现不同的目的:( d: t+ O- N6 S- p
* h# [ q8 ]% f$ b0 Z9 m源 RPM(SRPM)
( S9 L/ N. ?: k' L0 m' y) S9 C* H" V Y4 h0 v9 E/ E
SRPM 包含源代码和 SPEC 文件,这些文件描述了如何将源代码构建为二进制 RPM。另外,也可以选择包括源代码的补丁。
# _$ w W, f2 U/ Q7 g I \; U! z) Q
; R w u5 h. \( ]3 n二进制 RPM
6 k0 B1 F7 h) f Q/ I2 O8 {9 ~5 z3 B
一个二进制 RPM 包含了根据源代码和补丁构建的二进制文件。8 j, ~+ m- o4 C7 F" y) T
6 E/ z( M" T: ]* Z; A
3.1.2. 列出 RPM 打包工具的工具 6 }1 T" Z3 H% D9 p' J6 m
复制链接
4 s7 C- _8 c0 I. e以下流程演示了如何列出 rpmdevtools 软件包提供的工具。
0 Q" h6 F6 y/ |( \: w' V, u; }% K9 g, D2 _5 v' V3 h
先决条件: x* m& R2 J8 w# c6 o6 N: {; U
' @" H! g% g8 ^9 G
为了可以使用 RPM 打包工具,您需要安装 rpmdevtools 软件包,该软件包为打包 RPM 提供了多个实用程序。
8 d. U+ x( v3 @2 b2 D
X9 t# e# M* D% p# yum install rpmdevtools
, j* X, I" j& S( I1 E) i流程
% z9 \7 ~$ A: w; V- C$ R0 U. L- \9 W2 f1 i
列出 RPM 打包工具的工具:2 q; K( Y. @3 f/ m, z
1 G7 @1 F7 d0 Y1 x% P; S" Z4 [$ rpm -ql rpmdevtools | grep bin
- m9 f x( h3 |1 u' m; e附加信息
* r7 ?/ [4 d; K3 Z; S! v) ^. `* h. }1 Z
2 x8 n4 @! h. R. K1 _, g7 C8 E有关以上实用程序的更多信息,请参阅其手册页或帮助对话框。9 J8 ]( J( S; R8 M! }. M
3.1.3. 设置 RPM 打包工作区
( D& \! V6 {- }5 f* L$ [- g复制链接& s9 r! ]4 X2 Z D& o
这部分论述了如何使用 rpmdev-setuptree 程序设置属于 RPM 打包工作区的目录布局。
) d+ Y$ i0 L+ b M
" T- t! A/ x! M, W* |0 M4 m- \: t先决条件
7 D) T( w" n! |
' s2 J) z$ v" B: h4 h" t在您的系统中必须安装 rpmdevtools 软件包:0 u: J( D: s: w+ T& b" j4 p
' { a# r9 {/ l/ i' {+ O# yum install rpmdevtools/ i4 O9 I9 j/ Q4 E* n
流程
; Z" C6 z( V) g1 v; o6 @# \& P0 O: [; Q% y
运行 rpmdev-setuptree 程序:
8 ~+ s8 U; C _1 t* i1 L- C. e. `$ rpmdev-setuptree5 Q' l9 C$ {) k3 O2 i* W
$ E4 Z& }$ t3 p# m0 r! m$ tree ~/rpmbuild/5 ^: D5 P5 G$ ^: |
/home/<username>/rpmbuild/
6 \) k0 o; ]$ K3 r/ K( ^6 L4 g3 @|-- BUILD
$ o6 v6 p5 {6 n$ X& w$ g3 u+ S8 y1 }6 f0 u|-- RPMS
: X9 a' \. x5 M, U4 P6 h* {|-- SOURCES
3 k) A( O: N$ t( b% W5 h|-- SPECS7 E" G" Y: N7 `7 `- S# b3 Y1 t, k! }
`-- SRPMS
0 r8 O' ^0 [. p# _- N4 K0 h1 X# g- A, \3 M) V4 } [+ \
5 directories, 0 files- q2 y) ^* Y' Z% r7 Y2 C1 I
创建的目录用于这些目的:
0 ]& ~( M& q, A. @8 {+ d
% W( `# t3 U4 g- L# U' Q目录
2 M: Z" l$ f; Z$ N+ }6 i" U/ E2 y! Y/ ]0 @5 Y: M9 i
目的2 {' M; [* `! `/ D7 U" `
! |; |! f* K" ^6 w, k7 i# X3 u
BUILD3 [ V% r0 z) f7 U2 U" ?- h- h
# R5 E# [, z: J9 {3 {9 t构建软件包时,会创建各种 %buildroot 目录。如果日志输出没有足够的信息,这可用于调查失败的构建。
. S' k7 P1 l+ ?& m& u) N
1 s4 b. \% T' b+ T2 Y* SRPMS1 ?- v+ {# e2 O4 {
, l9 \# }* ?9 `" Y! _
此处创建了二进制 RPM,在用于不同架构的子目录中创建,例如在子目录 x86_64 和 noarch 中。
$ i3 T0 D/ y" s/ N4 \7 J
$ {: l/ T, I) V源
6 l- r ]$ g0 ~* m5 M# K+ @% P u1 ~8 f& b
此处,打包商放置了压缩源代码存档和补丁。rpmbuild 命令将在此处查找它们。
8 ~. y% N) h. a. G% D7 L! W2 R5 \ T" W0 t/ O+ ]" u6 F
SPECS" y( `; x- g6 J4 D
* G; t( b: d. \, N4 C+ X; g( ?软件包程序在此放置 SPEC 文件。$ u9 [4 T6 O+ V2 U
- s7 n1 c! e* x
SRPMS9 f' S4 V5 ?$ ]+ ?* I; W
6 ^" _/ r7 ]1 d' O+ `
当 rpmbuild 用于构建 SRPM 而不是二进制 RPM 时,会创建生成的 SRPM。
+ o: m* l5 s" }" _) K& D0 y: B3 @, e
3.1.4. SPEC 文件是什么 0 t5 m- m3 x/ }$ V! s# c8 f
复制链接
" m* S# {, b4 F9 r5 u& W+ O0 g& ~您可以将 SPEC 文件作为 rpmbuild 实用程序用来构建 RPM 的配方。SPEC 文件通过定义一系列部分中的说明,为构建系统提供必要信息。这些部分在 Preamble 和 Body 部分中定义。Preamble 部分包含一系列在 Body 部分中使用的元数据项。Body 部分代表说明的主要部分。1 W5 c2 U" w! k* F* p1 [$ W
; a: g& b( `0 m% V" b
3.1.4.1. Preamble Items # X# p( Y' Z, d2 R+ K7 k7 S
复制链接
. L( Z& H9 g) C下表介绍了 RPM SPEC 文件的 Preamble 部分中经常使用的一些指令。! J S1 |) R9 I4 }4 b
1 {4 M$ S1 x3 V- g- d
* o- ~ o. j" U1 a8 U8 v5 s表 3.1. RPM SPEC 文件的 Preamble 部分中使用的项目
- N5 G; b; q: k# P: a7 N, }: b( p. GSPEC 指令 定义
3 s# D# b. m9 _# R名称
# ]* i* I& B' m2 q( L7 y* B
, _' Y; k# ^1 j- J) b& l# ?$ r软件包的基本名称,应该与 SPEC 文件名匹配。: [$ k. n: d9 p5 S
; u! }. b O: j: z5 }4 Q版本; l4 G# a. f- T3 y- O2 ~4 T
" l$ L" U5 a; d: ~9 w
软件的上游版本。
: b. ?3 s2 f0 p% t7 Q. e* J6 q8 I, @ O1 x! ~/ l+ N
Release$ _4 g2 {8 P) c5 K; g. P4 y
% v7 X+ ]9 y6 ?发布此软件版本的次数。通常,将初始值设为 1%{?dist},并在每个新版软件包中递增。当软件的一个新版本构建时,将重置为 1。
b7 ~' x: a; l/ r& B' B' R- l% H, j
概述 [7 N1 q! G( S" ~7 }
. h0 S2 s% [+ y6 E软件包的一个简短总结.
7 v( n- m; M6 u. R0 n S1 S
# u# g K1 p0 T2 _* i许可证( Z6 H9 I6 A' @" g9 H2 t
1 [9 q0 J' W( L0 C所打包的软件许可证。
7 I- N5 k. ~; p q) M5 Y8 X9 i4 v" c4 F' I2 `! a
URL% z: g. g9 h; J9 |3 a
6 U/ _, y/ v8 a& B
有关程序的更多信息的完整 URL。大多数情况下,这是所打包软件的上游项目网站。
4 k9 u; {1 H9 v" B
8 o- |% s* g& v, o( h oSource0% n E, x) ?: n! {
8 x. y' T4 |1 O$ ?上游源代码的压缩存档的路径或 URL(未修补,补丁会在其他位置处理)。这应该指向该存档的可访问且可靠的存储,例如上游页面而不是打包程序的本地存储。如果需要,可以添加更多 SourceX 指令,每次递增数字,例如: Source1、Source2、Source3 等。% y- N" s( g7 N0 Q1 [" `8 c% R- U
1 e6 q2 J- h, e5 w; @. D/ i0 w
Patch
- f; u- F, X2 m. a8 g% _3 t, Z7 ?2 z/ c0 W1 Q- k) m
应用于源代码的第一个补丁的名称(如有必要)。
4 D6 Z9 c( w; u7 n) z
& [& M6 q1 b3 `该指令可以通过两种方式应用:带有或不带补丁末尾的数字。. C& x- K7 D w) u0 S ~8 L' M
' U: }' s" z# a* b" `- Z- }
如果没有指定数字,则会在内部分配一个条目。也可以使用 Patch0, Patch1, Patch2, Patch3 明确提供数字。
9 l$ i+ x) C8 _2 |
& O+ I3 G: V" S1 @0 C8 {这些补丁可以通过使用 %patch0、%patch1、%patch2 宏等应用。宏在 RPM SPEC 文件的 Body 部分中的 %prep 指令中应用。或者,您可以使用 %autopatch 宏,以 SPEC 文件中提供的顺序自动应用所有补丁。; z: F+ A, p; T. b1 o
! v! {( P9 N+ Z- T, hBuildArch
4 ~* r4 c2 b2 w7 i) v4 z2 L7 e% a
0 r6 f/ m% g" |/ w) ^: t如果软件包没有架构依赖,例如,如果完全使用解释编程语言编写,则将其设置为 BuildArch: noarch。如果没有设置,软件包会自动继承构建机器的架构,如 x86_64。5 D% k6 S1 f0 p0 k; V
4 x$ n% [' w$ v8 s N
BuildRequires _' _8 Q# o% L; E: L" y
* ]7 e' d3 `5 X2 V' [
使用编译语言构建程序所需的逗号或空格分开的软件包列表。BuildRequires 可以有多个条目,每个条目都在 SPEC 文件中的独立的行中。
; W8 i& C1 @ q' B2 @* x2 {! h4 A3 n. B& u
Requires
6 u6 l( o; N" ]4 z: x0 V/ W* ?; p% a3 t8 U' X% }/ a# p
安装之后,软件需要以逗号或空格分开的软件包列表。Requires 可以有多个条目,每个条目都在 SPEC 文件中的独立的行中。2 ]6 ~# Z: t! _5 o2 Y( a( S
: E; Q5 ^: \3 Q2 P$ d
ExcludeArch2 G5 o1 u X2 _" @6 d
E9 n6 o# ^$ b0 a& B9 k- q& K1 Y* U6 @如果某一软件不能在特定处理器架构上运行,您可以在此处排除该架构。4 U3 ^; n% s( G1 `; T
G+ x* z6 U! g* `& w; h' V0 M
Conflicts1 u- n0 x* x0 E9 l: w
`, p6 [% P' E# H% b9 OConflicts 与 Requires 相反。如果存在与 Conflicts 匹配的软件包,则软件包是否可以安装取决于,带有 Conflict 标签的软件包是否位于已安装的软件包中,还是准备要被安装到的软件包中。
4 }* H2 f# H5 Y5 y4 B7 M9 \0 [) v9 ?2 U5 s/ [4 q* v, h' ?8 ^
Obsoletes
p: F( u: m$ M& N. K5 T; \7 o/ c! A" r/ j' ?
这个指令会改变更新的工作方式,具体取决于 rpm 命令是否直接在命令行中使用,或者更新是由更新还是依赖项解析程序执行。当在命令行中使用时,RPM 会删除与正在安装的软件包的过时匹配的所有软件包。当使用更新或依赖项解析器时,包含匹配 Obsoletes: 的软件包会作为更新添加并替换匹配的软件包。7 p) a! l0 t* P9 j# C
- V$ Z# ?1 P* j! x0 H* S
Provides
! y/ _/ W8 O, V" ? Y5 C0 x+ ]" s) f) I
如果向软件包添加了 Provides,则软件包可以通过名称以外的依赖项引用。: r: Z6 G! r1 _2 Y" k
4 N' W3 M0 t. l% g# t$ }, A+ ]9 oName、Version 和 Release 指令包含 RPM 软件包的文件名。RPM 软件包维护者和系统管理员经常调用这三个指令 N-V-R 或 NVR,因为 RPM 软件包文件名具有 NAME-VERSION-RELEASE 格式。
7 X9 T3 _* \6 |4 J1 b. Z) s
T' s& r) S) P: F$ P7 {( G以下示例演示了如何通过查询 rpm 命令获取特定软件包的 NVR 信息。 L" E3 Z/ F; D! u
* f1 @. r9 s) g0 v+ M( S例 3.1. 查询 rpm 为 bash 软件包提供 NVR 信息/ P5 ^, |& s9 k+ H x/ a
7 L' v. h% ?* ^/ n* C2 `0 s0 L$ rpm -q bash) u' }( q9 n% K, K
bash-4.2.46-34.el7.x86_64% G# ~5 E; }: m2 _- [) g- U
在这里,bash 是软件包名称,4.2.46 是版本,34.el7 是发行版本。最后的标记是 x86_64,它向架构发出信号。与 NVR 不同,架构标记不直接控制 RPM 打包程序,而是由 rpmbuild 构建环境进行定义。这种情况的例外是独立于架构的 noarch 软件包。. k/ p0 t( [* Q1 T0 x% |7 v' s2 A/ d
6 }: ?6 v7 A, F3.1.4.2. 正文项目
z/ S4 r* Q1 p, p9 j- m$ k# o- i复制链接
9 J3 i0 X; g6 a, \4 u& M' R ~下表列出 RPM SPEC 文件的 Body 部分中使用的项目。
2 j5 i7 M6 m- i9 g8 }7 b8 y
& @: j1 C6 P/ [2 ]表 3.2. RPM SPEC 文件的 Body 部分中使用的项目4 W( O/ L" O$ g: y# b/ o
SPEC 指令 定义& q- q Z3 S/ Z+ F& p
%description# Z7 |% L7 n8 S4 I& ?% h2 A
: D+ w, \, p) u1 a- X9 c. }
RPM 中打包的软件的完整描述。此描述可跨越多行,并且可以分为几个段落。% |6 L6 \$ g/ m- V7 b8 o
7 r; c& l9 `. s0 Q- ?+ R1 m
%prep+ e, v8 T; V2 u
8 n% r8 V' R3 K用于准备要构建的软件的命令或一系列命令,例如,在 Source0 中解压缩存档。此指令可以包含 shell 脚本。1 I9 ^! f$ {0 a+ y
* x" E, n: M3 h%build
8 |. F. X7 ]; d0 b9 R7 s/ k( Z' _# n& W7 }& X: U
将软件构建到机器代码(用于编译的语言)或字节代码(用于某些解释语言)的命令或一系列命令。
4 W9 R& h0 C H: T& P* T: [( j+ W+ P9 y! T. B: g+ R# ^! c
%install
$ s8 e) s' K! G: }3 c5 S0 X1 L& B2 E" Y9 _
命令或一系列命令,用于将所需的构建工件从 %builddir (构建发生位置)复制到 %buildroot 目录(其中包含要打包文件的目录结构)。这通常意味着将文件从 ~/rpmbuild/BUILD 复制到 ~/rpmbuild/BUILDROOT,并在 ~/rpmbuild/BUILDROOT 中创建必要的目录。这仅在创建软件包时运行,而不是当最终用户安装软件包时。详情请查看 第 3.2 节 “使用 SPEC 文件”。
) d7 s; ?, Z) J6 S
! E0 N9 c, c, D- S }%check
0 l- {) _0 ~, M6 i
2 _, W& u! d! U$ f5 M用于测试软件的命令或一系列命令。这通常包括单元测试等内容。* c( G7 I) F, z) l. E2 ~
. F. {8 c# I7 n5 ]%files
1 v' Z: \. d3 }% Q4 f9 z7 w! Y4 D! y! F9 o
将在最终用户系统中安装的文件列表。
8 o4 e1 Z! L$ \- s+ l" N# ~) ^" B b
%changelog" ^1 f! h0 t) T+ H# Q
+ i: }0 v+ v& W5 E9 F* }在不同 Version 或 Release 之间软件包所发生的更改记录。- J8 J+ b6 O% d8 C/ ]1 ?
0 J; N9 }# O" h9 h: ]
3.1.4.3. 高级 items 0 s+ W3 s* b" U7 T) T* u& `
复制链接
" D7 k" p+ Y- A$ N$ [SPEC 文件还可以包含高级项目,如 Scriptlets 或 Triggers。它们在安装过程中对最终用户系统而不是构建过程的不同点生效。
+ b7 w- {) K; m; u4 \) g- k7 O1 h0 q- G0 _# E3 q; k
3.1.5. BuildRoots : Y( R" Z s9 X7 v6 V- Q
复制链接6 r+ H! T/ a* X+ d) j
在 RPM 打包上下文中,buildroot 是 chroot 环境。这意味着,构建工件被放在使用与最终用户系统中未来层次结构相同的文件系统层次结构,并将 buildroot 用作根目录。构建工件的放置应遵守最终用户系统的文件系统层次结构标准。2 s8 C! a! X. C( s( b+ Q, z7 ~
2 u5 m" `+ O* H: V( c! d; ^
buildroot 中的文件稍后放入 cpio 存档,后者成为 RPM 的主要部分。当在最终用户的系统中安装 RPM 时,这些文件将提取到 root 目录中,保留正确的层次结构。 u& A& _/ A- v
/ V; V% c' [6 a& b注意/ i' V8 j; h6 |
从 6 开始,rpmbuild 程序有自己的默认值。覆盖这些默认设置会导致几个问题,因此 {RH} 不推荐定义这个宏的值。您可以在 rpmbuild 目录中使用 %{buildroot} 宏。/ e# i t, v {3 [# R
4 o/ H: J. p! `" m5 M
3.1.6. RPM 宏 3 g# U7 k8 D7 I! h% D: {- t; f
复制链接
. N3 t T5 {9 O- _( Y3 Nrpm 宏 是一种直接文本替换,在使用特定内置功能时,可以根据声明的可选评估来有条件地分配。因此,RPM 可以为您执行文本替换。
" R2 l" X: @; F: p
7 H: H: i# E, l* `" J, U9 _! G示例用法是在 SPEC 文件中多次引用打包软件 Version。您仅在 %{version} 宏中定义 Version 一次,并在 SPEC 文件中使用此宏。每次出现时都会自动替换为您之前定义的 Version。' |4 `4 q) q+ q+ I/ v" @0 c
( _; v, q2 i- i- M2 G注意
: L# k1 E( Z4 T `' y如果您看到不熟悉的宏,您可以使用以下命令评估它:) r, v! I1 E: W
* C9 ?# t- U, ?% k6 z
$ rpm --eval %{_MACRO}5 x* M; M0 B$ ~% C$ q2 s$ X
评估 %{_bindir} 和 %{_libexecdir} 宏
- t) _$ x, d `% d9 m" u! n# N% \$ J. P- x
3 W" C- n/ x9 S
$ rpm --eval %{_bindir}2 y( F" {6 z( L
/usr/bin0 ^0 f( m7 b8 x9 n
/ ?9 i g" K; C' r$ rpm --eval %{_libexecdir}
& ~' {2 g; |3 A5 _- I6 |/usr/libexec6 C) M9 o9 y5 {2 Q; X
常用的宏是 %{?dist} 宏,它向哪个发行版发出用于构建的信号(分配标签)。
" b% ~( K, y7 K$ F3 o3 {& `/ |5 \) F
# On a RHEL 8.x machine
" |5 {" f- {* y. q, \$ rpm --eval %{?dist}% W2 ~5 _& q& n
.el8
$ U, O. O: J! A. m8 i/ a8 |3.2. 使用 SPEC 文件 ; w8 e: Q: c a: o
复制链接, U- Z$ f3 S7 \
这部分论述了如何创建和修改 SPEC 文件。
1 \2 x4 c2 }$ w" O2 u/ V7 v) g2 P
6 y6 | ?5 `* z1 c0 e/ V. L3 p7 M先决条件
/ c5 k6 x: g8 q) i/ k3 B _" L- N8 U+ d1 f4 Y
本节使用 第 2.1.1 节 “源代码示例” 中描述的 Hello World! 程序的三个示例实现。
- B& Y. L5 c+ x; d0 [- ^, L0 H4 o( O, ~4 n9 p1 _7 |
下表介绍了每个程序。7 `! V+ r9 W- ]
?$ H: K, q- s. P8 e2 E2 b% t8 P
软件名称- d: t, |. ?0 ^6 s5 |6 Z
5 f* p, t$ v4 s- E3 x% H. o- h
示例说明
0 v5 n1 G2 G9 N h4 [2 d; z' a. y; ?& U0 v: B
bello
+ ^ K: X% x- B- x
; P. V1 {9 }" a( ?6 z# b程序使用原始解释编程语言编写。它演示了,当不需要构建源代码时,只需要安装源代码。如果需要打包预编译的二进制代码,您也可以使用此方法,因为二进制文件也只是一个文件。
1 |% x9 M/ z( W9 v1 e& M3 }4 F7 L0 F r! b, w
pello, ~9 y S: ?3 d/ J
8 \$ k+ b: l5 f" [3 ` N
程序以字节编译的解释语言编写。它演示了源代码的字节,并安装字节代码 - 生成的预优化文件。; I! n0 M# k3 f& n- W8 p( b4 V
; W# l+ k" q9 r
cello
8 J1 k% ^4 {" a# I2 v5 |; Y7 C! @" J a4 S8 N% j
程序使用原生编译的编程语言编写。它演示了将源代码编译到机器代码中的常见流程,并安装生成的可执行文件。8 `& d7 x4 \! X0 n0 d6 E8 z
7 I$ p! u1 u1 P0 c9 e) c" @ e7 _3 BHello World 的实现是 :
6 g4 ^3 H+ x# B5 G5 b% Z/ _! F# m! I; x3 Y5 L( A
bello-0.1.tar.gz
' I# n& u7 g5 ypello-0.1.2.tar.gz8 h6 _8 o, [$ ]/ U% j9 @
cello-1.0.tar.gz; d9 L: ]. o; X" Z a! T7 U
6 @- m6 k v( d- }cello-output-first-patch.patch. T. y' X @( {: @
作为前提条件,这些实施需要放入 ~/rpmbuild/SOURCES 目录中。" {3 X. P# A* O- k6 V2 N
" l0 \7 j& N% t( G3.2.1. 创建新 SPEC 文件的方法 0 k4 o. @ o6 j: w0 u9 [" v1 I" z
复制链接
7 N; B: J) @& J- k: h8 p( Y" v要打包新软件,您需要创建新的 SPEC 文件。) [& {2 }) X2 N3 p
7 T1 j$ K- h* m# _$ L; P- u
实现这一点有两个:
: W- U) s l3 u& j, ~/ p ]3 v2 S: j" m& a5 O( e
从头开始手动编写新的 SPEC 文件8 j" d9 X! Z* k2 b0 b
使用 rpmdev-newspec 工具" v8 C) \% K. I
+ ?1 p0 G% z6 k& G
这个工具会创建一个未填充的 SPEC 文件,并填写所需的指令和字段。+ a4 E, j- `; M& G
8 {6 [& V' Y1 m. r注意$ n5 ^* W0 {) m! o
某些以编程为导向的文本编辑器,预先使用其自身 SPEC 模板填充新的 .spec 文件。rpmdev-newspec 实用程序提供了一个与编辑器无关的方法。
% H. w! G; M( j& P
. s9 {+ c8 g, N- i1 S3.2.2. 使用 rpmdev-newspec 创建新的 SPEC 文件
: ?! r& D$ G, [+ ~2 d复制链接
2 x, o. U* v6 D& B# l5 P5 U1 i以下步骤演示了如何为上述三个 Hello World! 程序(使用 rpmdev-newspec 程序)为每一个创建 SPEC 文件。
6 O2 T; J }0 ?) C
' Z" ?" H& s' j& Z7 X' c步骤$ h* `+ n* ^; w) ?# D0 {: _* Z
2 D! g% Z- L( l6 B9 g# k+ d4 A. s进入 ~/rpmbuild/SPECS 目录并使用 rpmdev-newspec 实用程序:; B3 ]8 j6 d4 A1 A$ \
# }5 M+ g X6 n T$ cd ~/rpmbuild/SPECS
h% }2 K# Q8 |% q0 Z e- F. Z5 [1 t( A8 |- [1 p0 H
$ rpmdev-newspec bello8 A8 T8 o& i2 g& _2 W" E: s8 P
bello.spec created; type minimal, rpm version >= 4.11.: S$ G/ K( g5 X& q
8 f: `- K; x4 W* y/ U9 n7 B- z$ rpmdev-newspec cello; M- ~5 y7 y9 Z# H# N
cello.spec created; type minimal, rpm version >= 4.11.
9 J3 E4 }5 B w, d# A
2 p) j" A+ |6 F# f1 [" N% |9 Z" |$ rpmdev-newspec pello
' _# t; O; O, z3 qpello.spec created; type minimal, rpm version >= 4.11.
1 j% E; \3 d' H% ~8 @~/rpmbuild/SPECS/ 目录现在包含三个名为 bello.spec、cello.spec 和 pello.spec 的 SPEC 文件。) @- s6 q* F. t* h. P. p
) V, G/ L! h# O; v2 P& c! y: vfd。检查文件:+ ~1 n. K2 t7 J- Z& U
1 \! D$ E, q( t4 B
+. R7 {- \. M- b6 W2 u% u
$ t2 o. h+ `. o3 y注意
0 X/ s! a+ q" R8 I: M- L: I' Crpmdev-newspec 实用程序不使用特定于任何特定 Linux 发行版的指南或约定。但是,本文档的目标为,因此在 SPEC 文件中引用 RPM 的 Buildroot 时,最好使用 %{buildroot} 表示法而不是 $RPM_BUILD_ROOT 表示法。 l; [' L9 O, K. z* V9 g. D
{+ ~, C! t; f8 R. {
3.2.3. 修改原始的 SPEC 文件以创建 RPM
* T9 k! Y5 Y/ _1 Z) L复制链接
- `5 ?, t; B% R9 X" w以下步骤演示了如何修改 rpmdev-newspec 提供的输出 SPEC 文件以创建 RPM。3 _/ o+ w& ?* p- ]- I+ w: N5 ?
J1 m4 l. Z% J. j# C先决条件
- D2 E7 W. h* P% r
; {+ U7 w4 T! r) l6 Q8 m. `; r8 `请确定:$ Y# I$ D! k# f7 `! K! S7 b/ ?8 O
7 R" c- S# e6 k7 ]
特定程序的源代码已放入 ~/rpmbuild/SOURCES/ 目录中。
6 u& Y7 z# F% K, O未填充的 SPEC 文件 ~/rpmbuild/SPECS/<name>.spec 已被 rpmdev-newspec 创建。
3 @1 t3 V4 w! A1 f- z/ Y2 `( t9 s& A步骤
% P" @: x6 F0 r( ? w$ u, \! t" {
+ B- i& X. ?4 ^8 {打开 rpmdev-newspec 程序提供的 ~/rpmbuild/SPECS/<name>.spec 文件的输出模板:/ [) r9 ~. t. S1 v7 p: S# S8 r
填充 SPEC 文件的第一个部分:
. f X; ~) D6 C8 G V: K9 h' E+ C" {; l; M2 Z4 P' b) s$ i( ?
第一部分包括 rpmdev-newspec 分组在一起的这些指令:
6 q5 g$ b: F$ f: Y1 Q% w
3 x. O! U" e% @. T$ Y: i D名称
7 `- D2 w* L' n0 g8 l6 }4 Q* b) I% i版本1 a# `" \7 t0 r. N U, f0 L$ H% W
Release
3 z) I7 {2 |2 u8 q概述
, R7 I. {5 s& y* W2 S
; H, e/ W! T6 f$ L" \, ZName 已指定为 rpmdev-newspec 的参数。4 W$ P/ u7 A' o9 m! X/ s
) d6 T# K8 ]/ _' u6 a! ^/ f) N m
将 Version 设置为与源代码的上游版本匹配。& ~, o/ Z. J; h4 R r! l1 O
, v9 B" {6 O1 X& ~' `0 URelease 自动设置为 1%{?dist},它最初是 1。每当更新软件包而上游发行版本的 Version 没有更改时(例如当包含补丁时),增加初始的值。当出现新的上游版本时,Release 被重置为 1。
) e @! ?6 z/ W! f4 m" Z
" X* l! e% `1 R/ c% dSummary 是该软件的简短说明。
, |0 ]6 K, x! c {% i
" R/ @" \* z+ L: `. Z填充 License、URL 和 Source0 指令:! Z+ |: T$ y3 N. I
" ?8 s) I" l) v8 iLicense 字段是与上游发行版本中源代码关联的软件许可证。如何在 SPEC 文件中标记 License 的具体格式将有所不同,具体取决于您遵循的基于哪个基于 RPM 的 Linux 发行版准则。
! q! ^1 |- a/ } k
( Y) t: z1 A5 b0 L1 ^例如,您可以使用 GPLv3+。% K* A/ x# P% |6 [, o& I& ^
. _$ w+ O: n8 x3 U
URL 字段提供上游软件网站的 URL。为实现一致性,请使用 RPM 宏变量 %{name} ,并使用 https://example.com/%{name}。( }# }: t3 b }; e+ u2 I
! m1 e2 g% m; N/ B/ ^% s4 s6 s USource0 字段提供上游软件源代码的 URL。它应直接链接到被打包的特定版本。请注意,本文档中给出的示例 URL 包括可在以后更改的硬编码值。同样,发行版本也可以更改。要简化这些潜在的更改,请使用 %{name} 和 %{version} 宏。通过使用以上,您仅需要在 SPEC 文件中更新一个字段。- i& x: q8 o/ b6 o3 o
9 h5 n o$ G! B! G. }" d
填充 BuildRequires、Requires 和 BuildArch 指令:
. y3 w; L: Z7 b7 _' \, D: E; a! b* t3 l0 L% ?5 H
BuildRequires 指定软件包的构建时依赖项。
5 q! S3 ?3 u* N" Q
h& K, \1 v5 ]; z8 S% L1 ~' O& oRequires 指定软件包的运行时依赖项。
% z6 y- V* o- o) B; n& L0 S5 M3 E. [& o' f% M# J- z; {' }) I
这是使用没有原生编译扩展的解释编程语言编写的软件。因此,使用 noarch 值添加 BuildArch 指令。这告知 RPM 不需要将这个软件包绑定到构建它的处理器架构。0 s& i. E3 S0 [* B) J
; Y" t/ {: X+ h6 n0 N$ L7 v1 g填充 %description、%prep、%build、%install、%files 和 %license 指令:
! z8 E' u" f8 T4 h/ i' @9 u9 x- `* M ]7 X* k! ]4 U
这些指令可被视为部分标题,因为它们是可以定义多行、多结构或脚本化任务的指令。
& e& V! l+ G, ?8 M0 J# ?: Z; K1 @& C. f+ t' h
%description 是一个比 Summary 更长的软件的信息,其中包含一个或多个段落。: R4 a8 \4 d- ^8 M! P& [
+ y: @8 l, o j
%prep 部分指定如何准备构建环境。这通常涉及对源代码的压缩存档、补丁应用程序以及可能解析源代码中提供的信息的扩展,以便在 SPEC 文件以后的部分中使用。在本节中,您可以使用内置的 %setup -q 宏。8 D( }4 r( C+ o1 `- z" a
- L' K1 G! K0 A, P/ T%build 部分指定如何构建软件。
4 Z, Y9 y5 k( k7 s+ O; x% z2 X
0 g/ s& y6 ^* W/ h, J' I( P5 t- X%install 部分包含在 BUILDROOT 目录中构建软件后如何安装软件的 rpmbuild 指令。4 Q+ w H0 h$ \
; ] F( [! g) Q x1 ~' p" b8 f2 {
该目录是一个空的 chroot 基础目录,类似于最终用户的根目录。您可以在此处创建包含安装文件的目录。要创建这样的目录,您可以使用 RPM 宏,而无需硬编码路径。8 }" F; ]; a9 A- n- T4 y% c$ n
- N; U: E% S; Z+ r8 F! X7 y" E2 ]
%files 部分指定此 RPM 提供的文件列表及其终端用户系统的完整路径位置。+ b; h( c s4 v P8 u
& |1 A; N' N6 o4 l( `" }
在本节中,您可以使用内置宏来指示各种文件的角色。这对于使用 command[]rpm 命令查询软件包文件清单元数据很有用。例如,要表示 LICENSE 文件是软件许可证文件,请使用 %license 宏。0 `, V" S0 o1 g' W& J
3 p& ^% C: T+ o0 t D/ X最后一个部分( %changelog )是软件包的每个 Version-Release 的带有日期戳的条目列表。它们记录打包更改,而非软件更改。打包更改示例:添加补丁,更改 %build 部分中的构建流程。" ^' |; _( ?, Z$ c4 A
4 x- a6 x! L/ u7 x$ ]4 Y在第一行使用此格式:) c; Z9 ]6 k1 h% J, c
; D4 R2 k% G$ d! X$ y8 p. J
以一个 * 字符开头,后跟 Day-of-Week Month Day Year Name Surname <email> - Version-Release
) f8 c8 w4 V. J0 P. e7 ?' n6 b# a& Z3 M, k
使用以下格式进行实际更改条目:4 z3 |2 e$ T" C* z; n6 C I/ |
' m; R0 e' W3 v! j每个更改条目都可以包含多个项目,每个代表一个改变。
/ m$ e- c/ q. \: Y* g4 Y每个项目在新行中开始。
) ~7 E0 }% ^8 ~2 ^6 v每个项目以 - 字符开头。
( V, d6 I4 n4 E: C2 L" }您已为所需的程序编写了整个 SPEC 文件。- Y+ w& |' A/ r5 @2 w! E! v
1 F" c5 K# J. l- ]8 S L
有关使用不同编程语言编写的 SPEC 文件示例,请参阅:% \0 _: Y) b3 P9 {( S
! B8 B, e- J3 _+ X& A7 `
3.2.4. 使用 bash 编写的程序的 SPEC 文件示例
8 V( W8 w$ u5 A复制链接
4 j Z( v0 u9 t W这部分显示了在 bash 中编写的 bello 程序的示例 SPEC 文件。有关 bello 的详情,请参考 第 2.1.1 节 “源代码示例”。' `. T9 i$ O, t6 z4 ?+ g/ J
- S2 u. L; a1 d( [6 Q% F! i$ ?在 bash 中编写的 bello 程序的 SPEC 文件示例( a, Y6 ~! n* q" i
( X4 {) C7 ?5 p6 m, H
2 t* m* a+ g9 D l g5 P2 qName: bello% ~. n5 @6 t& c$ j6 h
Version: 0.1
$ F3 T" d2 [/ e8 ?+ HRelease: 1%{?dist}
& c+ c+ a* V7 {- g7 z1 W3 Q7 vSummary: Hello World example implemented in bash script; N+ x, c/ v _" }+ z
+ J" t4 F C; Q" {, Q+ m {1 F
License: GPLv3+, A8 L- L: f2 H2 D6 s
URL: https://www.example.com/%{name}) S# m/ c% y0 t/ c
Source0: https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz- }' b, P; g' i$ v" N
- u0 b, k! i; Q7 W0 J
Requires: bash
4 c0 t2 [5 n( X) }! ^1 Q+ ~. g* }' ^! |4 N6 H9 }
BuildArch: noarch5 l% n1 l9 e/ p9 k; X5 Y
1 Q e" W4 o6 A: a9 C) B" G%description
" A& ?2 X- z% V) a5 FThe long-tail description for our Hello World Example implemented in) i- j: n0 M6 O9 `- K; B2 \/ @1 Y& |
bash script.
2 p$ c; \% \) R% b9 Y1 M3 h* L4 x$ L& B6 P' P$ y0 b
%prep
. O9 t; S _+ Y7 F: I; x+ X3 V%setup -q
$ l3 C* K% ?+ H4 Q' R' |) G# f
%build; }3 R; d% V5 n
3 N# I& g% i0 a# `6 Q%install. y) p& D9 D, C5 ?* [
! D# |7 e6 }) }5 D* o
mkdir -p %{buildroot}/%{_bindir}
- t6 }0 ]9 t6 c1 |: u h" q; a, ?, J! L% x- b
install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}; S* a6 D* u4 n
' V8 i* J8 \$ v
%files
0 ?1 E/ s# b& ?%license LICENSE* \2 T; p5 g: ]7 u3 s
%{_bindir}/%{name}
& G/ S4 S3 ?2 e3 U6 j. }
) J5 l2 w. W% M, V c" q%changelog& o2 e+ v3 L D) S2 p- L: i1 g6 N8 k
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1-11 } q. z2 p' b+ ]
- First bello package0 u( _ D. v; i: n# b1 w4 M8 ?
- Example second item in the changelog for version-release 0.1-1
# w3 t, p; \/ P4 k8 JExpand
2 d. F# {6 x7 {6 x9 S6 }BuildRequires 指令指定软件包的 build-time 依赖项已被删除,因为没有可用于 bello 的构建步骤。Bash 是原始解释编程语言,文件仅安装到其系统上的位置。4 v, E/ b# S) r
, P+ e, M9 b; z# ARequires 指令指定软件包的运行时依赖项,它只包括 bash,因为 bello 脚本只需要 bash shell 环境才能执行。
- B, J" k$ j" m; ]
- p) l- O' v6 Q3 N( g%build 部分指定如何构建软件为空,因为不需要构建 bash。6 Z& t3 U4 M* r% K! W1 ~
! i& a4 O9 d6 R: M( S+ ]
要安装 bello,您只需要创建目标目录并在其中安装可执行的 bash 脚本文件。因此,您可以使用 %install 部分中的 install 命令。RPM 宏允许在没有硬编码路径的情况下执行此操作。3 D3 y* k! F/ Z& q
; n- o! z- N* ]% N, R" X9 i' r! e
3.2.5. 使用 Python 编写的程序的 SPEC 文件示例 8 p* q/ D. s0 {# `) ]$ G
复制链接. X+ p7 J4 j0 L9 v
本节介绍使用 Python 编程语言编写的 pello 程序的示例 SPEC 文件。有关 pello 的详情,请参考 第 2.1.1 节 “源代码示例”。* @# Q6 ^9 _! ^! A
% l4 L# m$ i/ b5 p/ a1 A) V+ C使用 Python 编写的 pello 程序的 SPEC 文件示例7 e f# v1 N. w9 Z! e' \
. `% G/ H4 t" ?. F) |% N
* f, Q' }( \* C* J3 DName: pello
8 X: B0 L4 K* k& |Version: 0.1.1
1 _2 b- t3 x* U) z$ {& tRelease: 1%{?dist}
) _- A( `" @% y' |Summary: Hello World example implemented in Python
, k& f* e. b; ]# I& L) {" X6 u8 X3 a2 }) s. R+ X; j1 a- [' U. p
License: GPLv3+
$ c8 Q3 A) j$ k9 w( _+ L7 V" cURL: https://www.example.com/%{name}
$ ?4 {! c+ x5 d& \% D% C% w) h ESource0: https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz
' |/ Q! M. Q) ?; ?& I# I4 }
% M# W1 Q* W2 A9 Y. JBuildRequires: python, m$ K! C3 Y( T5 F; W
Requires: python5 D( b( ]5 K' H7 X9 b0 p; R; z
Requires: bash
b$ d F! A3 ~7 M1 I9 K( f/ n+ E* _: \. K1 j" n
BuildArch: noarch
0 {1 l7 a4 {& {2 E
6 Q7 p( b1 p- A# _6 m' P%description
! q y: k6 u) ]: h3 G1 |% gThe long-tail description for our Hello World Example implemented in Python.! d8 ]! Q2 W h0 H
; u& L* O, f- d A% u* P%prep
) m- _, K: q4 F9 ~8 Q+ l%setup -q
( q: \. J- ?& l, _, C+ R7 ^9 o. X l0 E
%build
9 _ r) L' m; W! x
$ {& F E- \9 D( p$ ^- D& s8 a; xpython -m compileall %{name}.py
# O; k* g0 p& ^) y
/ k; t. o( g% M# R4 s%install
, E3 g" p' n1 k7 e$ o- K3 |
B+ n$ T% M8 h4 k/ G- }3 l7 imkdir -p %{buildroot}/%{_bindir}5 ^9 M8 n S: ?$ E1 x9 u b
mkdir -p %{buildroot}/usr/lib/%{name}
' [( x: o+ N) c, s n8 b+ H/ d$ }% E1 J2 \2 j
cat > %{buildroot}/%{_bindir}/%{name} <←EOF
9 B; X4 \* c( G# |) H#!/bin/bash# a" T9 U- ]" E8 _5 V' w4 [9 G+ `
/usr/bin/python /usr/lib/%{name}/%{name}.pyc% L; L( o, q4 X) h# D3 Q- a
EOF/ b0 N) n* r% w6 _8 l7 X' C
1 z9 X# f# s8 l# c* `6 i
chmod 0755 %{buildroot}/%{_bindir}/%{name}* N1 t. W/ W, |5 n% T
4 W$ k; ~! R) _: [9 ~ }7 J
install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/
+ S2 {; i! n$ [/ R" ]
; I* O" [& j0 P( x! P4 W/ z%files
7 A: \5 n2 U) O3 K+ w%license LICENSE$ L( i7 M' D* S8 [
%dir /usr/lib/%{name}/
# `, N+ M' Z5 O8 g" O6 ?+ r) W%{_bindir}/%{name}1 h# ^: t) }2 ]: b- m/ i1 ?
/usr/lib/%{name}/%{name}.py*
. u: P- b5 R& L. A1 \
1 k5 \9 D* `4 o, r i%changelog( U% T/ @, J4 r3 T/ }' p
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 0.1.1-1
* w b1 B( B8 R - First pello package
; J- r# r1 C# _# Q" SExpand5 G, w" v; M6 V6 }" \9 z
重要; }. k, t( x2 c6 ?; ~6 P" U6 H
pello 程序以字节编译的解释语言编写。因此,shebang 不适用,因为生成的文件不包含该条目。
5 ?5 z5 D) u" @3 ^. ~) Z y( s+ W6 w5 o, U( S
因为 shebang 不适用,您可能需要应用以下任一方法:3 H8 c7 ?. C$ Q2 p" ]
5 D/ W& [: A! _0 i6 [9 L0 A创建一个将调用可执行文件的非字节编译的 shell 脚本。1 ?1 Z: Z, U4 {, p' q# h
使用一小段 Python 代码,它不是字节编译的,作为程序执行的入口点。; c. r m: a z% |
这些方法对于具有数以千计的代码的大型软件项目非常有用,因为字节编辑代码可以提高性能。- O: P |$ m/ N0 v" S% y
4 U5 [2 X3 p; L- v& sBuildRequires 指令指定软件包的 build-time 依赖项,其中包括两个软件包:+ l$ J8 N1 z: z q8 _, f
) u- V' K1 X( J- [. X% x
执行字节构建过程需要 python 软件包
5 Q; G% f, `8 \执行小入口点脚本需要 bash 软件包
) i( T# K. Y* [Requires 指令指定软件包的运行时依赖项,它只包括 python 软件包。pello 程序需要 python 软件包在运行时执行字节编译的代码。; \* e: z; Q6 e: g
4 p3 p# j1 b+ H$ y7 N" C
%build 部分指定如何构建软件,对应于软件对字节级编译的事实。( k6 T) h0 K' _, W
' k6 K% d& D$ E要安装 pello,您需要创建一个打包程序脚本,因为 shebang 不适用于字节编译语言。可以通过多种方式完成此操作,例如: B1 V: ?' V0 M" t8 n
% A+ i1 Z i2 y* i+ M4 }
制作单独的脚本,并将该脚本用作单独的 SourceX 指令。* y. N3 j) S3 R) o
在 SPEC 文件中创建文件.. ?( y) o( w* T
此示例显示在 SPEC 文件中使用命令行创建打包程序脚本,以演示 SPEC 文件本身可以脚本化。此打包程序脚本将通过此文档来执行 Python 字节编译代码。2 e- V1 J- X2 q" X% {. b3 d0 Z) K+ _
% v( O2 u: y# l- R本例中的 %install 部分也对应一个事实:您需要将字节文件安装到系统的库目录中,以便访问它。 D: k- z: U2 [/ o
* f! `7 R! [) _& t9 s
3.2.6. 使用 C 语言编写的程序的 SPEC 文件示例 : E# D% H/ o$ ]8 K3 ]: [
复制链接
# G3 \2 g3 u, b% H* @2 C本节介绍使用 C 编程语言编写的 cello 程序的示例 SPEC 文件。有关 cello 的详情,请参考 第 2.1.1 节 “源代码示例”。
0 @3 g% O" ?" x6 w+ {& J4 L7 \/ I$ [, }
使用 C 语言编写的 cello 程序的 SPEC 文件示例
- d: R# x0 p9 N8 k. j* D& Z2 H# ~
! m- a. e. k E2 s8 t
Name: cello. V0 W: O4 M; }" X& e
Version: 1.0
0 A4 [* ?3 T i6 k) J# \/ RRelease: 1%{?dist}1 p9 z Z, J, k+ q# |+ M- E. b
Summary: Hello World example implemented in C
3 D; Z* P8 I3 Y
2 D- `/ m) d$ T1 u! q3 Q) e8 ~5 uLicense: GPLv3+
) J4 B, ^0 W1 ~% Q/ k+ e# Z" mURL: https://www.example.com/%{name}, y: @& n( I/ i; v" W9 `
Source0: https://www.example.com/%{name}/releases/%{name}-%{version}.tar.gz& r" H( w# O3 Q, p" z5 z
$ [# q% ~6 M. z" v: W s! z: p
Patch0: cello-output-first-patch.patch
7 K! u. D# a, L& W% `, s6 I" C! o5 b! j
BuildRequires: gcc
0 @. S! ?* G! \8 h$ KBuildRequires: make
/ W8 @9 y) D1 f) X- I. r' } Z7 D
4 E. B; V6 {' ?7 c M! |+ L%description
9 T& Q1 o( b$ ^! G9 \The long-tail description for our Hello World Example implemented in( D/ f+ V' X5 P6 _9 X; H
C.
, A3 J1 ]8 a4 E9 G
& R4 v6 o6 g/ W+ i" @%prep2 I8 E9 z: R% _
%setup -q
1 M. I& [: i. V, O) F0 o* v( z% `4 e; `5 R$ ~0 ^- _7 L2 W- |% F& @
%patch0
8 F3 y4 a# ~ N6 m+ \
( K! i' \- V. r%build5 d q+ Z6 V# x+ L0 h, M
make %{?_smp_mflags}
' @$ r% t6 y- _! n+ {& o0 r6 q8 H- S
%install- R# r5 P/ y& p" W$ x5 o
%make_install
8 Z8 u" l3 N) y6 b) d' @& k& P& R% ~+ B4 r
%files4 v) O6 J: @: a; S) O' t4 ^
%license LICENSE
* J( N( K7 F7 N+ l g; h% I4 K%{_bindir}/%{name}
* e5 _0 G9 Y u! O$ |6 H) U, ?& K0 m v H0 f, K% z4 P
%changelog+ g& W- K; `$ Y6 S: q
* Tue May 31 2016 Adam Miller <maxamillion@fedoraproject.org> - 1.0-1
. Q' \5 o T1 T4 s/ `4 S" q9 Z4 H- First cello package) J& _% u. m0 ?" }" w9 L
Expand6 o7 J# Q- i! z! v* [
BuildRequires 指令指定软件包的 build-time 依赖项,其中包含执行编译构建过程需要的两个软件包:2 p' x6 P# i7 N$ l3 k1 r7 z
7 M' p- U/ s( [; ]2 qgcc 软件包
, r" c0 v' h. L* s9 m0 kmake 软件包
9 W' A$ A8 }& M, s% |# O本例中省略了该软件包的运行时依赖项 Requires 指令。所有运行时要求都由 rpmbuild 进行处理,而 cello 程序不需要核心 C 标准库之外的任何内容。
% f A, S" c+ k/ v3 x3 U4 [; v: e- U' n% W3 F2 `, Z$ E$ f/ g
%build 部分反映了编写了 cello 程序的 Makefile 的事实,因此可以使用 rpmdev-newspec 程序提供的 GNU make 命令。但是,您需要删除对 %configure 的调用,因为您没有提供配置脚本。
. ?5 G( m4 C" L' V& r* Q, D8 E! c! ]6 i P! m
可使用 rpmdev-newspec 命令提供的 %make_install 宏来完成 cello 程序安装。这是因为 cello 程序的 Makefile 可用。
, y% p6 ~; L5 p! ]! ] y2 s, |. k3 h- a4 V" V
3.3. 构建 RPM % ]6 \2 Q, X4 W$ o) @
复制链接
/ G/ W" O/ g `' I& l这部分论述了如何在为程序创建 SPEC 文件后构建 RPM。* w- m4 Y' R$ `1 ^$ K. w* Y
9 g$ D# R6 D* Y' A# F: i: JRPM 使用 rpmbuild 命令构建。此命令需要特定的目录和文件结构,这与 rpmdev-setuptree 程序设置的结构相同。
v1 {; q, k) w
: c9 ]4 ]& ?" Y# Y1 e不同的用例和所需结果需要不同的参数组合到 rpmbuild 命令。本节描述了两个主要用例:
" ] _- ]6 Q% X7 u* a! S2 y* r
1 K2 Z% L6 z% V7 I4 |) ^. l构建源 RPM6 _' l5 I% y9 z* a1 i0 P( W; w
构建二进制 RPM* }% F2 I+ m5 N) L# n
3.3.1. 构建源 RPM 9 v- _ e0 o4 X& z. r
复制链接
4 S4 i; V4 D8 Z; d# ?' l. X这一段是过程模块简介:对流程的简短描述。1 _5 R x4 x: I& s
5 x* Z$ ?5 w1 f. w! \* L5 A. p
先决条件
8 ^1 C! z: o1 T+ I% f* j- F6 ^6 s" D9 c/ ~3 A
我们要打包的程序的 SPEC 文件必须已经存在。有关创建 SPEC 文件的更多信息,请参阅使用 SPEC 文件。 { I4 Q2 ]% K7 }! D
$ T( ^( K2 X/ \2 O
流程
. A; n, H( T& u6 x5 ?3 t
( Z& Q+ j. T8 u( _3 y0 [$ \以下流程描述了如何构建源 RPM。/ O5 n+ E3 }5 y0 c
/ f# q# d1 q( L, d! U2 w
使用指定的 SPEC 文件运行 rpmbuild 命令:
' W* @& d ^! t- r/ D/ U* t' g6 q0 S
$ rpmbuild -bs SPECFILE
M* {; x! A) p: s: n7 j" _使用 SPECfile 替换 SPECFILE。-bs 选项代表构建源。; H: P2 F* G( v" @5 j
( { M4 J* e$ Y$ q/ Z0 @以下示例显示了为 bello、pello 和 cello 项目构建源 RPM。' W. l' T% y. e* V5 ~
: m# i1 G/ Y5 K3 t& h3 J* O
为 bello、pello 和 cello 构建源 RPM.
7 {# l! q( f3 R% I' r% \- Y" @
1 N' x$ Q. ]7 L+ w. c: x& f3 a' Q( C4 D1 w5 L5 J- h
$ cd ~/rpmbuild/SPECS/
8 x6 l* ^; I3 n
: ^' A8 P$ D# w. ]7 b; N0 `( G8$ rpmbuild -bs bello.spec, t% s u. @6 G2 Z' E1 N# u
Wrote: /home/<username>/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm
8 x8 U/ y) S5 j7 ~6 `# F) h: S% L- ~) T6 A
$ rpmbuild -bs pello.spec
) A# r* E: Q# l- [( J, ^Wrote: /home/<username>/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm, V8 K8 u% @: y r- u2 y, r
# s0 z3 ^$ A8 g+ ]3 y; ^
$ rpmbuild -bs cello.spec
! G9 d' Z! S% R, b4 d d8 CWrote: /home/<username>/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm8 z9 ^4 F1 G0 M( @9 t9 i) Y
验证步骤
3 ~7 P B& i! m2 O4 s
( k2 w+ E. @; P4 g# ]9 A9 R确保 rpmbuild/SRPMS 目录包含生成的源 RPM。该目录是 rpmbuild 所期望的结构的一部分。
l- z; Y4 R4 Q9 T" h$ w3 c; r! }3.3.2. 构建二进制 RPM
q$ z$ o: i2 x* _复制链接
; C; c" E" S4 ~以下方法可用于构建二进制 RPM:7 r# T0 k+ f- j9 V. X
. U7 [+ k% ]1 U9 |从源 RPM 重建二进制 RPM
0 e0 s" {, U# p2 C0 c+ t3 R$ R4 f) H; I从 SPEC 文件构建二进制 RPM
+ l3 S! T5 j2 z. X, V3 T$ P8 `# T从源 RPM 构建二进制 RPM
9 w9 i7 l4 L* P+ V' n0 e9 t) F3.3.2.1. 从源 RPM 重建二进制 RPM , Y6 C; Y/ z! z- s, N/ O- W
复制链接
* Y$ `8 V9 a* m以下流程演示了如何从源 RPM(SRPM)重建二进制 RPM。+ P& S8 w/ L; b8 B) D5 a( A, N
9 @; V/ w& y) V0 g$ \4 g3 F- ^
步骤
. B( Q3 h K. }( x# d; o+ R4 _
. ]: V" a0 Y: [/ `- n要从 SRPMs 中重建 bello、pello 和 cello,请运行:; j7 V! F% x8 z/ a
' f; u3 i. L9 j. E' g
$ rpmbuild --rebuild ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm
& {! r: I4 ]9 a* Y" x[output truncated]
) v' x) N! R3 f9 ~; `7 O% q# b/ r( |8 U9 W! f2 q! d" [; O
$ rpmbuild --rebuild ~/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm
0 A6 b" v4 S/ W* X" e. K+ @[output truncated]
" V0 [% i* T# C* I) y. V- v# e" g9 v2 F7 ~: S% G
$ rpmbuild --rebuild ~/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm8 Q) D9 t3 B- e4 A' C. \; \
[output truncated]6 s. n1 r/ E- f+ z0 Q( t0 J
注意5 ?1 s; s: g" _4 [
调用 rpmbuild --rebuild 涉及:+ o3 k8 S; ?4 k5 c
& ?1 h8 C3 l. b1 Z$ Q% a
在 ~/rpmbuild/ 目录中安装 SRPM - SPEC 文件和源代码 -。
0 K. C' k+ z, U+ D使用安装的内容进行构建.
3 G. Y& R! @" j删除 SPEC 文件和源代码。
5 ]6 [& e" g; r) S) @$ o( R要在构建后保留 SPEC 文件和源代码,您可以:* c9 f; S) P: z% U$ L9 _! l0 H
6 ~+ \7 m6 X9 L0 u1 w构建时,使用带有 --recompile 选项而非 --rebuild 选项的 rpmbuild 命令。
1 A1 a$ w% }7 H/ d使用以下命令安装 SRPMs:
$ _# c! U O* X4 I, G& n6 w e8 s8 ?" u* _$ t/ z( ~
$ rpm -Uvh ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm) w. Y; C; `# ^8 G5 x% F
Updating / installing…
+ Q$ }0 C* w: [) \' N4 a 1:bello-0.1-1.el8 [100%]
+ \! E) j+ z$ H: m' n) [: z3 Q% ]3 ?0 U- |
2 B" ]0 w* w( f. Z2 J; n5 B$ rpm -Uvh ~/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm! b6 o& L7 a0 t/ I
Updating / installing…9 G1 c7 q1 A5 p. { x
…1:pello-0.1.2-1.el8 [100%]- G: | \, E4 L3 z9 W. b4 q/ P
5 a) F5 `7 s/ X% D. D$ n- s. z
$ rpm -Uvh ~/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm) B- h) I& w, D: e
Updating / installing…; q% {/ \- D7 u v7 c7 j2 X1 O
…1:cello-1.0-1.el8 [100%]! j3 |$ o6 }& M7 @9 S5 s) J& E
创建二进制 RPM 时生成的输出是详细的,这对调试非常有用。输出因不同示例而异,并对应于其 SPEC 文件。
2 p" Q7 l: a0 O1 Y* w. W7 H4 B5 n. V! M9 O
如果软件包没有特定架构,生成的二进制 RPM 位于 ~/rpmbuild/RPMS/YOURARCH 目录中(其中 YOURARCH 是您的架构),或位于 ~/rpmbuild/RPMS/noarch/ 目录中。9 m' |+ Q2 D4 i* J t
! r6 C0 d6 l8 d9 g3.3.2.2. 从 SPEC 文件构建二进制 RPM
) L: y! _1 _, S) s) d复制链接
4 d T* H. ]; B% i D以下步骤演示了如何从 SPEC 文件构建 bello、pello 和 cello 二进制 RPM。
* Z* m' x$ K7 e
9 i) d- [8 M' ~ F: K步骤
) A7 A) z" Y$ w" f/ Z& C( ^
% n; |& y2 p$ {* B使用 bb 选项运行 rpmbuild 命令:( I$ x5 p. P3 W# \# {/ Z
M" k) \' G |! _% Z
$ rpmbuild -bb ~/rpmbuild/SPECS/bello.spec3 y/ ^- @0 g; p6 b; z# u
u, W& A' G( L0 w$ rpmbuild -bb ~/rpmbuild/SPECS/pello.spec
, L/ m: O& P7 O9 V
& W2 l$ N9 l8 j* D H. ^& N$ rpmbuild -bb ~/rpmbuild/SPECS/cello.spec) C4 S& N0 R0 j0 O
3.3.2.3. 从源 RPM 构建 RPM
1 b$ U' U% [ }7 l1 D复制链接
. k; T( B. _! E( B也可以从源 RPM 构建任何类型的 RPM。要做到这一点,请使用以下步骤。
, V) H0 k) m, k9 G: G3 s' [3 z, ~7 `) J3 k
步骤* x& n0 A9 U9 k5 o4 a$ Q; y
5 _3 S E K; h+ {: C ^, [
使用以下选项之一运行 rpmbuild 命令,并使用指定的源软件包:" s, q9 R$ |& l
! s/ ?) f, x5 f+ i! v5 A/ T
# rpmbuild {-ra|-rb|-rp|-rc|-ri|-rl|-rs} [rpmbuild-options] SOURCEPACKAGE' a3 W/ N1 ?, e c, e1 ] A+ m; |
其他资源7 Z2 x1 n7 l, W; j/ b
+ K+ S; e, S( L2 x8 k, e9 K: E/ Z有关从源 RPM 构建 RPM 的详情,请查看 rpmbuild (8) 手册页中的 BUILDING PACKAGES 部分。
' i R( ?, \, c- Z: |" q7 `# S6 B
q1 {' e" `* j- i7 r; v3.4. 检查 RPM 健全性 ) E9 @. t* P+ T
复制链接
3 f5 q& _- O7 n1 a% x2 \创建软件包后,检查软件包的质量。6 V4 |# g6 b6 d% |* n
5 w. @6 N. X' I+ t) @/ B6 }8 K
检查软件包质量的主要工具是 rpmlint。' W/ T1 h& D' A) B) _
0 c) [9 Z' y8 h ]' orpmlint 工具执行以下操作:
% K; R* }+ `; H: v, q0 s$ s, |5 k9 h9 H4 z2 G. v4 J
提高 RPM 可维护性. J9 i/ _! a3 c1 B# S3 Y
通过对 RPM 进行静态分析来启用完整性检查。
4 Q% ^% t+ Y% H' B- p通过对 RPM 进行静态分析来启用错误检查。
, v' b- x2 q. [9 A- I3 Lrpmlint 工具可以检查二进制 RPM、源 RPM (SRPMs)和 SPEC 文件,因此它对打包的所有阶段都很有用,如下例所示。+ z* _2 X) k" V1 I* z& T
7 s7 r, T9 ?6 j
请注意,rpmlint 有非常严格的准则,因此有时可以接受跳过其中的一些错误和警告,如下例所示。
5 T! I9 l( Y- s* O
! D/ M" h! @3 l% O. W/ r$ B注意
1 N+ q7 N; B6 y- f0 |, B; L) S4 Y! U在以下示例中,rpmlint 在没有任何选项的情况下运行,这会产生一个非详细的输出。如需了解每个错误或警告的详细说明,您可以运行 rpmlint -i。
$ x, }- G' f* v7 p6 l$ H" i. E' |1 Z( r3 z# c9 p8 M
3.4.1. 检查 bello for sanity 2 s& Z3 q* z" B
复制链接5 x+ K! H# N, ]+ ]) p4 h% }9 c
本节介绍在检查 bello SPEC 文件示例和 bello 二进制 RPM 时可能发生的警告和错误。0 E: x1 }4 D2 D. f, J9 U
2 ~* @# y$ S ~% a' K. U
3.4.1.1. 检查 bello SPEC 文件
" W# b; Y: k; t$ b$ j( Z9 m* e1 }复制链接
+ z6 R+ ~. T3 n例 3.2. 在适用于 bello 的 SPEC 文件中运行 rpmlint 命令的输出
% F- A0 ~+ p: {8 h- c# {* @2 n# S; O
$ rpmlint bello.spec4 }% ~) R- L6 Q" k- x
bello.spec: W: invalid-url Source0: https://www.example.com/bello/releases/bello-0.1.tar.gz HTTP Error 404: Not Found2 B/ C/ A4 m+ O2 h( c9 d* n' `
0 packages and 1 specfiles checked; 0 errors, 1 warnings.* o8 y/ z( |/ u) H7 B2 F! e: C
对于 bello.spec,只有一个警告,表示 Source0 指令中列出的 URL 不可访问。这是正常的,因为指定的 example.com URL 不存在。假设我们预期此 URL 在未来工作,我们可以忽略这个警告。 V$ c- o- ^& }
1 X2 k, W2 {4 x* |+ ~0 `
例 3.3. 在 SRPM forllo 上运行 rpmlint 命令的输出$ p6 N! T+ {+ X2 @1 O0 s. ?5 Z: |1 n
5 d8 s1 |/ a2 K C& ^$ rpmlint ~/rpmbuild/SRPMS/bello-0.1-1.el8.src.rpm
5 }, u, j& Q& H; m3 Mbello.src: W: invalid-url URL: https://www.example.com/bello HTTP Error 404: Not Found
2 w. o" P2 [- z E }* nbello.src: W: invalid-url Source0: https://www.example.com/bello/releases/bello-0.1.tar.gz HTTP Error 404: Not Found
( W4 j- N; T( R" b6 C: L t1 packages and 0 specfiles checked; 0 errors, 2 warnings.
A5 K- O9 ^) H, o& `- o对于 bello SRPM,有一个新的警告,表示 URL 指令中指定的 URL 不可访问。假设链接将在以后工作,我们可以忽略此警告。
8 v5 Z! M- w7 G# q l s! T6 J& {
' U. I% R% ^( N3.4.1.2. 检查 bello 二进制 RPM
6 o7 S/ @9 s* e# ?) z复制链接
3 K' ]: _" X' U" T在检查二进制 RPM 时,rpmlint 会检查以下项目:
8 n6 a/ `' M4 p9 B4 H$ R" j! T4 m8 ]
Documentation- g1 q( }4 _5 T2 w/ P
man page9 Q( A7 Z. q, w* @8 c# x
致地使用文件系统层次结构标准" d+ d9 L! P. l( B+ ^+ V
例 3.4. 在 bello 的二进制 RPM 上运行 rpmlint 命令的输出
p" ^2 z0 z/ I( x+ W' ~) H3 b# C/ J$ S' m
$ rpmlint ~/rpmbuild/RPMS/noarch/bello-0.1-1.el8.noarch.rpm$ |" F1 T' J& k, m9 i# ^
bello.noarch: W: invalid-url URL: https://www.example.com/bello HTTP Error 404: Not Found9 T& y8 _1 i/ @( O. [5 Q' ~# x
bello.noarch: W: no-documentation/ l7 c7 u0 f7 s3 P% B+ a1 Y
bello.noarch: W: no-manual-page-for-binary bello
7 r5 m9 m, A. p! Z1 packages and 0 specfiles checked; 0 errors, 3 warnings.3 I) K. g% N) C9 \( P' ^
no-documentation 和 no-manual-page-for-binary 警告表示 RPM 没有文档或手册页,因为我们没有提供任何文档或手册页。除以上警告外,RPM 会传递 rpmlint 检查。
1 R" T8 F6 a, t7 t; h1 S
& j% Z. l0 R: F" w3.4.2. 检查 pello for sanity
: o; F! i* l$ }4 E/ D复制链接' [5 F( j' ?. n: U. J7 Q7 B/ _: q
本节显示在 pello SPEC 文件和 pello 二进制 RPM 示例中检查 RPM 健全时可能出现的警告和错误。
7 v0 J1 F: c! x' K( t* {8 `1 V+ Q, u0 `/ T! t
3.4.2.1. 检查 pello SPEC 文件 z( Y6 f% }6 X; I" K
复制链接
! L: R% @3 q: ~) g例 3.5. 在 pello 的 SPEC 文件中运行 rpmlint 命令的输出& `: V7 ~4 a' z v9 i: r
* x% R3 N1 v4 c; k$ d* h
$ rpmlint pello.spec7 @* u# D, ]9 S
pello.spec:30: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name}- m7 c, f+ c& H
pello.spec:34: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.pyc! C' u& t* N/ t- A
pello.spec:39: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name}/9 j }% G$ }2 L K2 ~" b' m" I! l
pello.spec:43: E: hardcoded-library-path in /usr/lib/%{name}/6 }! m0 J& C" U/ s' f$ e
pello.spec:45: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.py*8 x- B/ y1 b# Z
pello.spec: W: invalid-url Source0: https://www.example.com/pello/releases/pello-0.1.2.tar.gz HTTP Error 404: Not Found
- A3 ]7 z3 \. s" u9 P0 T) a% N0 packages and 1 specfiles checked; 5 errors, 1 warnings.+ \/ D7 G7 _3 X& R
invalid-url Source0 警告表示 Source0 指令中列出的 URL 不可访问。这是正常的,因为指定的 example.com URL 不存在。假设此 URL 将在以后正常工作,您可以忽略这个警告。
/ j+ ^- F# f6 J# W1 g' c3 m* l% [" R3 v2 A6 B/ n0 l
hardcoded-library-path 错误建议,使用 %{_libdir} 宏而不是使用硬编码的库路径。在本例中,可以安全地忽略这些错误。但是,对于将它们进行生产而言,请确保仔细检查所有错误。
/ I- X2 Y' |: u; C$ c+ L, q L& |
! l4 ]$ ~5 S+ |8 @# y9 U4 j7 d, e例 3.6. 在 SRPM for pello 上运行 rpmlint 命令的输出
1 y2 [3 t& B' z* t2 K6 U/ F
1 O) e( L9 L m* J g, ^& R3 z$ rpmlint ~/rpmbuild/SRPMS/pello-0.1.2-1.el8.src.rpm
! M @7 g2 p& o# b- Tpello.src: W: invalid-url URL: https://www.example.com/pello HTTP Error 404: Not Found
/ \4 N' Q s/ ^5 \( mpello.src:30: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name}" f" N0 K( d* r' X8 Y% R
pello.src:34: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.pyc# |0 p2 r0 F( n, X
pello.src:39: E: hardcoded-library-path in %{buildroot}/usr/lib/%{name}/
, U4 a* C+ w3 f# v, Y& M# ]# epello.src:43: E: hardcoded-library-path in /usr/lib/%{name}/
# t6 A8 ~* F5 f+ `, gpello.src:45: E: hardcoded-library-path in /usr/lib/%{name}/%{name}.py*3 M% G* h! @4 P* f) V8 p0 j
pello.src: W: invalid-url Source0: https://www.example.com/pello/releases/pello-0.1.2.tar.gz HTTP Error 404: Not Found
- _' [/ X% D8 `9 ^1 packages and 0 specfiles checked; 5 errors, 2 warnings.
6 }" R% E3 w4 |6 X5 \9 y7 j此处新的 invalid-url URL 错误是关于 URL 指令的,它无法被访问。假设该 URL 将在以后有效,您可以安全地忽略此错误。
0 R1 ^+ l/ i! w$ s
2 {$ y+ U! A4 x3 }! u! e% L3.4.2.2. 检查 pello 二进制 RPM $ ~4 M6 D: y% ^. }! x2 U
复制链接
. H7 u8 s' T" S, i$ u# _! k在检查二进制 RPM 时,rpmlint 会检查以下项目:
: u% k! I9 H8 |3 S
0 N& P4 Q+ y# ]! |: [ bDocumentation$ a1 J; i) A: t
man page
# T( `% s6 ^3 e" ] D. k7 g6 g致地使用文件系统层次结构标准5 Z5 T- B' O- h3 A( o
例 3.7. 在 pello 二进制 RPM 上运行 rpmlint 命令的输出
# w' `5 ~1 }$ g# b: t: w
/ ^; N: R1 j9 q' k2 r$ rpmlint ~/rpmbuild/RPMS/noarch/pello-0.1.2-1.el8.noarch.rpm: Z0 u+ n# o# `* @9 J( u
pello.noarch: W: invalid-url URL: https://www.example.com/pello HTTP Error 404: Not Found0 |# }: b+ R/ ]9 L! H+ z
pello.noarch: W: only-non-binary-in-usr-lib' n0 |+ l) v+ U/ Q( a" y+ t# A
pello.noarch: W: no-documentation
! s) `/ e! b8 r8 Q6 u" ^- ~pello.noarch: E: non-executable-script /usr/lib/pello/pello.py 0644L /usr/bin/env, v1 \' m& @+ j! w* W3 v8 h( m
pello.noarch: W: no-manual-page-for-binary pello& `. u7 R' L4 ^: J
1 packages and 0 specfiles checked; 1 errors, 4 warnings.7 X6 H3 r, ]) P
no-documentation 和 no-manual-page-for-binary 警告表示他 RPM 没有文档或 man page,因为没有提供任何文档。; X: u% W [ e% P1 _
1 C$ a9 t$ t t$ \only-non-binary-in-usr-lib 警告表示您在 /usr/lib/ 中只提供了非二进制工件。该目录通常为共享对象文件保留,它们是二进制文件。因此,rpmlint 预期 /usr/lib/ 目录中的至少一个或者多个文件是二进制的。
% R- I1 J) [/ N2 O: d$ T, Q$ J& p0 b
3 p. ] C- @4 C这是 rpmlint 检查的一个示例,它是否符合文件系统层次结构标准。通常,使用 RPM 宏来确保文件正确放置。在本例中,可以安全地忽略这个警告。
2 m: l. S j8 x0 [, X a2 O& c- [6 C. m% M& r; y0 h: u
non-executable-script 错误警告 /usr/lib/pello/pello.py 文件没有执行权限。rpmlint 工具预期文件可以执行,因为文件包含 shebang。在本例中,您可以保留此文件而不具有执行权限,并忽略此错误。
2 |" x! k) n! u5 p" J! a' P, D9 _ e K* D9 u9 G# e! h- N
除以上警告和错误外,RPM 传递 rpmlint 检查。) l: Q, b. m' U+ ]
+ z( l, q# a8 I6 n& F) R6 W3.4.3. 检查完整性的单元格
- x$ p; v3 I0 k/ x复制链接: L' I; x& a; f& ^5 W) b
本节显示在 pello SPEC 文件和 cello 二进制 RPM 示例中检查 RPM 健全时可能出现的警告和错误。: w1 G' q/ z* q) ~4 W" [. s. Y
9 E- C+ N$ G" q2 y4 `& [7 l. q
3.4.3.1. 检查 cello SPEC 文件 * D+ u+ U' q* |8 P; L
复制链接
1 q( |: D. h* }例 3.8. 在 SPEC 文件中为 cello 运行 rpmlint 命令的输出
. r8 Y, [- |0 [3 T1 z. v, F) A9 `* {
. ?2 N2 T' _1 N$ g$ rpmlint ~/rpmbuild/SPECS/cello.spec
7 G' u' Q( V% h, _3 m/home/<username>/rpmbuild/SPECS/cello.spec: W: invalid-url Source0: https://www.example.com/cello/releases/cello-1.0.tar.gz HTTP Error 404: Not Found
4 D9 D0 h# \0 M! t$ b' Y; C" M0 packages and 1 specfiles checked; 0 errors, 1 warnings.. @" @! L n/ }* ?0 I6 {
对于 cello.spec,只有一个警告,表示 Source0 指令中列出的 URL 不可访问。这是正常的,因为指定的 example.com URL 不存在。假设此 URL 将在以后正常工作,您可以忽略这个警告。" ?# z: z& q, a. w% A
' Q }+ |4 D* G6 K0 D) V- A5 e; n
例 3.9. 在 SRPM for cello 上运行 rpmlint 命令的输出
2 ^/ `' `% t7 Q6 a. S' d! w9 u7 n4 k5 B' q! v
$ rpmlint ~/rpmbuild/SRPMS/cello-1.0-1.el8.src.rpm
3 C5 h6 N( L" ^. L% {cello.src: W: invalid-url URL: https://www.example.com/cello HTTP Error 404: Not Found$ N, j- F' m, l4 z, g+ k
cello.src: W: invalid-url Source0: https://www.example.com/cello/releases/cello-1.0.tar.gz HTTP Error 404: Not Found! G0 F4 v/ A' I/ L1 F
1 packages and 0 specfiles checked; 0 errors, 2 warnings.
7 G3 v7 F' E- D8 v. S( ^* A8 P对于 cello SRPM,有一个新的警告,表示 URL 指令中指定的 URL 不可访问。假设链接将在以后工作,您可以忽略此警告。
. O9 G0 f* j7 g: ~+ @) V8 A0 `# C, k: W0 P
3.4.3.2. 检查 cello 二进制 RPM ( u* J0 k" u8 ]1 b R
复制链接6 o1 s' @# C; Y
在检查二进制 RPM 时,rpmlint 会检查以下项目:
$ u, |; |5 R F1 V6 I8 y* \7 S \5 l" o; ?8 [5 J7 z
Documentation
/ g0 u* A& z6 L" ^1 o7 Q; d& }man page) k6 Y( E5 _ z" C. D
致地使用文件系统层次结构标准8 c9 \3 y9 _$ r. x: s" }
例 3.10. 在用于 cello 的二进制 RPM 上运行 rpmlint 命令的输出
: [+ w' \8 C f; a* F' F5 J2 f( b5 X( d) Y( J
$ rpmlint ~/rpmbuild/RPMS/x86_64/cello-1.0-1.el8.x86_64.rpm
w- u9 J% i! F6 p; fcello.x86_64: W: invalid-url URL: https://www.example.com/cello HTTP Error 404: Not Found5 E5 j' S: E# q+ T+ s
cello.x86_64: W: no-documentation0 `2 {: l+ \5 s2 ?4 K, {
cello.x86_64: W: no-manual-page-for-binary cello
@; O w* s4 d8 ~3 a' y1 packages and 0 specfiles checked; 0 errors, 3 warnings.# L5 }4 Y( L5 F' V( E
no-documentation 和 no-manual-page-for-binary 警告表示他 RPM 没有文档或 man page,因为您没有提供任何信息。除以上警告外,RPM 会传递 rpmlint 检查。
" |; Y$ d; ^% J0 K+ {
% P3 v) i; \$ ~- ^5 c5 Z* h" p第 4 章 高级主题
( I0 a; p4 w, N- ]0 P复制链接$ k' ~' {/ Z$ y7 P
本节涵盖超出入门教程范围但对真实 RPM 打包很有用的主题。9 v% g1 {" w, p* u, h
: l1 i4 ?" G6 [( Q. e4.1. 签名软件包 - J3 ~0 I0 Z" U+ S4 w
复制链接( t8 a/ k0 t* J& w8 w
软件包经过签名,以确保没有第三方可以更改其内容。在下载软件包时,用户可以使用 HTTPS 协议添加额外的安全层。& z& e' y5 p: H9 _5 L9 d8 S# {
# p- a. g8 q2 Y, s2 e
为软件包签名有三种方法:
* e- Y" F4 A- u# D
* _' ?& t, A3 J4.1.1. 创建 GPG 密钥
6 ^: Y5 @! @+ [- W复制链接$ m" z: N$ n$ \" A, P% O$ r
流程
: N: m$ m4 W& q$ n% r6 b+ _1 g, _$ F, o% h- L3 y
生成 GNU Privacy Guard(GPG)密钥对:( p5 [7 ?/ n6 N3 s/ H
8 N7 \9 |4 ^# ~
# gpg --gen-key9 W( D5 p4 Q4 i; E$ Y
确认并查看生成的密钥:
" B6 p2 b6 Y( j9 ?0 d
0 U& O+ B8 |. t% c; Y5 o) \# gpg --list-keys! Q2 B9 F% j/ q1 b L# o
导出公钥: T- _$ z/ C9 N. j
; x8 Y6 M+ m" f J1 O3 J# gpg --export -a '<Key_name>' > RPM-GPG-KEY-pmanager
5 j( I& \7 P, V# |5 p, z注意; W# [: y% d- w
包含您为键选择的实际名称,而不是 <Key_name>。6 u. r, D/ c+ _2 ~( U
2 ]8 \9 e6 ` s* t( }$ w
将导出的公钥导入到 RPM 数据库中:. ^4 K& {$ ~: y% L# a
# z) t7 i' F1 K* f
# rpm --import RPM-GPG-KEY-pmanager6 `; q" x" g8 w% M, c& ^
4.1.2. 在已经存在的软件包中添加签名 0 d0 |$ [+ E8 S4 e. Q6 l
复制链接' L0 L- \$ e' H
这部分论述了在没有签名的情况下构建软件包时最常见的情况。签名仅在软件包发布前添加。( S' G; L4 ^- N1 c& K* @) S
& y2 i$ q9 H& H' I0 Q" {
要在软件包中添加签名,请使用 rpm-sign 软件包提供的 --addsign 选项。; L6 w) Z2 H- s) c
7 v$ L' v5 b4 v
通过多个签名,可以将软件包构建器的所有权路径记录到最终用户。
' K3 j3 V/ i' l: P; }) F. O
0 @# a7 t& |; ]步骤
/ q9 U/ B' O8 m0 p4 a
9 J: l3 O Q+ ~+ r9 n8 y在软件包中添加签名:% q% h$ ?1 L" ?) p+ y3 u1 |- l, C ], F
' @$ [( r \; w( i6 i e- z$ rpm --addsign blather-7.9-1.x86_64.rpm8 R7 e' U# Q8 y1 v- O+ L8 W
注意
. P2 ]# m8 F/ w {8 \7 H; {您需要输入密码来解锁签名的机密密钥。7 l; `6 N, D! f3 n9 M4 @
( H& X% A" B. {- e# k% V! `( f* q4 j9 `7 V
4.1.3. 检查带有多个签名的软件包的签名 ! \" o0 i, V. k" g/ Z, o+ u
复制链接' c+ W) O& h5 A9 ` J0 y# q
流程
; I3 m6 \! N; Y0 P* a
7 |: `, F G. s( b# W1 |要检查带有多个签名的软件包的签名,请运行以下命令:/ }6 R0 u! u0 k# o' x/ [
# a% o, J+ B2 f3 T3 q+ U# R7 u$ rpm --checksig blather-7.9-1.x86_64.rpm
& o ^- p# w1 ]& Q6 }blather-7.9-1.x86_64.rpm: size pgp pgp md5 OK5 |; A* ]# w' t7 x1 c3 N
rpm --checksig 命令的输出中的两个 pgp 字符串显示软件包已被签名两次。' q& a0 r4 b3 L! i. ^
- Z9 H2 b. E8 f" j
4.1.4. 在已经存在的软件包中添加签名的实际示例
# g# m6 |9 S3 z7 D5 `7 U; j7 `( d复制链接( S6 W3 P) p: J' |) \
这部分论述了在现有软件包中添加签名可能会很有用的示例。
6 U% \" `. u% z: [' L! k3 n4 V: H Y) A6 B; j* k- N. Y! S
公司的一个部门创建了软件包并使用部门的密钥对其进行签名。然后,公司总部检查软件包的签名,并将企业签名添加到软件包中,说明已签名软件包是验证的。! l# j7 U2 r" p
* q: e( s* ~' v4 t
使用两个签名时,该软件包可让其为零售商采用方法。零售商会检查签名,如果匹配,也会添加其签名。
7 O% Y% o2 b& X! ^3 @
% G+ @2 x$ _9 a' r) o现在,这个软件包已成为希望部署该软件包的公司。检查软件包中的每个签名后,它们知道它是真实的副本。根据部署公司的内部控制,他们可以选择添加自己的签名,以通知其员工收到其公司批准。/ r6 n _7 p% Y1 O$ ]9 L
5 e- l; R: N* g |) k2 e8 ~5 W4 F
4.1.5. 在已经存在的软件包中替换签名
, |! q3 T8 k( L( E- z: U复制链接
8 d9 C, E* T* R' C( a; Q这个步骤描述了如何在不重建每个软件包的情况下更改公钥。
$ {; l# |# J! k- G6 Y& G; v2 S: ~0 ^' F# h
流程
& F( h5 i' x, n H$ s
' R7 `! P/ S" t: l要更改公钥,请运行以下命令:
0 U) P" k [: [! _% S6 K$ Q: I1 J, Y; z/ Y8 C, ~
$ rpm --resign blather-7.9-1.x86_64.rpm* ?, t' R* c3 N3 ~
注意
]5 e% l6 C; N您需要输入密码来解锁签名的机密密钥。
* L7 v* h! h; O* Y: a
4 S# w5 P8 Q1 Q" f* {' ?$ `5 J1 `- C9 n--resign 选项还允许您更改多个软件包的公钥,如以下步骤所示。
( Q4 m \" }* I( ^
/ `7 i! Q' r1 E' v, v- O步骤& k7 y0 {& {2 o0 s3 D
: h. d! i% H) b# w8 @, ?+ [要更改多个软件包的公钥,请执行:! u6 b+ b; j2 S' a, l
4 }4 [; x: }" z' l7 w) `" ] u
$ rpm --resign b*.rpm5 ^4 I. a6 R7 J. S l3 M
注意! u" v" _, b) I6 e; g
您需要输入密码来解锁签名的机密密钥。! \5 ~# d8 c/ V7 d4 d
) O4 P6 @0 S& l W9 z' }4.1.6. 在构建时签名软件包 . i! v b" c ?- n* J
复制链接* }1 U2 |5 U7 N2 T# u
流程
0 u* T+ F$ x5 R1 M2 x7 m; z! W h6 X4 [: p5 F5 v S, z
使用 rpmbuild 命令构建软件包:. u M: x' K0 G5 M: o
% p3 F* Y) J5 f/ p6 V
$ rpmbuild blather-7.9.spec# e! f4 h2 o. [: q7 z ]
使用 --addsign 选项使用 rpmsign 命令签署软件包:7 [+ M* ?8 z. j: t+ E7 u# E
. l) c5 h! E1 X d4 ]- K1 p$ rpmsign --addsign blather-7.9-1.x86_64.rpm% B j4 ?0 w! c% g7 g( r
(可选)验证软件包的签名:
s# F1 O+ j! ?/ ^0 j% D$ d$ rpm --checksig blather-7.9-1.x86_64.rpm4 }1 P0 r' J4 ] C: Q" [" X
blather-7.9-1.x86_64.rpm: size pgp md5 OK
. U# f; l0 _: T: I. B* p( b7 T( V注意 [2 J E! ^# f& ^+ z# r
在构建和签名多个软件包时,请使用以下语法避免多次输入 Pretty Good Privacy (PGP)密码短语。
# J" E) D- ~' @3 x4 F K4 j7 ]0 M7 O8 g
$ rpmbuild -ba --sign b*.spec5 Z* ~1 u3 v' f, D# J& T
请注意,您应该输入密码来解锁签名的 secret 密钥。
( g$ x" |- V2 f' t1 m0 B& @6 H7 k+ \! I8 G( m# b- }- r
4.2. 有关宏的更多内容 & \4 W+ @; D2 M1 C R
复制链接7 Z9 J4 D0 B+ x" M; d2 P2 `
本节介绍所选内置 RPM Macros。有关此类宏的详细列表,请参阅 RPM 文档。
; W% ~# Q! r, T( a* K% j8 R' _( w2 B1 i8 v" n
4.2.1. 定义您自己的宏
# n& \2 ?) c: Z# V; F9 K4 |复制链接
: y% D. P6 u- p5 l/ b下面的部分论述了如何创建自定义宏。+ K, I+ S+ C" r; J$ p
- y% m8 K4 T' d/ v2 e! C步骤
( a$ H+ K' H3 o7 `& w% G0 E( w+ s) ]0 `5 E5 p: O3 F; I
在 RPM SPEC 文件中包括以下行:
# Q) e7 B8 L! e- P. q1 ~' L9 C5 C0 C8 `) ?, W2 @. e, H6 \
%global <name>[(opts)] <body>9 |2 g& K x D" P# t8 h# {
删除 \ 周围的所有空格。名称可以是字母数字字符,字符 _,长度必须至少为 3 个字符。包含 (opts) 字段是可选的:
" f) {2 O5 T2 n* x4 `9 \: Q. T0 X+ ~# r$ F3 _6 ?4 m
Simple 宏不包含 (opts) 字段。在这种情况下,只执行递归宏扩展。
0 n3 o4 M2 u& d: g1 j" XParametrized 宏包含 (opts) 字段。在宏调用开始时传递括号之间的 opts 字符串可得到 argc/argv 处理的 getopt(3)。" L7 a/ J* D6 {' B8 b. ^
注意
" e! {+ h3 c% ^8 o( y0 W旧的 RPM SPEC 文件使用 %define <name> <body> 宏模式。%define 和 %global 宏之间的差异如下:( y- l* {& |/ ^
& A/ c, p! P9 y$ ?1 g( l# w! Q%define 是本地范围的。它适用于 SPEC 文件的特定部分。%define 宏的主体部分在使用时会被扩展。2 X, j# o6 H9 b9 g" M: T
%global 有全局范围。它适用于整个 SPEC 文件。在定义时扩展 %global 宏的正文。$ t* [8 v& j. s/ L% {
重要% \: S! w# t2 \
宏会被评估,即使被注释掉或者宏的名称被指定到 SPEC 文件的 %changelog 部分中。要注释掉宏,请使用 %%。例如 %%global.: e: ]7 Z5 _% d4 w7 o
0 i* L; V9 ^" e其他资源
N1 A4 `2 l3 j4 }3 D+ D0 O3 _% _6 T3 s1 v
有关宏功能的综合信息,请参阅 RPM 文档。
9 \; x2 Q; H. y V3 U
5 h6 H3 Y0 B+ l3 v% @4.2.2. 使用 %setup 宏
* I: x5 E4 I, H9 `5 {, T% o复制链接
$ a" m9 k! A# T" K+ O这部分论述了如何使用 %setup 宏的不同变体构建带有源代码 tarball 的软件包。请注意,宏变体可以合并 rpmbuild 输出说明了 %setup 宏的标准行为。在每个阶段开始时,宏输出 Executing (%…),如下例所示。
/ n( b* e; L$ T' b
/ [% _3 E. o' ~$ N7 Q& m7 n例 4.1. %setup 宏输出示例
( i6 Y4 B q. Y% s4 R) U$ r4 f; ^' B5 \
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.DhddsG
' ` o+ d8 K- r" sshell 输出启用了 set -x。要查看 /var/tmp/rpm-tmp.DhddsG 的内容,请使用 --debug 选项,因为 rpmbuild 在成功构建后删除临时文件。这将显示环境变量的设置,后跟:9 v4 p" r( H( c: O" M5 ?5 q
" u) Z% m. s4 \2 m: \. T0 {% H% e
cd '/builddir/build/BUILD'7 `1 e' S! G s
rm -rf 'cello-1.0'% p' u1 C8 t" x! D1 y6 O3 \6 D
/usr/bin/gzip -dc '/builddir/build/SOURCES/cello-1.0.tar.gz' | /usr/bin/tar -xof -
# B T) [' q" k: M. Z ^! GSTATUS=$?- N2 }% l A5 Q* `$ {; A. T% R
if [ $STATUS -ne 0 ]; then
; p8 |. ^, S7 d1 R+ B! [- L exit $STATUS
w5 p6 w A) yfi) n6 C. I/ o! [: ]3 V7 W4 X
cd 'cello-1.0'
2 h) C/ u6 V; e. r+ }/usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .9 T0 o! y8 w% x! Y' M+ [5 Z& a
%setup 宏:
- l$ S" N: a# i% g2 c, {' j; G$ l1 T9 `' J* }0 g; A
确保我们在正确的目录中工作。- n# y0 F3 h6 s0 ?3 ~9 V$ [) e
删除之前构建的恢复。* Y/ i$ |. T# @/ g
解包源 tarball。! X2 g4 y1 a0 |8 L! T$ F; l
设置一些默认特权。+ X, @% W/ B0 w7 b% `0 _: h
4.2.2.1. 使用 %setup -q 宏
" [/ b! Q$ \. b! F复制链接
1 D; x3 h$ s. N: F* X( \+ s2 d-q 选项限制 %setup 宏的详细程度。仅执行 tar -xof 而不是 tar -xvvof。使用这个选项作为第一个选项。
! P5 L# y5 Z+ b0 h# A: }6 k3 j6 m, s0 E0 @, Q! V- R/ M
4.2.2.2. 使用 %setup -n 宏
" l# Y0 P6 `5 o! z0 X5 E. h$ ?复制链接6 Q7 K, }7 c# \2 p5 z* L
-n 选项指定已展开 tarball 中的目录名称。1 b* @/ ?% g+ r$ o$ P
: D$ ` k! V: M% x x当来自扩展 tarball 的目录与预期内容不同时,会使用这个情况(%{name}-%{version}),这可能会导致 %setup 宏的错误。: c9 T7 W$ H7 s) V- z" s
! i7 c" u2 ], z. u( ?' U- d1 m) |例如,如果软件包名称是 cello,但源代码以 hello-1.0.tgz 中存档,且包含 hello/ 目录,则 SPEC 文件内容需要如下:
& }/ _8 ?' j7 P: W) `( D; q9 R& `* |$ \' ?7 C2 s9 B0 M
Name: cello
0 Z( y% m1 ~- u( N( rSource0: https://example.com/%{name}/release/hello-%{version}.tar.gz
& B5 T. l8 J6 @* E! ]0 w…
' m9 R2 ]. ?$ g8 B% I9 r%prep
, F) w$ f, ?: a/ H a. ^! U4 I%setup -n hello3 M$ l" v" W b
4.2.2.3. 使用 %setup -c 宏
* X9 n& y' K7 X4 w复制链接+ o) J+ U5 @! I- o
如果源代码 tarball 不包含任何子目录,并在解压缩后的文件会填充当前目录,则使用 -c 选项。& ]* o( |; V- C i+ X
0 ?( Q7 \3 S9 R
然后,-c 选项会在归档扩展中创建目录和步骤,如下所示: v* Y8 I8 m; O9 X( ~. Y! ?: \
( c: S3 h" S. ?* {6 `+ _/usr/bin/mkdir -p cello-1.0
) j+ e+ F) e1 r% hcd 'cello-1.0'
) i# l- ?9 t( E, p) F) }( C归档扩展后不会更改该目录。1 Y9 ~( s2 ]( Q/ ^4 i$ G1 m
; ]$ G% S* l* e7 m d% F# | u. k
4.2.2.4. 使用 %setup -D 和 %setup -T 宏
K8 D S+ G4 R! z- S* b2 j3 E! c复制链接
: c( \! x$ Z2 d- e: Q-D 选项会禁用删除源代码目录,在使用 %setup 宏时特别有用。使用 -D 选项时,不会使用以下行:1 s8 \/ h0 ]" Z8 @& p5 v
* X4 C1 b+ y1 m+ nrm -rf 'cello-1.0'4 |7 ^. W" t F4 b) }4 j" v$ ~
-T 选项通过从脚本中删除以下行来禁用源代码 tarball 的扩展:
0 C/ C# U& V8 d; q0 _* l
8 y5 a; t- j# R+ D8 w; l3 a/usr/bin/gzip -dc '/builddir/build/SOURCES/cello-1.0.tar.gz' | /usr/bin/tar -xvvof -
K" N7 |2 N) x- K& X4.2.2.5. 使用 %setup -a 和 %setup -b 宏
& f2 i2 J' g- g复制链接) A/ k6 w8 X. P& C2 H- k1 d
-a 和 -b 选项可以扩展特定的源:9 Z# E2 d& }& l3 t" J- p
# e0 R1 V. L W) g, r-b 选项代表之前(before),在进入工作目录前扩展特定源。-a 选项代表 之后,在 输入后会扩展这些源。它们的参数是 SPEC 文件中的源号。
" |! ?0 l7 }3 h4 B* Z M- m8 i
/ e" T' H/ p+ G/ C! ]# c在以下示例中,cello-1.0.tar.gz 存档包含一个空 examples 目录。示例以单独的 example.tar.gz tarball 中提供,它们被扩展到同一名称的目录中。在这种情况下,如果在输入工作目录后扩展 Source1,请使用 -a 1。5 m5 E$ i9 s% L) X8 a! j
+ T0 ?+ |5 @" S% x. |) F( \" n6 q" HSource0: https://example.com/%{name}/release/%{name}-%{version}.tar.gz
$ x! H! b/ z2 jSource1: examples.tar.gz
0 M+ R8 N1 s1 k, K0 U4 a# b…
. J4 O0 a2 l' u& R# G; g( F%prep$ A6 T/ O5 j& X, L5 q
%setup -a 1
' W" B# i" ^1 c* ~" m% ]1 T1 f, B在以下示例中,在单独的 cello-1.0-examples.tar.gz tarball 中提供了示例,它扩展至 cello-1.0/examples。在这种情况下,使用 -b 1,在进入工作目录前扩展 Source1 :( g' p" T- G4 O7 Q+ U" a
8 v0 u5 o2 `: O! t: v% y
Source0: https://example.com/%{name}/release/%{name}-%{version}.tar.gz# k* j6 h h( ~) F1 i
Source1: %{name}-%{version}-examples.tar.gz; M) h5 Z; U% p
…# P* ^8 ]9 c4 f$ k3 w
%prep
5 \6 V1 x: p8 K* y, M%setup -b 1& T5 j4 a# b/ [% `5 H" ?
4.2.3. %files 部分中的常见 RPM 宏
6 z3 i! D6 E1 V' u7 `) w9 V( v: `复制链接
! v4 b. v0 I" o这部分列出了 SPEC 文件的 %files 部分中所需的高级 RPM Macros。
+ F% @; n- p5 M! ~' w4 y2 w0 O1 Z0 v# T! B2 z% s' D
表 4.1. %files 部分中的高级 RPM Macros6 \" w+ p2 @: y# ^7 }( o2 X
Macro 定义
: i7 \8 a$ P3 W9 S%license
0 M3 B$ v8 u9 S9 K+ M) ?2 s8 p
v$ x# g9 @' n( r. b宏识别列为 LICENSE 文件的文件,该文件将被 RPM 安装和标记(例如)。示例: %license LICENSE$ R/ w( @" o! `' J4 N8 J! }+ m+ }
2 G- N& w: q- m+ \6 ^%doc* I* c# G r0 d6 L) P0 N' ]
) ^: Q ]& x+ g* x1 q宏识别列出为文档的文件,还将安装并标记 RPM。宏用于有关打包软件的文档,以及用于代码示例和各种附带项的文档。在包括事件代码示例时,应谨慎地从文件中删除可执行模式。示例: %doc README
P+ G4 f3 ]6 T/ Z4 ~: ~9 G, Q# M) e6 G. c0 w# U
%dir8 [- w! M+ o9 a3 V, P+ L
: d0 L& L9 t, [
宏可确保路径是此 RPM 拥有的目录。这一点很重要,因此 RPM 文件清单准确知道在卸载时要清理哪些目录。示例: %dir %{_libdir}/%{name}/ ~4 ?" [; Q6 H! ~
2 U7 [; L I: p' g1 h* a%config(noreplace)7 u3 S& L7 `/ X
/ p9 o- l0 P( b. r宏可确保以下文件是一个配置文件,因此如果从原始安装校验和中修改了该文件,则不应在软件包安装或更新包时覆盖(或替换)。如果有更改,则会在升级或安装时使用 .rpmnew 创建该文件,以便不修改目标系统上的预先存在的或修改的文件。示例:%config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf/ J8 ?8 y/ ]7 m- G' ], x: C
! w( G& E5 j' X$ ]/ h( ]9 _! I4.2.4. 显示内置宏
. h- {' p, T8 A# q& K$ ^% \% |1 q复制链接
7 A3 H' u+ ^. G! o9 x提供多个内置 RPM 宏。5 g9 F1 _- _( v; Y; r" d$ p$ B
7 W( V3 V# ?) o. j5 h流程
/ U5 I, J$ {* z" r! b( d5 L! B+ ~6 D+ l+ [, h4 ]
要显示所有内置 RPM 宏,请运行:
S1 P) R# k( h6 j/ r! A+ u6 j
* q( d4 I+ a# s6 y, prpm --showrc% p$ h" r* B- ?" }. z
注意/ [" f4 w1 F0 z3 H# b7 v( `
输出很长。要缩小结果范围,请在 grep 命令中使用上述命令。/ d5 Y$ C3 q1 A+ x2 Y- `
% F3 F9 I; g2 x% k. F& z9 q$ o要查找有关您系统 RPM 版本 RPM 宏的信息,请运行:
: n U: V. O# N1 i/ [
$ ~2 y4 ^% B4 B9 v3 hrpm -ql rpm
$ d$ ^) z9 @- ^6 B( K/ v5 n注意
2 t) {: P$ `" D- ~0 ~' tRPM 宏是在输出目录结构中标题为 macros 的文件。( q# ]) \/ ^1 S8 |$ k) x
2 u; a/ v4 }( }: ~6 w" t# L! \4.2.5. RPM 发布宏 8 {1 q. r9 I) G" B. @
复制链接
. w% Y. K& L" B6 g* H- d不同的发行版根据被打包的软件语言或发布的具体准则,提供不同的推荐 RPM 宏集合。4 D* M) h6 h8 j' C! p
/ t$ F) O* x+ x' I' k4 z推荐的 RPM 宏集合通常作为 RPM 软件包提供,可以使用 yum 软件包管理器进行安装。
' m+ ]5 ^5 U/ d5 Y
* o8 q2 z1 l- V- g& r安装后,宏文件可在 /usr/lib/rpm/macros.d/ 目录中找到。
9 M( V! q- b" y% [7 s! j* R6 }2 Z) [" p/ }" x. F0 n" R: p
要显示原始 RPM 宏定义,请运行:
* t" H$ n# {/ A- l9 R0 q& e4 u
) l8 p3 H+ n" B& z0 Krpm --showrc* j; P; I- ?* Y$ _/ N
以上输出显示原始 RPM 宏定义。9 F f. ^, N0 }0 i& @: L
$ M5 {' d1 M8 A6 c要确定宏的作用以及在打包 RPM 时如何有帮助,使用宏名称作为其参数运行 rpm --eval 命令:. r+ o: G ?# t& R& E# P' [" k
. T X6 ^( ?" A, ?" D; jrpm --eval %{_MACRO}
+ E6 M0 b- [% K$ o7 z详情请查看 rpm man page。
' B3 R* O) m) [ J, y) V
z# Z; [( }2 n9 P, @4.2.5.1. 创建自定义宏 " {: N/ O' k6 X1 @
复制链接
?! Q! {: T6 R T' i% e6 p您可以使用自定义宏覆盖 ~/.rpmmacros 文件中的发布宏。您所做的任何更改都会影响您计算机上的每个构建。
8 R6 B/ I) Y3 ~* D4 z' z! H$ I# Y0 V% B
警告6 W7 {6 B8 D+ q1 N. u" [9 a/ R7 q
不建议在 ~/.rpmmacros 文件中定义任何新宏。其他机器上不会包括此类宏,因为用户可能想要重新构建您的软件包。4 \0 w$ [6 W6 F1 X8 h d
6 _& ]1 ^4 x x6 C& r要覆盖宏,请运行 :
- ~- }9 B- m) f5 x/ c5 N5 \
6 V" Q+ T% h( z x4 w! Y%_topdir /opt/some/working/directory/rpmbuild
( [8 N0 x: H3 B n* A您可以从上面示例中创建 目录,包括通过 rpmdev-setuptree 实用程序的所有子目录。此宏的值默认为 ~/rpmbuild。
# @/ h$ D3 M6 ~( | ^6 g7 \9 O! G; b' c, O [
%_smp_mflags -l3
) f# J V! W+ e/ Z' a以上宏通常用于传递 Makefile,如 make %{?_smp_mflags},并在构建阶段设置多个并发进程。默认情况下,它被设置为 -jX,其中 X 是内核数。如果您更改了内核数量,您可以加快或减慢软件包构建速度或减慢速度。
# `! B; F- B* Q) \8 s: }' X
" n% q0 A. w: T! c4.3. Epoch, Scriptlets 和 Triggers 0 B/ R+ U0 D5 M- g4 r- ?) x6 R
复制链接
( h: p- E- T6 ^# z本节介绍 Epoch、Scriptlets 和 Triggers,它们代表 RMP SPEC 文件的高级指令。, F. u7 r' C, T* v/ C
~! I2 J: D% E2 e. V, T所有这些指令都影响不仅影响 SPEC 文件,还影响到安装结果 RPM 的末尾计算机。; e0 V" t" J1 N4 I
9 {6 J O6 J5 w4.3.1. Epoch 指令
+ z9 P3 q" ]1 ~+ X6 x复制链接, L0 U, ?- v$ {! w+ q
Epoch 指令支持根据版本号定义权重的依赖关系。
$ ?8 F! Z! U0 y9 ?) |7 U6 \
+ Z" l! H: A% s# Q e如果 RPM SPEC 文件中未列出此指令,则完全不设置 Epoch 指令。这与常规的理解不同:不设置 Epoch 的结果是 Epoch 为 0。但是,YUM 实用程序将未设置的 Epoch 视为 Epoch 为 0,用于 depsolving。7 _ ?4 `! @( j# Q
8 L( e* ~) S- Y' g* \3 n ^; P) D但是,在 SPEC 文件中列出 Epoch 时通常会被省略,因为在大多数情况下,如果使用 Epoch 值,则在进行软件包版本比较时会 skews 预期的 RPM 行为。
- }6 f$ C1 v4 R( e) K
! c2 w1 Z0 ~: \/ V: @例 4.2. 使用 Epoch
5 o- {2 r) Z, Z( n. V% X8 B% q* y. i$ L- v
如果您使用 Epoch: 1 和 Version: 1.0 安装 foobar 软件包,其他软件包 foobar with Version: 2.0 但没有 Epoch 指令,则新版本永远不会被视为更新。原因是,在签发 RPM 软件包版本是首选使用 Epoch 版本而不是传统的 Name-Version-Release marker。 Z+ Y) o3 r* U2 k/ ?% |
" g% m( ]0 V, H# F$ T
使用 Epoch 比较罕见。但是,Epoch 通常用于解决升级排序问题。在软件版本号方案或带有字母字符的版本中,这个问题可能会出现上游变化的影响,这些字符不能始终根据编码进行可靠地进行比较。
6 U' m- B+ r: K+ i' k ?1 }2 h0 I$ d. C
4.3.2. Scriptlets ( K4 K. {- t5 p9 b1 \; a( l
复制链接% U% p1 d- Q& g
Scriptlets 是一组在安装或删除软件包之前或之后执行的 RPM 指令。
3 A8 \& k# s3 {- M7 Q/ ?% T% K6 Z7 ^- E& g
使用 Scriptlets 仅在构建时或启动脚本中无法完成的任务。
. v7 H, J5 L' c" j) |5 T: |5 X) W& i1 T
4.3.2.1. scriptlets 指令
y: ]# h# v* H0 w( b2 N7 Q复制链接
) \( T1 T' ]8 c存在一组常用 Scriptlet 指令。它们和 SPEC 文件部分标题类似,如 %build 或 %install。它们由多行代码段定义,这些片段通常写为标准的 POSIX shell 脚本。但是,它们也可以使用其他适用于目标机器分布接受的 RPM 编程语言编写。RPM 文档包括可用语言的详尽列表。) E. o# o/ [ }5 P+ b7 G
2 l9 D' c9 q8 |; _0 e
下表包含 Scriptlet 指令,按其执行顺序列出。请注意,包含脚本的软件包会在 %pre 和 %post 指令之间安装,并在 %preun 和 %postun 指令之间卸载。' b( \; ]2 R$ d# \7 U7 A; f2 ?- l
* }6 x. E3 ^5 B% c% `. s
表 4.2. Scriptlet 指令
: Q- D0 ^, X! ^6 P指令 定义
0 d3 W7 o- |( l%pretrans
) p! R6 N# t$ x9 B& | k1 ~( K4 J9 y. D. b% j6 I( M
Scriptlet 在安装或删除任何软件包之前执行。0 s( U O8 |# F/ q' K& Y
7 `# f; t& }2 W5 _
%pre+ X! r5 S+ N7 }$ v8 v
% V; l0 R6 S- I7 e1 b! R
Scriptlet 在目标系统上安装软件包之前执行。- C0 b! L Z7 L' t+ W
) H- j, x" o- g4 R
%post0 O/ ?3 d& f; ^5 u/ p
- ^1 U# b, s* s* g9 `( z
Scriptlet 仅在目标系统上安装软件包后执行。9 V: ?$ }! y9 X. m
* |/ o# S/ k6 E) Q4 C
%preun
0 S) N! A; F( f( b4 R5 |. P2 `: n8 J. h R' u% R
在从目标系统卸载软件包前执行的 Scriptlet。
0 @) S* X/ Z( o0 F$ n9 X- P- M6 ?( @5 E I- v( |' N! k( R/ \
%postun
6 J+ m4 }2 c0 J6 B; h: _1 Y+ l. t) Q. [
Scriptlet 在软件包从目标系统卸载后执行。6 u" B8 `9 K, N8 r7 ?; o
- Q: w0 F4 e9 q" S
%posttrans0 U, l0 f9 _% o4 ^: |% M, d$ J
: `# W8 d" E& K! i8 ]4 G6 X6 X6 D在事务结束时执行的 Scriptlet。) ^& s, X u) v
: v; U$ D. b8 W, Z6 G8 h4.3.2.2. 关闭 scriptlet 执行 6 z5 M/ F& ]5 x- Q& y# ]5 l8 l
复制链接
' m. }: E: ~0 A" P4 {; [6 {要关闭任何 scriptlet 的执行,请使用 rpm 命令和 --no_scriptlet_name_ 选项。
& q' \6 H& K* a9 ~/ v2 u% S$ r
流程
$ a3 v' h- q8 e4 D8 f
% X1 q$ x6 x5 \/ Y6 g例如,要关闭 %pretrans scriptlets 的执行,请运行:
7 [6 T. c" d- ~" o1 ~! Z6 g, l6 |6 k. a! Y
# rpm --nopretrans# ?; X7 [/ x& l i# I$ B' F+ K
您还可以使用 -- noscripts 选项,它等同于以下所有:
) f! ?: ^4 ]3 A; e# ~6 o9 q7 y7 f; O5 r
0 H3 J' _# e1 i' S8 H v--nopre
' C2 U+ v3 H, M3 n--nopost
J( n% s; m, n* _( ]/ @- i--nopreun
0 {# }5 g) z7 q--nopostun
* H* H9 u: V1 K2 g9 F9 J: d--nopretrans
: ?2 ?0 `0 H! H- i--noposttrans' }0 d1 {, n) n' B2 ^
其他资源
! J6 | w; P- ~6 ~' J. c/ j) {" J
# {- V: Z! e/ m! h- l4 \* X详情请查看 rpm (8) 手册页。
. ]! k. C9 U* M3 \4.3.2.3. scriptlets 宏 $ z7 M, a! x6 {2 h- x0 n
复制链接- L/ u( I! L; Z
Scriptlets 指令也适用于 RPM 宏。 ~) K" B4 l8 R+ K |) p% | l
! T c) I6 U k以下示例显示了使用 systemd scriptlet 宏,这样可确保 systemd 会收到有关新单元文件的通知。0 H+ V- z9 e! x! S
( b8 l. r! K2 @& `0 w9 ~. m$ rpm --showrc | grep systemd
* g3 m* O. Z$ g-14: transaction_systemd_inhibit %{plugindir}/systemd_inhibit.so
7 L8 S$ ~* Z: H* s* N C% O-14: _journalcatalogdir /usr/lib/systemd/catalog
1 K7 H/ B1 ]! A$ x-14: _presetdir /usr/lib/systemd/system-preset
4 C( r. K5 q0 U. p-14: _unitdir /usr/lib/systemd/system8 P( f9 s+ M7 p8 m
-14: _userunitdir /usr/lib/systemd/user
( Y% N+ g; t& Z; l' {# ~" z$ ]/ C* d/usr/lib/systemd/systemd-binfmt %{?} >/dev/null 2>&1 || : /usr/lib/systemd/systemd-sysctl %{?} >/dev/null 2>&1 || :3 G+ z. r6 m K/ k
-14: systemd_post
$ u) e* {% B5 c$ h$ z-14: systemd_postun% k: D9 N- c7 @! E! k- i+ z
-14: systemd_postun_with_restart
4 H2 O4 x! ?! j# L2 l-14: systemd_preun- i# k, _" z$ E$ h7 w' R# n! i
-14: systemd_requires6 w$ o6 v8 a2 W3 f) T
Requires(post): systemd
) M# \- M) X" @+ y N$ pRequires(preun): systemd
/ _ h! S$ U5 x+ P# A: ~$ f- [ KRequires(postun): systemd1 q7 e) o! ? Q1 A4 o
-14: systemd_user_post %systemd_post --user --global %{?} -14: systemd_user_postun %{nil} -14: systemd_user_postun_with_restart %{nil} -14: systemd_user_preun systemd-sysusers %{?} >/dev/null 2>&1 || :
2 y D, J) g7 E$ ~echo %{?} | systemd-sysusers - >/dev/null 2>&1 || : systemd-tmpfiles --create %{?} >/dev/null 2>&1 || :
# z; |8 E2 n* u) Z/ W8 {( @# ?9 ^3 F6 J. g/ F `
$ rpm --eval %{systemd_post}+ A7 p( w3 j' d s( s
$ f- E3 E' P0 K8 `' x' Z+ U, Vif [ $1 -eq 1 ] ; then5 p) \; L9 q8 s! W0 D% Y9 d3 _
# Initial installation/ S; [4 ?! w8 n9 I* e. n1 f8 ?' w, Q
systemctl preset >/dev/null 2>&1 || :& j9 Y% `( A% ~: F* {& P
fi
( E/ x; j# B5 L/ G Q4 n s% Z' R' c, a1 \
$ rpm --eval %{systemd_postun}
/ f- o2 P5 U* x7 g) Q" @: G! O* r6 R# E3 O6 h8 E( W5 Z9 ?4 M
systemctl daemon-reload >/dev/null 2>&1 || :) T7 o/ |4 }; F6 e8 v6 {
, m1 L; M/ ]; z
$ rpm --eval %{systemd_preun}4 }8 t' {" r1 u$ ^5 ~
+ m! z5 i* T+ [5 W) i: F
if [ $1 -eq 0 ] ; then
9 l2 q* T3 }) f # Package removal, not upgrade% F2 N- f5 q2 }; U f7 Z4 N: ?
systemctl --no-reload disable > /dev/null 2>&1 || :
, _! }9 n& p) i9 g, }1 @ systemctl stop > /dev/null 2>&1 || :
( m# e" Y- F. d* e) v$ Z; C& }& zfi
4 D/ H' E) k( U, f% \' }/ kExpand/ Y& i; n# B) P, s
4.3.3. Triggers 指令
7 F: f4 t C2 p- D5 C复制链接, c5 {# T/ e' K
Triggers 是 RPM 指令,可提供在软件包安装和卸载期间交互的方法。
) E6 s1 E2 F2 r C. h: p8 |4 F, Y4 i# l
警告
* K8 P f3 c* N( k3 A4 ~Triggers 可能会在意外执行,例如在更新包含软件包时执行。很难调试 Triggers,因此需要以可靠的方式实施它们,以便在意外执行时不会中断任何操作。因此,{RH} 建议最小化 Triggers 的使用。; T! m8 ~5 G" Q2 m
$ y5 R$ p' I& a2 X8 C! Y# S下面列出了执行顺序以及每个现有 Triggers 的详情:
. }) a; h) u- a( y+ w+ {3 ?% b0 t1 ^3 M K+ L% d5 O
all-%pretrans! G9 N; S2 S5 |$ u' |
…
4 B+ \8 M* m# m2 tany-%triggerprein (%triggerprein from other packages set off by new install)
. @2 Y! V% E$ xnew-%triggerprein
# \% K: o& J8 S onew-%pre for new version of package being installed4 l0 V8 e: s* Q$ l' ]9 ?$ V/ K" W! m
… (all new files are installed)
+ ^, { I* f% Y- q Z# R( Gnew-%post for new version of package being installed7 I" s, {4 c; ]0 c6 K- L
0 `# d1 H. u, z; ?
any-%triggerin (%triggerin from other packages set off by new install)
% Z( |8 A5 x7 T$ S; j @. ynew-%triggerin; f0 K/ m9 f2 E/ E$ F, S) G
old-%triggerun3 A7 b. m) \# b1 z: P7 q5 K1 @
any-%triggerun (%triggerun from other packages set off by old uninstall)
: c" y$ x6 L$ O- t# S! M- b9 `8 a5 i) j4 H! @5 \
old-%preun for old version of package being removed
; g) X0 \ ^ h3 J3 S8 ^7 j( r5 o… (all old files are removed)
! u8 |* T3 l( N! m5 r' Uold-%postun for old version of package being removed
$ b) L" |3 y, L$ p1 a: F
' c' m" [: G5 R% E& i. o ~% oold-%triggerpostun1 @9 k/ ]: B5 d# X6 |0 v o& S
any-%triggerpostun (%triggerpostun from other packages set off by old un
) h8 @4 G# `! Q7 o2 n install)
3 H& G5 b. D6 D…$ s/ A' ?2 J; ^ }$ V
all-%posttrans0 y' M$ u& N- I9 [3 A
以上项目位于 /usr/share/doc/rpm-4.*/triggers 文件中。
2 a; i2 Z- [9 i! q" Z6 _+ h' E8 E( ?- U! g9 n0 D
4.3.4. 在 SPEC 文件中使用非 shell 脚本
( g( x6 J9 a3 L% U8 L) n, B0 r复制链接
7 v% ?. x+ |4 I+ G! K8 D5 t. F' c+ HSPEC 文件中的 -p scriptlet 选项允许用户调用特定的解释器,而不是默认的 shell 脚本解释器(-p /bin/sh)。+ ~+ X; |* E6 Q Z1 L; ?
2 \6 c* l& Q5 \9 H! x) a
下面的步骤描述了如何创建脚本,它会在安装 pello.py 程序后输出信息:+ o4 k5 E5 Q/ w1 y: g! t
0 s8 m5 X( D& D% b4 V; Y" F' s8 g步骤' L- _0 h+ @& b& ?+ R
+ j- }6 Z# ^8 x( g
打开 pello.spec 文件。; r5 Q; j- P5 f
找到以下行:2 ^) A& ]" K; y# D* u
8 R. q% w5 n& U% ^# C' f! zinstall -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/
+ s) a' N T' w4 y# G, u* T6 i在上面的行下,插入:
( S5 S7 g6 C+ W9 l s6 {
/ d* j! t0 K6 Q @+ ?2 c%post -p /usr/bin/python34 u0 d# R" i/ {9 c/ H% u& ?) O
print("This is {} code".format("python"))
2 O3 d6 }! j5 a/ f; n; h, [安装软件包:
# M' C6 L# s% ]; p8 P, \
9 k( |) t! S( p' l, }4 }# y* @# yum install /home/<username>/rpmbuild/RPMS/noarch/pello-0.1.2-1.el8.noarch.rpm) f! B) H" a( {
安装后检查输出信息:0 Q: x C8 C5 O
6 @7 O [% h) R2 t" P1 }
Installing : pello-0.1.2-1.el8.noarch 1/1
: d) m$ f- {. |* S; v$ n; LRunning scriptlet: pello-0.1.2-1.el8.noarch 1/13 z7 p- c r3 g9 H8 `2 f
This is python code
# c7 j! o5 P! Z+ ?9 T+ v z' h注意
) e3 N3 n5 z0 W# i* b* o要使用 Python 3 脚本,在 SPEC 文件中的 install -m 下包含以下行:
& q- ~; R E6 l9 \/ g( a, p1 Y, \! y- [5 R
%post -p /usr/bin/python3
9 e) Z0 H) t. f! L; v/ i要使用 Lua 脚本,在 SPEC 文件中的 install -m 下包含以下行:
2 W3 @6 q5 l4 p& P8 H! | r, D
3 i0 ~5 r* d2 `; e7 @5 F6 U1 j& P%post -p <lua>" O! j t* @: O% @$ H* d
这样,您可以在 SPEC 文件中指定任何解释器。2 V Y) @( c' Q$ Z% e) Z9 K% |% V
8 u4 w' o. L) @4 C, Z' I6 x+ `6 W4.4. RPM 条件
5 {8 p' Q0 x' r; l5 m复制链接
0 U; n% m1 B* sRPM 条件可启用 SPEC 文件的各种部分的条件。8 p$ J, N5 n4 J' T! Z" `" P1 f$ v
& T2 P+ Z( L/ [+ F! p. K% ]
条件包括通常会处理:: j3 D" r" B P0 S
3 o8 ?3 x8 f% d5 u$ m) F
特定于架构的部分
$ I2 @ b4 n& j特定于操作系统的部分
; G) c% o8 s- L7 a& i5 x9 }: [不同操作系统版本之间的兼容性问题5 y- u+ p! t. A- T5 X( F1 [1 Z
宏的存在和定义
7 j S1 j0 D, \. g4.4.1. RPM 条件语法 y& A' R2 {; g
复制链接3 a4 m9 F9 u o
RPM 条件使用以下语法:# @, R! ^* F- G. j# A; i) m- W
2 k4 f& V C6 s+ T. I% f" C
如果 expression 为 true,则执行一些操作:
/ t$ ^8 Y7 D% b6 s J' ]' u$ u8 c' K7 s5 B6 f
%if expression) R& F3 P {+ J5 U' `" _, ?
…
" x& a. d" ~1 b" Y! B9 q6 y%endif
1 G* Q1 z! ~7 W如果 expression为 true,则执行一些操作,在其他情况下执行另一个操作:
* v4 t' x6 I+ v" f4 a' P
4 Q# e4 @) O: h4 r%if expression/ o' _/ }6 P3 G) R8 ~& Z4 m
…
. k: W. T8 }* q6 [5 T: O5 O( I/ z%else
- C, @4 I3 H7 U2 r…- P) o$ o' S" r/ K
%endif6 b, Z- M) j: X6 J. m5 R# B' S" [. ]
4.4.2. RPM 条件示例 5 @% E% [9 G* [7 |2 e0 O
复制链接/ E- Z" P+ Z7 k0 B" i1 k$ z, L# F
这部分提供了 RPM 条件的多个示例。) e4 Q2 j( I# Y% ~# H) r
2 n* v( O, ] d, z: Q+ w" ]+ e4.4.2.1. %if 条件
. u+ X3 T$ B# H6 F4 K$ [9 P复制链接* G# n0 |/ u, V- h$ T V
例 4.3. 使用 %if 条件来处理 8 和其他操作系统间的兼容性7 Z6 b+ [' L; g" Q5 w+ v2 J
: b' v- R2 B6 b1 _9 ~
%if 0%{?rhel} == 8+ I' K. u$ M# x) ]% S) s) D7 \
sed -i '/AS_FUNCTION_DESCRIBE/ s/^//' configure.in sed -i '/AS_FUNCTION_DESCRIBE/ s/^//' acinclude.m4
L! _- e; R8 d5 ^( c%endif
0 W$ Z/ C4 ?9 U. i* t这个条件在支持 AS_FUNCTION_DESCRIBE 宏时处理 RHEL 8 和其他操作系统间的兼容性。如果为 RHEL 构建软件包,则会定义 %rhel 宏,并将其扩展到 RHEL 版本。如果它的值是 8,表示软件包是为 RHEL 8 构建的。然后对 AS_FUNCTION_DESCRIBE 的引用(不被 RHEL 8 支持)会从 autoconfig 脚本中删除。2 o8 M; g5 Z6 R
$ S+ Y+ G! t# q) X8 H. m! A例 4.4. 使用 %if 条件句处理宏定义
$ O) v, ^& x( `/ l% t' t3 n8 K8 r9 _! l+ `" S
%define ruby_archive %{name}-%{ruby_version}$ I+ K' r! T8 x! g+ g; b: T
%if 0%{?milestone:1}%{?revision:1} != 0/ a: q3 M; C; I
%define ruby_archive %{ruby_archive}-%{?milestone}%{?!milestone:%{?revision:r%{revision}}}) d* D( ?1 a2 L4 c
%endif7 J5 `: ~, h" O" N
这个条件处理宏的定义。如果设置了 %milestone 或 %revision 宏,则会重新定义用于定义上游 tarball 名称的 %ruby_archive 宏。 a$ B; s4 H# V9 y' }; h
2 b$ }( g6 a+ Y$ W) r) Q& B: h$ O3 L
4.4.2.2. %if 条件的专用变体 2 R6 T2 P+ F0 M" Q- @, ?
复制链接
Q. h2 y |1 d, v6 C4 E- ^+ n) t%ifarch 条件、%ifnarch 条件和 %ifos 条件是 %if 条件的专用变体。这些变体常被使用,因此它们有自己的宏。
3 z$ u9 ]: A( y
: ~; w& y% g1 Z4.4.2.2.1. %ifarch 条件 5 t8 E: i9 v# r2 D, P
复制链接3 X" i/ G/ |% M. j/ ^# ^
%ifarch 条件用于开始特定于体系结构的 SPEC 文件的块。它后接一个或多个架构说明符,各自以逗号或空格分开。
" N1 t0 O2 [) g" G4 X' Y3 z( p
* h% h' y! R$ ~: x7 }* S: }; A例 4.5. 使用 %ifarch 条件的示例
0 K4 `" `; x8 K O' P" \& x% Q5 R* s( b' t z+ g+ R
%ifarch i386 sparc
6 f0 C5 v, E1 O( r3 g! N# z…2 o Y$ A! o1 M
%endif5 @/ `. ?# x7 N/ ?: f
在 %ifarch 和 %endif if 之间所有 SPEC 文件的内容都仅在 32 位 AMD 和 Intel 构架或 Sun SPARC 的系统中处理。
3 }% h, D4 m3 K# ~9 t& G; ~% W3 U; R0 P, b
4.4.2.2.2. %ifnarch 条件 . x! [& H& ^" e+ V; ~4 w
复制链接6 Q- J7 Z" g' z/ u/ M. H' H
%ifnarch 条件的逻辑与 %ifarch 条件的逻辑相反。% Z3 l9 \* \' W
: A. C$ i# ]# P, P4 E. l
例 4.6. 使用 %ifnarch 条件的示例
) Q R+ n+ m6 Q' h w) P& N0 E1 |1 `7 u' O& Z& V
%ifnarch alpha; M3 p6 ]* S9 r
…( Q1 f; e2 [6 ^- l& N! [' E- P& {
%endif
0 G! l! f1 a$ r6 q& B Y: I只有在基于 Digital Alpha/AXP 的系统上的数字 Alpha/AXP 系统上执行时,才会处理 %ifnarch 和 %endif 之间的 SPEC 文件的内容。
: |& ^3 b7 I# D5 p' X9 W
, Y$ T9 {1 {1 o6 _# Q& o/ `4.4.2.2.3. %ifos 条件 * C7 t) U0 A) F% |- p. d
复制链接
$ l: V% \, w3 P* ^5 h%ifos 条件用于根据构建的操作系统控制处理。其后可以使用一个或多个操作系统名称。+ g ~( |: L: j! Z/ o/ u% I
9 b, d& Q e, ]# c- t
例 4.7. 使用 %ifos 条件的示例
$ E4 k: ~" \9 B) E
9 n& D4 z5 G. E b( \- C J%ifos linux
! n# k1 X8 S; z1 Z. c' U; b2 w…8 o, f, p: o N, }1 V
%endif' H( g3 D: ` P
只有 Linux 系统上完成构建时,才会处理 %ifos 和 %endif 之间的 SPEC 文件的内容。7 p! O7 g( f- t$ X4 a
7 _' x, U( M9 N/ O: t. u! ?附录 A. RHEL 7 中 RPM 的新功能 % F% { J Y% m1 ]6 D1 p
复制链接$ u* q4 s4 C8 n) ~' I0 w) I
此列表记录了 Red Hat Enterprise Linux 6 和 7 之间 RPM 打包中最显著的变化。
4 A, Y1 e/ U: A1 u, f. M% ]
9 S0 q; L" g ~- ~! K; Y添加了一个新的命令 rpmkeys,用于密钥环导入和签名验证。
; A( y) x8 u0 ~% T6 H6 f添加了一个新的命令 rpmspec,用于 spec 查询和解析输出。
9 [. [* M6 ]* R添加了一个新的命令 rpmsign,用于软件包签名。; @4 S) i# e- U! A% ]7 ^
posix.exec () 和 os.exit () 扩展嵌入在 %{lua:…} 脚本中,除非从使用 posix.fork () scriptlet 创建的子进程调用。
9 W: x3 W7 I B% c. L% q%pretrans scriptlet 失败会导致软件包安装跳过。
4 j/ ^3 ^4 q& S* _6 Fscriptlet 可以在运行时宏排除并查询格式。
" `' h) ?1 d4 b* j现在,pre-transaction 和 post-transaction scriptlet 依赖项可以使用 Requires (pretrans) 和 Requires (posttrans) scriptlet 正确表示。; m( F- ^9 j: g: l" t* O
添加了用于提供额外排序提示的 OrderWithRequires 标签。标签遵循 Requires 标签语法,但不生成实际依赖项。只有在计算事务顺序时,排序提示才会被视为 Requires,只有在涉及的软件包在同一事务中存在时。/ R/ ~4 N, N! ^: l" }' x2 T
%license 标志可在 %files 部分中使用。此标志可以与 %doc 标志类似,将文件标记为许可证,尽管需要安装 --nodocs 选项。, b5 n& [, \7 y
添加了用于自动化补丁应用程序的 %autosetup 宏,并添加了可选的分布式版本控制系统集成。
4 q6 U/ k4 V8 o7 B自动依赖项生成器已被重写为可扩展且可自定义的基于规则的系统,并具有内置过滤。
+ F, l' c! g! \% dOpenPGP V3 公钥不再被支持。- E% ]) i- g+ \" h+ J
第 5 章 关于 RPM 打包的其他资源 , W( J$ \) [% g- k; W( ?
复制链接4 r$ H$ e0 |2 a' C: w! x& `
本节介绍了与 RPM、RPM 打包和 RPM 构建相关的各种主题。其中一些是高级的,并扩展了本文档中包含的简介资料。
# p# }+ D) R! N7 T" v! w
. h( _9 P8 F a$ mRed Hat Software Collections Overview - Red Hat Software Collections 产品在最新稳定版本中提供持续更新的开发工具。
: g2 l- |! ]8 f( |: ?! l- d3 o* }! j) P0 i# c% \
Red Hat Software Collections - 打包指南介绍了 Software Collections 以及如何构建和打包它们。具有基本了解 RPM 的软件打包的开发人员和系统管理员可以使用本指南来启动 Software Collections。
* x) A8 M* I' k1 G% g2 G4 q
3 ?5 l0 J5 N1 ZMock - Mock 为各种架构及 Fedora 或 RHEL 版本相比具有构建主机的不同架构提供社区支持的软件包构建解决方案。3 n: T: j$ t: j0 ^9 |/ D& x
! w) }. T7 r5 v1 Y( `# ]: FRPM 文档 - 官方 RPM 文档.
6 V) @5 P. b$ o/ F6 y: r& K+ y1 d& b G) p6 l- L1 l
Fedora 打包指南 - Fedora 的官方打包指南,适用于所有基于 RPM 的发行版。 |
|