Development/CMake/Python

From KDE TechBase

How to integrate a Python project into the KDE4 cmake system

This is work in progress - right now there seem to be very different views about how runtime dependencies for projects should be handled. This is much more of a problem for Python projects because almost all of their dependencies are runtime only.

Here are some links to discussions:

http://lists.kde.org/?l=kde-buildsystem&m=128267903722403&w=4 http://lists.kde.org/?l=kde-core-devel&m=126890156111852&w http://lists.kde.org/?l=kde-buildsystem&m=128550824619920&w=4

Build time dependencies

There is not much that needs to be compiled for a Python project:

  • The byte-compiled *.pyc files if you choose to do that when building the package. A better way would be to do that at install time - that ensures the correct Python version is used. This is what Debian-based distros do. If you compile them at buid time, they should be generated for all project modules. However the main .py file (or files) like kajongg.py which are executed first should not be bytecompiled. The Python interpreter would not use that anyway, it always recompiles the main .py file when loading it. For shorter startups, make it as small as possible. See the example below. Since cmake bytecompiles all python source files at build time, this main file (like kajongg.py) should not be added to the list of source files. Instead simply install those main .py files directly in the right place.
  • Maybe some *.ui files to be processed by pyuic4. If you only have few small *.ui files you may prefer to simply distribute the *.ui files and have them processed at runtime (I did not measure how much time that actually takes). This of course simplifies cmake configuration.
    from PyQt4 import uic
    uic.loadUi('mywidget.ui')
    

So you need a Python interpreter installed for the generation of byte-compiled *.pyc files. Make sure it is a version that can also execute your program. If the version installed at the client side is too different, your precompiled bytecode is incompatible and cannot be used, so the client system will recompile your sources. And if it cannot write them because of missing access rights, it will do that at every program start (there are ways how to tell python where to write its local *.pyc files but that is out of scope for here).

And optionally you need pyuic4 installed. This macro calls pyuic4 and installs the resulting *ui.py files:

PYKDE4_ADD_UI_FILES(src/*.ui)

However I believe I had some problems with that macro, that may have been one reason why I now do that at runtime for Kajongg. This would need to be checked.

Runtime dependencies

In C/C++ most runtime dependencies are also build time dependencies - the KDE4 cmake macros do not even let you differentiate them (yet). However Python source code can be bytecompiled without the imported modules being installed - so the set of build time dependencies is very small and about the same for all Python projects.

Most distribution packagers do NOT want cmake to error out on missing runtime dependencies, they do not even want warnings about them because they just might not want to install them. They want to have their build system as simple (and as fast) as possible with a minimal set of dependencies. However this is not true for all packagers, some do want warnings. Developers probably want warnings too but it should be a small burden for them to install what the program claims as missing.

Until an easy way is found to satisfy both use cases, it is probably best to only implement the least common denominator: Do not error out or produce warnings.

Of course packagers still need to know the runtime dependencies. For now there is no nice way of specifying this with existing cmake macros. Currently the best solution for you is to write runtime dependency information into a file README.packagers in the home of your project.

Executables

In theory, the main.py (like kajongg.py in the example below) could directly be installed in whatever */bin directory but it is nicer to only put a symbolic link there like /usr/bin/kajongg -> /usr/share/kde4/apps/kajongg/kajongg.py. Of course cmake comes with a macro for this:

PYKDE4_ADD_EXECUTABLE(kajongg.py kajongg)

Example projects

  • Kajongg, a board game. This project is not yet conforming to the above text - I will convert it as soon as nobody objects to this.