-1

condensed version of what I want to achieve: Create .rpm and .deb packages from my source.py source code and make sure all dependencies get resolved when installing them on an deb/rpm based linux distribution.

More details: Let's assume I have created a piece of software which is located in a folder structure like this:

---MyProgram          Folder
   ---MyProgram       Folder
       ---img         Folder
          ---logo.ico File
       ---media       Folder
          ---head.txt File
       ---__init__.py File
       ---source.py   File
       ---a.py        File
   ---LICENSE         File
   ---README.md       File
   ---setup.py        File

The file setup.py contains the following:

import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="MyProgram",
    version="0.0.1",
    author="First Last",
    author_email="email@memore.com",
    description="A tool to create nice things",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://google.com",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.7',
    data_files=[
    ('.../MyProgram/img/logo.ico'),
    ('.../MyProgram/media/head.txt'),
],
)

I now run

python setup.py sdist bdist_rpm

from a cmd line under '.../MyProgram'. Two folders 'dist' and 'build' are created as well as 'MyProgram.tar.gz' and two rpm's 'MyProgram-noarch.rpm' and 'MyProgram-src.rpm'. When i try to install 'noarch.rpm' under fedora 31 the process end successfully but no "shortcut" is created, and when i type MyProgram in a cmd line it is not found.

rpm -ql MyFilter

does find it and outputs a bunch of paths:

/usr/lib/python3.7/site-packages/MyProgram/...
/usr/lib/python3.7/site-packages/MyProgram/source.py
/usr/lib/python3.7/site-packages/MyProgram/a.py
....

Which tells me that my installation at least has copied the basic filesystem. But i also see that all the original .py files are still .py files.

My questions:

  • How can i 'make' the rpm so that all dependencies are contained inside the rpm, or at least get resolved by dnf/apt/yum when installing the rpm? In other wording: Is it possible to bundle all dependencies into a rpm/deb like in an .exe for example?
  • How can i specify a path like '/usr/bin' or 'usr/share' as installation target dir?
  • How can i add a launcher app bundled into the rpm/deb?
  • Is the above a good way of doing this at all?

If the solution to this is trivial and i just overlooked it i am really sorry to bother you but atm i just can't see it. Sites that have relevant information and that i already reviewed:

https://docs.python.org/2.0/dist/creating-rpms.html

https://github.com/AppImage/AppImageKit/wiki/Bundling-Python-apps

Python 3.5 create .rpm with pyinstaller generated executable

https://github.com/junaruga/rpm-py-installer

https://www.pyinstaller.org/

https://packaging.python.org/overview/#python-source-distributions

https://packaging.python.org/overview/

https://pyinstaller.readthedocs.io/en/stable/usage.html

https://pyinstaller.readthedocs.io/en/stable/installation.html

https://python-packaging-tutorial.readthedocs.io/en/latest/setup_py.html

J.Doe
  • 127
  • 1
  • 1
  • 9

1 Answers1

0

Just my two cents, rather than a complete answer. Will mostly touch on RPM packaging.

The bdist_rpm option seems easy, but you have little control of the logic of the .spec file it generates/uses and cannot do fancy stuff like scriplets, etc.

That is, unless you take the approach of having it generate the .spec file and quit (instead of building final RPM). From the docs:

If you wish, you can separate these three steps. You can use the --spec-only option to make bdist_rpm just create the .spec file and exit; in this case, the .spec file will be written to the “distribution directory”—normally dist/, but customizable with the --dist-dir option. (Normally, the .spec file winds up deep in the “build tree,” in a temporary directory created by bdist_rpm.)

But as a matter of preference and consistency, I would advise on following distro-specific guidelines for packaging Python apps.

In that way, you will be more in line with the distro's you are building for.

It is not the easiest way though. You will have to shift through some docs. Basically, if you're building for anything CentOS/RHEL, Fedora guidelines for packaging should be observed.

You can find the extra reference here, with the example .spec file for building both Python 2 and 3 versions of the same app.

For this whole 'build like a distro' thing, you would definitely want to look into using mock for the job, to build your package in a chroot.

As for the "shortcut" issue, you have to have your setup.py declare some console scripts for it to create one when you install your package. E.g. from lastversion's setup.py:

entry_points={"console_scripts": ["lastversion = lastversion:main"]},

This entry will result in a "binary" lastversion created/installed (which runs the defined function) when you install your Python package.

Subsequently, in the spec files, the macro %py2_install will make use of setup.py to create the same launcher program.

And you will then be able to ensure that launcher is packaged by placing it in the files section of the spec file:

%files -n python3-myapp
%license COPYING
%doc README.rst
%{python3_sitelib}/%{srcname}/
%{python3_sitelib}/%{srcname}-*.egg-info/
%{_bindir}/myapp
Danila Vershinin
  • 8,725
  • 2
  • 29
  • 35