01 打包前的准备工作
1. 如何制作程序⚓
虽然有很多方法将人类阅读的源码转换为机器码,但是可以归纳为以下三种:
- The program is natively compiled.
- The program is interpreted by raw interpreting.
-
The program is interpreted by byte compiling.
-
程序是本地编译的
- 程序通过原始解释器解释
- 程序通过字节编译解释
1.1 Natively Compiled Code⚓
本机编译的软件是指用编程语言编写的软件,编译成机器代码,生成二进制可执行文件。这种软件可以独立运行。
以这种方式构建的RPM包是特定于架构的。意味着如果你在64-bit架构的机器上编译,则不能在32-bit架构的机器上运行。打包的结果会在名字中含有特定的架构。
1.2 Interpreted Code⚓
一些编程语言(bash、python等)不会编译成机器码。相反,他们的程序的源代码是由语言解释器或语言虚拟机逐步执行的,无需事先转换。
完全用解释型编程语言编写的软件不是特定于架构的。于是RPM包名中会含有noarch
。
解释型语言又分为两种,这两种类型在程序构建过程和打包过程中有所不同:
- raw-interpreted:
Raw-interpreted 语言程序完全不需要编译,直接被解释器执行。
- byte-compiled
Byte-compiled 语言需要被编译为字节码,然后在虚拟机中执行。
注意:某些语言可以选择两种模式中的一种。
2. 三种语言类型构建过程举例⚓
2.1 Natively Compiled Code⚓
C语言源码cello.c
:
#include <stdio.h>
int main(void) {
printf("Hello World\n");
return 0;
}
2.1.1 手动构建⚓
gcc -g -o cello cello.c
执行:
$ ./cello
Hello World
2.1.2 自动构建⚓
Makefile
:
cello:
gcc -g -o cello cello.c
clean:
rm cello
构建:
$ make
make: 'cello' is up to date.
执行:
$ ./cello
Hello World
2.2 Interpreted Code⚓
2.2.1 Raw Interpreted Code⚓
bello
:
#!/bin/bash
printf "Hello World\n"
运行:
$ chmod +x bello
$ ./bello
Hello World
2.2.2 Byte-Compiled Code⚓
python源码可以是raw-interpreted
,但是byte-compiled
版本更快。因此,RPM倾向于打包byte-compiled
版本以发布给最终用户。
pello.py
:
#!/usr/bin/env python
print("Hello World")
Byte-compile pello.py
:
$ python -m compileall pello.py
$ file pello.pyc
pello.pyc: python 2.7 byte-compiled
执行:
$ python pello.pyc
Hello World
3. 为软件打补丁⚓
使用diff
工具检查不同,输出补丁文件;使用patch
工具对文件打补丁。类似于版本控制系统git
。
为cello.c
文件打补丁举例:
- 保存原文件
$ cp cello.c cello.c.orig
- 修改源码
cello.c
#include <stdio.h>
int main(void) {
printf("Hello World from my very first patch!\n");
return 0;
}
- 使用
diff
生成一个补丁
$ diff -Naur cello.c.orig cello.c
--- cello.c.orig 2016-05-26 17:21:30.478523360 -0500
+++ cello.c 2016-05-27 14:53:20.668588245 -0500
@@ -1,6 +1,6 @@
#include<stdio.h>
int main(void){
- printf("Hello World!\n");
+ printf("Hello World from my very first patch!\n");
return 0;
}
- 将补丁保存到文件中
$ diff -Naur cello.c.orig cello.c > cello-output-first-patch.patch
- 恢复原文件
$ cp cello.c.orig cello.c
- 使用
patch
应用补丁
$ patch < cello-output-first-patch.patch
patching file cello.c
4. 安装任意部件⚓
linux使用了Filesystem Hierarchy Standard (FHS)来规定何种文件存放在哪里。
下面介绍两种方法将任意文件放在操作系统中。
4.1 使用 install 命令⚓
有时使用自动构建工具(make等)并不是最优选择,比如,如果打包的程序简单而且不需要提取开销。此时经常使用install
命令将文件以指定权限放在指定目录。
$ sudo install -m 0755 bello /usr/bin/bello
4.2 使用 make install 命令⚓
在Makefile
中添加install
部分:
cello:
gcc -g -o cello cello.c
clean:
rm cello
install:
mkdir -p $(DESTDIR)/usr/bin
install -m 0755 cello $(DESTDIR)/usr/bin/cello
构建与安装:
$ make
gcc -g -o cello cello.c
$ sudo make install
install -m 0755 cello /usr/bin/cello
5. 为打包准备源码⚓
开发者经常发布软件方式是压缩打包源码。
软件应与软件许可证(license)一起分发,一般写在LICENSE
文件中。GPLv3 license:
$ cat /tmp/LICENSE
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.
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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
5.1 将源码放到压缩包中⚓
下面的例子使用gzip
压缩包。
5.1.1 cello⚓
- 将文件放在单独的文件中,版本是1.0
# 注意,文件夹名称必须和 “name-version” 一致
$ mkdir /tmp/cello-1.0
$ mv ~/cello.c /tmp/cello-1.0/
$ mv ~/Makefile /tmp/cello-1.0/
$ cp /tmp/LICENSE /tmp/cello-1.0/
- 创建用于发布的打包文件并移动到
~/rpmbuild/SOURCES/
$ cd /tmp/
$ tar -cvzf cello-1.0.tar.gz cello-1.0
cello-1.0/
cello-1.0/Makefile
cello-1.0/cello.c
cello-1.0/LICENSE
$ mv /tmp/cello-1.0.tar.gz ~/rpmbuild/SOURCES/
-
添加补丁
如果有补丁文件的话,将补丁文件也放在
~/rpmbuild/SOURCES/
下(如果不手动编写规则,好像不会应用补丁)。
$ mv ~/cello-output-first-patch.patch ~/rpmbuild/SOURCES/
现在,源码已经准备好打包到RPM中了。