Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何构建一个RPM包 #11

Open
tzing0013 opened this issue Sep 22, 2023 · 0 comments
Open

如何构建一个RPM包 #11

tzing0013 opened this issue Sep 22, 2023 · 0 comments
Labels
openEuler Improvements or additions to documentation publish New feature or request RPM Linux package manager

Comments

@tzing0013
Copy link

tzing0013 commented Sep 22, 2023

构建一个RPM包

1. rpmdevtools工具及SPEC文件

一些基础点 可以直接从下一章节
网上找了好多相关的教程,RedHat的教程应该是最官方的。
目前没找到如何生成压缩包的,本文使用setuptools生成
还有说使用pyinstaller生成可执行文件然后获取其依赖并压缩的,没有测试这个

  1. 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阶段安装的文件
  2. 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包

  1. 编写py文件

    还是最通用的hello world

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    def my_print():
        print('hello world')
    
    if __name__ == '__main__':
        my_print()
  2. 编写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',
    )
    
  3. 目录结构

    python-myrpm/
    ├── myrpm
    │   ├── __init__.py
    │   └── myrpm.py
    └── setup.py
  4. 生成压缩包

    在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
  5. 制作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文件中更高级的修改需要进一步探索

  6. 构建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
  7. 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的打印内容

  1. 解压rpm包获取源码压缩包

    # rpm2cpio myrpm-0.1.1-1.src.rpm | cpio -div -D srcrpm
    # tree
    .
    └── srcrpm
        ├── myrpm-0.1.1.tar.gz
        └── myrpm.spec

    其中 -D 参数为指定解压的目录

  2. 解压源码

    解压后进入到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
  3. 生成git patch文件

    当前在srcrpm/myrpm-0.1.1/myrpm目录,示例如下

    1. 选择要修改的文件初始化git仓
    2. 完成你的修改,且不要add
    3. 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
  4. 修改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
  5. 构建

    构建时将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
@wangxiyuan wangxiyuan added the openEuler Improvements or additions to documentation label Sep 26, 2023
@MengqingCao MengqingCao added RPM Linux package manager publish New feature or request labels Sep 27, 2023
@Yikun Yikun added publish New feature or request and removed publish New feature or request labels Oct 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
openEuler Improvements or additions to documentation publish New feature or request RPM Linux package manager
Projects
None yet
Development

No branches or pull requests

4 participants