Description
构建一个RPM包
1. rpmdevtools工具及SPEC文件
一些基础点 可以直接从下一章节看
网上找了好多相关的教程,RedHat的教程应该是最官方的。
目前没找到如何生成压缩包的,本文使用setuptools生成
还有说使用pyinstaller生成可执行文件然后获取其依赖并压缩的,没有测试这个
-
rpmdevtools工具
构建主要用的就是SPEC文件和源文件,将其放到对应的文件夹下执行构建命令
首先创建RPM的工作环境,便捷的就是安装rpmdevtools工具
执行rpmdev-setuptree命令后结果如下# rpmdev-setuptree # tree ~/rpmbuild/ /root/rpmbuild/ ├── BUILD ├── RPMS ├── SOURCES ├── SPECS └── SRPMS
工作环境目录用途如下
目录 用途 BUILD 构建时生成的各种信息都在这里 RPMS 构建出的二进制包 SOURCES 构建用的源文件放这里,如压缩包、补丁文件等 SPECS 构建用的.spec文件放这里 SRPMS 构建出的源码包 BUILDROOT 构建过程中创建,保存%install阶段安装的文件 -
SPEC文件
SPEC文件可以分为Preamble和Body两部分
Preamble:
SPEC指令 用途 Name package name Version version number Release NA Summary NA License NA URL 该包的上游网址 Source0 源文件 Patch0 数量可变 BuildArch 构建依赖的环境 BuildRequires 构建所需的依赖包 Requires 运行所需的依赖包 Body:
SPEC指令 用途 %description NA %prep 构建前的一些命令 %build 构建时执行的命令 %install 最终安装目录 %check 测试软件命令 %files 最终会安装在系统的文件 %changelog NA
2.构建一个简单的hello world rpm包
-
编写py文件
还是最通用的hello world
#!/usr/bin/python # -*- coding: utf-8 -*- def my_print(): print('hello world') if __name__ == '__main__': my_print()
-
编写setup.py文件
前面是license 命令是setuptools.setup
setup中哪些可以不需要还没有完全搞清楚,当前这样没有问题# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools setuptools.setup( name='myrpm', version='0.1.1', license='Apache License 2.0', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development :: Libraries :: Python Modules', ], packages=['myrpm'], include_package_data=True, zip_safe=False, platforms='any', )
-
目录结构
python-myrpm/ ├── myrpm │ ├── __init__.py │ └── myrpm.py └── setup.py
-
生成压缩包
在python-myrpm/目录下执行
python setup.py sdist
执行后目录如下 生成了myrpm-0.1.1.tar.gz压缩文件
感兴趣可以解压看看 我们就使用这个压缩文件作为源码构建RPM包python-myrpm/ ├── dist │ └── myrpm-0.1.1.tar.gz ├── myrpm │ ├── __init__.py │ └── myrpm.py ├── myrpm.egg-info │ ├── dependency_links.txt │ ├── not-zip-safe │ ├── PKG-INFO │ ├── SOURCES.txt │ └── top_level.txt └── setup.py
对应的还有一些其他命令,install是使用源码安装、build是构建、
clean是清理build和bdist生产的临时目录、bdist是生成二进制压缩包、
sdist是源码压缩包,--formats可以指定压缩包格式python setup.py build python setup.py install python setup.py clean python setup.py bdist
-
制作SPEC文件
优先使用工具创建 在SPECS目录下执行如下命令 生成myrpm.spec文件
rpmdev-newspec myrpm.spec
修改SPEC文件如下
%global debug_package %{nil} Name: myrpm Version: 0.1.1 Release: 1 Summary: simple python rpm License: Apache-2.0 URL: https://docs.openstack.org/tooz/latest/ Source0: myrpm-0.1.1.tar.gz BuildArch: noarch BuildRequires: python3-setuptools %description A simple python rpm %prep %autosetup -n %{name}-%{version} %build %py3_build %install %py3_install pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst fi popd mv %{buildroot}/filelist.lst . %files -n %{name} -f filelist.lst %dir %{python3_sitelib}/* %changelog * Thu Sep 21 2023 XXX <[email protected]> - init
其中
%global debug_package %{nil} 是缺少debug相关文件 当前不关注使用该命令忽略其报错
Source0填充包名
%prep 填充%autosetup -n %{name}-%{version}
%build 填充%py3_build
%install 填充%py3_install
pushd 这里是把最终会安装在系统的文件写入到filelist.lst中
%file 是指明哪些文件会安装在系统,如果有遗漏,构建是会提示
'error: Installed (but unpackaged) file(s) found'的报错
%license 和 %doc 当前不关注忽略对SPEC文件中更高级的修改需要进一步探索
-
构建RPM包
把第4步和第5步中的源码压缩包、SPEC文件分别放到SOURCE和SPECS目录下
~/rpmbuild ├── BUILD ├── RPMS ├── SOURCES │ └── myrpm-0.1.1.tar.gz ├── SPECS │ └── myrpm.spec └── SRPMS
在SPECS目录下执行rpmbuild命令
rpmbuild -ba myrpm.spec
构建成功后使用如下命令查询结果
tree /root/rpmbuild/*RPMS /root/rpmbuild/RPMS └── noarch └── myrpm-0.1.1-1.noarch.rpm /root/rpmbuild/SRPMS └── myrpm-0.1.1-1.src.rpm
-
RPM包使用
使用rpm -ivh 安装rpm包,安装后就可以import了
使用rpm -qa | grep 查询安装的包
使用rpm -e 卸载安装的包
当前发现卸载是会在/usr/lib/python3.9/site-packages/中残留__pycache__文件夹
暂时无法解决,试了下别的包也有这个问题
3.增量构建RPM包
增量构建可能描述的不准确,实际上是以git.patch的形式添加自己对已有RPM包的修改,然后构建
这种构建要使用源码包
RPM包一般分为二进制和源码包(后缀为.src.rpm)
包名中noarch字段表示无环境依赖
源码包可以通过rpm2cpio命令解压.src.rpm的包得到
也可以找到相关的SPEC文件,通过URL获取对应的压缩包
以上一章节中构建的RPM包为例,更改my_print的打印内容
-
解压rpm包获取源码压缩包
# rpm2cpio myrpm-0.1.1-1.src.rpm | cpio -div -D srcrpm # tree . └── srcrpm ├── myrpm-0.1.1.tar.gz └── myrpm.spec
其中 -D 参数为指定解压的目录
-
解压源码
解压后进入到myrpm目录
# tar -vxf myrpm-0.1.1.tar.gz # tree srcrpm/ ├── myrpm-0.1.1 │ ├── myrpm │ │ ├── __init__.py │ │ └── myrpm.py │ ├── myrpm.egg-info │ │ ├── dependency_links.txt │ │ ├── not-zip-safe │ │ ├── PKG-INFO │ │ ├── SOURCES.txt │ │ └── top_level.txt │ ├── PKG-INFO │ ├── setup.cfg │ └── setup.py ├── myrpm-0.1.1.tar.gz └── myrpm.spec
-
生成git patch文件
当前在srcrpm/myrpm-0.1.1/myrpm目录,示例如下
- 选择要修改的文件初始化git仓
- 完成你的修改,且不要add
- git diff生成补丁文件
# git init # git add myrpm.py # git commit -m "init" # vi myrpm.py # git diff myrpm.py > myrpm.patch # tree . ├── __init__.py ├── myrpm.patch └── myrpm.py
-
修改SPEC文件
需要修改或者添加的字段如下:
index 5869db2..cb7fcb8 100644 --- a/myrpm.spec +++ b/myrpm.spec @@ -1,12 +1,13 @@ Name: myrpm Version: 0.1.1 -Release: 1 +Release: 2 Summary: simple python rpm License: Apache-2.0 URL: https://docs.openstack.org/tooz/latest/ Source0: myrpm-0.1.1.tar.gz +Patch01: myrpm.patch BuildArch: noarch BuildRequires: python3-setuptools @@ -15,7 +16,7 @@ BuildRequires: python3-setuptools A simple python rpm %prep -%autosetup -n %{name}-%{version} +%autosetup -n %{name}-%{version} -p1 %build @@ -38,5 +39,8 @@ mv %{buildroot}/filelist.lst . %changelog +* Fri Sep 22 2023 xxx <[email protected]> - 0.1.1-2 +- change print content + * Thu Sep 21 2023 xxx <[email protected]> - 0.1.1-1
-
构建
构建时将patch文件补充到SOURCES目录中,其他与上一章节相同
如果遇到'No file to patch. Skipping patch.'的报错
大概率是patch文件中的目录有问题
如当前示例中,patch文件中的目录为a/myrpm.py和b/myrpm.py
并且构建是会报错,将目录改为a/myrpm/myrpm.py和b/myrpm/myrpm.py即可
4.部分宏的对应值
宏 | 值 |
---|---|
%{_sysconfdir} | /etc |
%{_prefix} | /usr |
%{_exec_prefix} | %{_prefix} |
%{_bindir} | %{_exec_prefix}/bin |
%{_lib} | lib (lib64 on 64bit systems) |
%{_libdir} | %{_exec_prefix}/%{_lib} |
%{_libexecdir} | %{_exec_prefix}/libexec |
%{_sbindir} | %{_exec_prefix}/sbin |
%{_sharedstatedir} | /var/lib |
%{_datadir} | %{_prefix}/share |
%{_includedir} | %{_prefix}/include |
%{_oldincludedir} | /usr/include |
%{_infodir} | /usr/share/info |
%{_mandir} | /usr/share/man |
%{_localstatedir} | /var |
%{_topdir} | %{getenv:HOME}/rpmbuild |
%{_builddir} | %{_topdir}/BUILD |
%{_rpmdir} | %{_topdir}/RPMS |
%{_sourcedir} | %{_topdir}/SOURCES |
%{_specdir} | %{_topdir}/SPECS |
%{_srcrpmdir} | %{_topdir}/SRPMS |
%{_buildrootdir} | %{_topdir}/BUILDROOT |
%{_var} | /var |
%{_tmppath} | %{_var}/tmp |
%{_usr} | /usr |
%{_usrsrc} | %{_usr}/src |
%{_docdir} | %{_datadir}/doc |