Easy RPMs with setup.py
Building RPMs is a business made easy and flexible with Python's Distutils, and it allows to package any files at all, not just Python scripts and modules.
If writing SPEC files and building RPMs has always been an ordeal, to the point that packaging your software takes longer than writing it (and I kid you not, it's often been the case for me) this approach might be of interest to you. And just because it involves using Python's Distutils doesn't mean it's only meant to package Python code. It works for just about anything.
1 It's a Doddle
Write a setup.py
file looking like:
#!/usr/bin/env python
import distutils.core
name = 'yourtool'
distutils.core.setup(name=name,
version='1.0',
author="Firstname Surname",
author_email="Firstname.Surname@cern.ch",
url="http://cern.ch",
description="Short description of your tool",
long_description="Long description of your tool",
license="ASL",
scripts=[name],
data_files=[
('/usr/share/man/man1', [name + '.1.gz']),
],
)
Run:
python setup.py bdist_rpm
And Bob's your uncle.
2 Specifying Dependencies
Not all the meta-data you need to write an RPM can be specified as setup()
function parameters. This is true of several SPEC file options for which you'll need to use a specific command line option, e.g. for package dependencies. And you'll soon want to use a Makefile for this purpose:
rpm:
python setup.py bdist_rpm --requires foo
3 Build Packages Programmatically
Since setup.py
is nothing but a Python script, it's of course possible to make packaging a rather intelligent process. For instance, nothing keeps you from e.g. changing your package name depending on the distribution:
#!/usr/bin/env python
import platform
dist = platform.linux_distribution(full_distribution_name=0)
distutils.core.setup(name='foo' if dist == 'redhat' else 'bar',
[...]
4 Generating Files to Package?
This may unfortunately not work as expected. For instance, if you've got a Markdown manual page that you'd like to turn into a real groff manual page, calling pandoc
with subprocess
in the setup.py
script will not work, because it seems that setup()
is run not only when you execute setup.py
but also at later stages in other directories where the original Markdown source may not be available. There's nothing for it, you're better off using a Makefile:
rpm: manpage
python setup.py bdist_rpm
manpage:
pandoc -s -tman yourtool.md | gzip > yourtool.1.gz
clean:
python setup.py clean
rm yourtool.1
5 It Doesn't Work on AFS
That's because Distutils wants to create hard links if possible, rather than copying. But hard links aren't supported on AFS. An easy workaround is to trick Distutils into believing that hard links can't be used on your system, simply by removing the corresponding Python function:
#!/usr/bin/env python
import distutils.core
import os
delattr(os, 'link')
name = 'yourtool'
[...]