Building CentOS RPM packages with Python Setuptools

Python 2/3 and CentOS

If you are using setuptools for python 2/3, you have the ability to make a python package and then have it make a RPM package if you are on CentOS.

First, you need a basic python package.

# basic-project/setup.py
from setuptools import setup

setup(
    name="basic",
    version="0.0.5",
    packages=[
        "basic",
    ]
)
# basic-project/basic/__init__.py
# basic-project/basic/example.py
from __future__ import print_function
def example():
    print("hello world")

Second, you need to install some tools on your CentOS machine

yum install rpm-build

Third, you can execute an RPM build on your CentOS machine

cd basic-project
python setup.py bdist_rpm

You should see a lot of text like

+ /usr/lib/rpm/check-buildroot
+ + /usr/lib/rpm/redhat/brp-compress
+ + /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ + /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ Bytecompiling .py files below /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/BUILDROOT/basic-0.0.5-1.x86_64/usr/lib/python2.7 using /usr/bin/python2.7
+ + /usr/lib/rpm/redhat/brp-python-hardlink
+ + /usr/lib/rpm/redhat/brp-java-repack-jars
+ Processing files: basic-0.0.5-1.noarch
+ Provides: basic = 0.0.5-1
+ Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PartialHardlinkSets) <= 4.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
+ Requires: python(abi) = 2.7
+ Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/BUILDROOT/basic-0.0.5-1.x86_64
+ Wrote: /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/SRPMS/basic-0.0.5-1.src.rpm
+ Wrote: /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/RPMS/noarch/basic-0.0.5-1.noarch.rpm
+ Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.csyKCO
+ + umask 022
+ + cd /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/BUILD
+ + cd basic-0.0.5
+ + rm -rf /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/BUILDROOT/basic-0.0.5-1.x86_64
+ + exit 0
+ Executing(--clean): /bin/sh -e /var/tmp/rpm-tmp.3hZ8rw
+ + umask 022
+ + cd /home/jstephens/basic-project/build/bdist.linux-x86_64/rpm/BUILD
+ + rm -rf basic-0.0.5
+ + exit 0
+ moving build/bdist.linux-x86_64/rpm/SRPMS/basic-0.0.5-1.src.rpm -> dist
+ moving build/bdist.linux-x86_64/rpm/RPMS/noarch/basic-0.0.5-1.noarch.rpm -> dist
$

Now you should have a fully working RPM package located in basic-project/dist/bdist.linux-x86_64/rpm/RPMS/noarch/basic-0.0.5-1.noarch.rpm which you can install with yum install.

It is worth noting that this is not, in the end, a particularly complicated business. RPMs are really just tar balls with metadata. If you examine the files installed, you'll see that it is merely all the files that would have been installed to site-packages anyways.

The downside of this method is that while RPMs are perfectly capable of tracking dependencies and setuptools can capture requirements, this method does not automatically maintain that information in the RPM. You can manually specific dependencies for the RPM on the command line

python setup.py bdist_rpm --requires my_requirement

You can imagine that this is not the most maintainable system...

social