Table of Contents#
- Prerequisites
- Project Structure Setup
- Creating the Desktop Entry
- Building the Debian Control Files
- Creating the Installation Scripts
- Building the .deb Package
- Testing and Distribution
- Advanced Packaging Techniques
- Conclusion
- References
Prerequisites#
Before we begin, ensure you have the following tools installed:
sudo apt update
sudo apt install build-essential devscripts debhelper dh-python python3-all
sudo apt install python3-gi python3-setuptoolsYou should also have a basic PyGObject application ready for packaging. For this tutorial, we'll use a simple example application called "MyGtkApp".
Project Structure Setup#
A well-organized project structure is crucial for successful packaging. Here's the recommended layout:
mygtkapp/
├── src/
│ └── mygtkapp/
│ ├── __init__.py
│ ├── main.py
│ └── ui/
│ └── main_window.glade
├── data/
│ ├── icons/
│ │ └── mygtkapp.png
│ └── applications/
│ └── mygtkapp.desktop
├── debian/
│ ├── control
│ ├── rules
│ ├── changelog
│ ├── compat
│ └── install
└── setup.py
Example Application Files#
src/mygtkapp/main.py:
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio
import os
import sys
class MyGtkApp:
def __init__(self):
# Create builder and load UI file
self.builder = Gtk.Builder()
# Get the directory where the script is located
if getattr(sys, 'frozen', False):
# Running as bundled executable
base_path = sys._MEIPASS
else:
# Running as script
base_path = os.path.dirname(os.path.abspath(__file__))
ui_file = os.path.join(base_path, 'ui', 'main_window.glade')
self.builder.add_from_file(ui_file)
# Connect signals
self.builder.connect_signals(self)
# Get main window
self.window = self.builder.get_object("main_window")
self.window.show_all()
def on_window_destroy(self, widget, data=None):
Gtk.main_quit()
def on_button_clicked(self, widget):
print("Button clicked!")
if __name__ == "__main__":
app = MyGtkApp()
Gtk.main()src/mygtkapp/ui/main_window.glade:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="main_window">
<property name="can_focus">False</property>
<property name="default_width">400</property>
<property name="default_height">300</property>
<property name="title">My GTK Application</property>
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">10</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">Welcome to My GTK App!</property>
<property name="margin">20</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Click Me!</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_button_clicked" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</interface>Creating the Desktop Entry#
The desktop entry file allows your application to appear in the application menu.
data/applications/mygtkapp.desktop:
[Desktop Entry]
Version=1.0
Type=Application
Name=My GTK Application
Comment=A sample PyGObject application
Exec=mygtkapp
Icon=mygtkapp
Categories=GTK;Development;
Terminal=false
StartupNotify=trueBuilding the Debian Control Files#
The debian/ directory contains all the metadata needed to build your package.
debian/control:
Source: mygtkapp
Section: python
Priority: optional
Maintainer: Your Name <[email protected]>
Build-Depends: debhelper-compat (= 13), dh-python, python3-all, python3-setuptools
Standards-Version: 4.6.0
Homepage: https://example.com/mygtkapp
Package: mygtkapp
Architecture: all
Depends: ${python3:Depends}, ${misc:Depends},
python3-gi,
gir1.2-gtk-3.0,
python3-setuptools
Description: A sample PyGObject application
MyGtkApp is a demonstration application showing how to package
PyGObject applications as .deb files. It provides a simple GUI
interface built with GTK 3.
debian/compat:
13
debian/changelog:
mygtkapp (1.0-1) unstable; urgency=medium
* Initial release of MyGtkApp
-- Your Name <[email protected]> Mon, 01 Jan 2024 12:00:00 +0000
debian/rules:
#!/usr/bin/make -f
%:
dh $@ --with python3 --buildsystem=pybuild
override_dh_auto_build:
# Custom build steps can be added here
override_dh_auto_install:
dh_auto_install
# Install desktop file and icon
install -d debian/mygtkapp/usr/share/applications
install -m 644 data/applications/mygtkapp.desktop debian/mygtkapp/usr/share/applications/
install -d debian/mygtkapp/usr/share/icons/hicolor/48x48/apps
install -m 644 data/icons/mygtkapp.png debian/mygtkapp/usr/share/icons/hicolor/48x48/apps/debian/install:
src/mygtkapp /usr/lib/python3/dist-packages/
data/icons/mygtkapp.png /usr/share/icons/hicolor/48x48/apps/
Creating the Installation Scripts#
setup.py:
from setuptools import setup, find_packages
import os
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup(
name="mygtkapp",
version="1.0",
packages=find_packages(where="src"),
package_dir={"": "src"},
install_requires=[
"PyGObject",
],
entry_points={
'console_scripts': [
'mygtkapp=mygtkapp.main:main',
],
},
data_files=[
('share/applications', ['data/applications/mygtkapp.desktop']),
('share/icons/hicolor/48x48/apps', ['data/icons/mygtkapp.png']),
],
author="Your Name",
author_email="[email protected]",
description="A sample PyGObject application",
long_description=read("README.md"),
license="GPL-3.0",
keywords="gtk pygobject desktop",
url="https://example.com/mygtkapp",
classifiers=[
"Development Status :: 4 - Beta",
"Environment :: X11 Applications :: GTK",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
],
)Building the .deb Package#
Now that all files are in place, let's build the package:
# Navigate to your project directory
cd mygtkapp
# Make the rules file executable
chmod +x debian/rules
# Build the source package
dpkg-buildpackage -uc -us
# Alternatively, build without signing
debuild -i -us -uc -bAfter successful execution, you'll find the .deb file in the parent directory:
../mygtkapp_1.0-1_all.deb
Installing the Package#
To install your newly created package:
sudo dpkg -i mygtkapp_1.0-1_all.debIf there are dependency issues:
sudo apt-get install -fTesting and Distribution#
Testing the Installation#
-
Verify files are installed correctly:
dpkg -L mygtkapp -
Test the application:
mygtkapp -
Check desktop integration:
- Search for "My GTK Application" in your application menu
- Verify the icon appears correctly
Creating a PPA (Personal Package Archive)#
For wider distribution, consider creating a PPA:
# Create source package
debuild -S -sa
# Upload to PPA
dput ppa:your-username/your-ppa mygtkapp_1.0-1_source.changesAdvanced Packaging Techniques#
Handling Dependencies#
For complex applications, you might need additional dependencies:
Enhanced debian/control:
Depends: ${python3:Depends}, ${misc:Depends},
python3-gi,
gir1.2-gtk-3.0,
gir1.2-gstreamer-1.0,
gir1.2-webkit2-4.0,
python3-cairo,
python3-setuptools
Suggests: gir1.2-gtksource-3.0
Creating Systemd Services#
If your application needs to run as a service:
debian/mygtkapp.service:
[Unit]
Description=My GTK Application Service
After=network.target
[Service]
Type=simple
User=mygtkapp
ExecStart=/usr/bin/mygtkapp-service
Restart=on-failure
[Install]
WantedBy=multi-user.targetUsing dh-virtualenv for Virtual Environment Packaging#
For applications with complex Python dependencies:
sudo apt install dh-virtualenvModified debian/rules:
#!/usr/bin/make -f
%:
dh $@ --with python-virtualenvConclusion#
Packaging PyGObject applications as .deb files significantly improves the user experience by providing a standardized installation method. While the initial setup requires careful attention to detail, the result is a professional-grade distribution package that integrates seamlessly with Debian-based systems.
Remember to:
- Test your package on clean systems
- Keep dependencies up to date
- Follow Debian packaging guidelines
- Use version control for your packaging files
With these techniques, you can distribute your PyGObject applications confidently, knowing they'll work reliably for your users.
References#
- Debian Policy Manual
- Debian New Maintainers' Guide
- Python Packaging Authority
- PyGObject Documentation
- GTK Documentation
- Desktop Entry Specification
Useful Tools and Commands#
# Check package contents
dpkg -c package.deb
# Extract package without installing
dpkg -x package.deb extraction_dir/
# Check package metadata
dpkg -I package.deb
# Lintian - Debian package checker
sudo apt install lintian
lintian package.debBy following this comprehensive guide, you'll be well-equipped to package your PyGObject applications professionally and distribute them to users on Debian-based Linux distributions.