Commit bfb1862d authored by David Boddie's avatar David Boddie

Add most of the first tutorial

Update the development information with a PyGObject reference.
parent ac218a6f
.. _First_Application_building:
Building the Application
========================
.. contents::
:local:
The ``app`` directory and its subdirectories contain ``meson.build`` files that
describe how the application is built. These are used by the `Meson`_ build
tool to configure the build process.
Meson is usually run so that it creates a build directory. This is where all
the resources are put so that the `Ninja`_ build tool can perform the actual
process of building and installing the application.
Top-Level Build File
--------------------
In the ``app`` directory itself, the ``meson.build`` file begins with a
declaration of the project name, version and build system requirements:
.. literalinclude:: app/meson.build
We also declare the ``data`` and ``src`` subdirectories, causing Meson to
examine them for any ``meson.build`` files they may contain.
The last line causes a special script to be run after installation. We will
cover this later.
Sources Build File
------------------
The ``meson.build`` file in the ``src`` directory describes how the source
files are processed when the build occurs:
.. literalinclude:: app/src/meson.build
In this case, we instruct Meson to take the ``main.py`` file in the ``src``
directory and copy it into the build directory as ``your-first-application`` --
this is the name given as the executable in the :ref:`desktop entry file
<First_Application_desktop_file>`.
We also declare that the file should be installed, and that its installation
directory is the system location for executables (``bindir``).
Data Build File
---------------
The ``meson.build`` file in the ``data`` describes how the data files are
processed when the build occurs:
.. literalinclude:: app/data/meson.build
Here, we tell Meson to simply copy the ``com.example.first_application.desktop``
file into the build directory. We also declare that it should be installed, and
that its installation directory is the ``applications`` subdirectory of the
system location for data files (``datadir``).
The ``com.example.first_application.svg`` file is more easily described to
Meson. It will be installed in the appropriate subdirectory of the system
location for data files that is used for icons.
Building using Meson and Ninja
------------------------------
When building the application for deployment on the phone, we will use Flatpak
to coordinate the build process. However, behind the scenes, we are using Meson
and Ninja to perform the actual configuration and build. If you want to try and
build the application for testing on your workstation, you can follow the steps
below to build, install, and finally uninstall it.
To configure the build on the command line, enter the ``app`` directory and
run Meson, specifying the source and build directories::
meson . _build
Build the application using Ninja, passing the build directory as an argument
so that the build occurs within that directory. There is no need to specify a
build rule because the default rule builds the application::
ninja -C _build
Finally, use ``sudo`` to install the application in a standard location on your
system using the ``install`` build rule::
sudo ninja -C _build install
To uninstall the application, run its ``uninstall`` rule::
sudo ninja -C _build uninstall
All of the files that were installed should now have been cleanly removed from
system locations.
Summary
-------
We have examined the contents of some ``meson.build`` files to see how simple
rules are used to describe the configuration process. We have also seen how
Meson and Ninja are used to configure and build the application.
The application can also be packaged for more convenient installation using the
Flatpak framework. This is the subject of the next part of the tutorial.
.. include:: /links.rst
.. _First_Application_data:
Data Files
==========
.. contents::
:local:
Inside the ``data`` directory are three files: ``com.example.first_application.desktop``,
``com.example.first_application.svg`` and ``meson.build``.
The ``com.example.first_application.desktop`` file is a `Desktop Entry`_ file.
The ``com.example.first_application.svg`` file is a `Scalable Vector Graphics`_
(SVG) file that contains the application icon.
The ``meson.build`` file describes the build rules for the program -- we will
look at these later in :ref:`First_Application_building`.
.. _First_Application_desktop_file:
The Desktop Entry File
----------------------
The ``com.example.first_application.desktop`` contains metadata about the
application that browsers and application launchers can use to show information
about the application, including its name, icon and the name of its executable
file. The contents of the file itself follows a simple format with many entries
being self-documenting:
.. literalinclude:: app/data/com.example.first_application.desktop
Less obvious entries are ``Exec`` and ``Terminal``. The ``Exec`` entry holds the
file name of the executable used to run the application. This will be defined
in the build script we use. The ``Terminal`` entry determines whether the
application should be run in a terminal program. We can ignore the other
entries for now.
The Icon File
-------------
The ``com.example.first_application.svg`` file is simply an SVG file:
.. image:: app/data/com.example.first_application.svg
We use an SVG file for convenience -- it can be rescaled as needed by the user
interface that shows it because the icon is stored in a vector file format. As
a result, we do not need to provide bitmaps of different sizes.
Summary
-------
In this part of the tutorial we looked at two files that provide information
about the application (a desktop entry file) and a visual representation for it
(an SVG icon file).
Next, we will see how the main program and the data files are put together when
the application is built.
.. include:: /links.rst
Getting the Application
=======================
The application can be found in the `Librem 5 developer documentation
repository`_. You can clone this repository locally with Git::
git clone https://source.puri.sm/Librem5/developer.puri.sm.git
This should result in the creation of a directory called ``developer.puri.sm``
in your current directory. Enter this directory and find the application
directory for this tutorial::
cd developer.puri.sm/Apps/Tutorials/First_Application/app
You can build the application from the command line or open it in :ref:`gbuilder`.
.. include:: /links.rst
Overview of Files and Directories
=================================
The main ``app`` directory contains the following files and directories. Those
marked with a trailing slash are directories.
====================================== =========================================
Name Description
====================================== =========================================
**build-aux/** Helper scripts for the build system.
**com.example.first_application.json** Manifest file for deployment.
**data/** Data files for the installed application.
**meson.build** The main build file.
**src/** Source files for the application.
====================================== =========================================
The first four of these are concerned with building and packaging the
application, or contain data files that are not part of the application itself.
The ``src`` directory is where we will start to explore how the application is
put together.
.. _First_Application_src:
Source Files
============
.. contents::
:local:
Inside the ``src`` directory are two files: ``main.py`` and ``meson.build``.
The ``meson.build`` file describes the build rules for the program -- we will
look at these later in :ref:`First_Application_building`.
The ``main.py`` file contains the Python source code for the application.
The Program
-----------
Because the application is very simple, we show the whole main program here to
provide an overview before looking at the details:
.. literalinclude:: app/src/main.py
After the opening comments, there are three parts to the program: the module
imports, the application class, and the module level code at the end. We will
examine these parts of this program individually.
Importing Modules
~~~~~~~~~~~~~~~~~
The program begins by importing the modules it needs to create a user
interface. These are the ``sys`` module, which is needed to access the
command line arguments passed to the program when it is run, and the ``gi``
module, which provides a Python interface to the GNOME libraries:
.. literalinclude:: app/src/main.py
:start-at: import
:end-at: repository
When importing the ``Gtk`` module, it is important to specify the version of
the API that will be used. Version 3.0 is the default in many environments, but
it is good practice to be explicit about the version in use.
Application Class
~~~~~~~~~~~~~~~~~
The application is represented by the ``Application`` class which is derived
from the standard ``Gtk.Application`` class. This class provides methods to set
up the application and perform tasks when it is run. It is defined in the
normal way, beginning with the ``__init__`` method:
.. literalinclude:: app/src/main.py
:start-at: class Application
:end-at: GLib.set_application_name
This method performs two tasks that are necessary for the application to run
correctly:
1. It uses the ``super`` built-function to call the ``__init__`` method of the
base class. This associates the application with the application ID given.
This ID must have a certain format which is described in the
`Gio.GApplication documentation`_.
2. It calls the ``GLib.set_application_name`` function to set a user-readable
application name that will be localized if translations are available.
It is not necessary to know what these things do. We just need to ensure that
they are done in this method.
When the application is run, the ``do_active`` method of the ``Application``
class is called. This is something that we need to implement if we want the
application to do something. In this case, we create a window and give it an
icon. Then we add a label to the window and show it:
.. literalinclude:: app/src/main.py
:start-at: do_activate
:end-at: show_all
Going into detail, we create an instance of the ``Gtk.ApplicationWindow``
class, passing the application instance to it so that the application runs
until the window is closed -- see the `application property`_ documentation for
more information.
Text is displayed in the window using an instance of the ``Gtk.Label`` class
which we configure by calling ``set_markup`` to set its ``markup`` property.
This allows us to use simple HTML-like markup to show text with a specific size.
Because the window is a container, the label is added to it using the ``add``
method, and the window is shown using the ``show_all`` method so that both the
window and its contents are displayed.
Creating and Running an Application Instance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The last part of the program contains a standard Python idiom for checking that
the module is being run as a script:
.. literalinclude:: app/src/main.py
:start-at: __main__
:end-at: exit
Here, we create the ``Application`` instance and call its ``run`` method with
any arguments that were passed to the application from its environment. When it
has finished running, its exit code is returned via the normal ``sys.exit``
call.
Summary
-------
This part of the tutorial showed the simple Python program that forms the core
of the application. It can be run as a standalone application.
However, if we want to install it, we need to build it in a particular way, and
we need to provide files that will allow the user to launch it from a GUI. The
next part of this tutorial describes how we provide the data files to do that.
.. include:: /links.rst
.. _`application property`: https://developer.gnome.org/gtk3/stable/GtkWindow.html#GtkWindow--application
.. _`Application section`: https://python-gtk-3-tutorial.readthedocs.io/en/latest/application.html
#!/usr/bin/env python3
from os import environ, path
from subprocess import call
prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local')
datadir = path.join(prefix, 'share')
destdir = environ.get('DESTDIR', '')
# Package managers set this so we don't need to run
if not destdir:
print('Updating icon cache...')
call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')])
{
"app-id": "com.example.first_application",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "your-first-application",
"finish-args": [
"--socket=wayland"
],
"build-options": {
"env": {
"V": "1"
}
},
"cleanup": [
"/lib/pkgconfig",
"/man",
"/share/doc",
"/share/gtk-doc",
"/share/man",
"/share/pkgconfig"
],
"modules": [
{
"name": "first-application",
"buildsystem": "meson",
"builddir": true,
"subdir": "First_Application",
"sources": [
{
"branch": "master",
"type": "git",
"url": "https://source.puri.sm/david.boddie/tutorials.git"
}
]
}
]
}
[Desktop Entry]
Name=Your First Application
Icon=com.example.first_application
Exec=your-first-application
Terminal=false
Type=Application
Categories=
StartupNotify=false
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" height="64" version="1.1" width="64"
viewBox="0 0 100 100">
<rect x="0" y="0" width="100" height="100" stroke="none" fill="#8080c0" />
<rect x="0" y="60" width="100" height="40" stroke="none" fill="#80c080" />
<circle cx="70" cy="30" r="20" stroke="none" fill="#f0f080" />
</svg>
configure_file(
input: 'com.example.first_application.desktop',
output: 'com.example.first_application.desktop',
copy: true,
install: true,
install_dir: join_paths(get_option('datadir'), 'applications')
)
install_data('com.example.first_application.svg',
install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'scalable', 'apps'))
project('first-application',
version: '0.1.0',
meson_version: '>= 0.40.0',
)
subdir('data')
subdir('src')
meson.add_install_script('build-aux/meson/postinstall.py')
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2018 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
class Application(Gtk.Application):
def __init__(self):
super().__init__(application_id='com.example.first_application')
GLib.set_application_name('Your First Application')
def do_activate(self):
window = Gtk.ApplicationWindow(application=self)
window.set_icon_name('com.example.first_application')
label = Gtk.Label()
label.set_markup('<span font="40">Hello World!</span>')
window.add(label)
window.show_all()
if __name__ == "__main__":
app = Application()
result = app.run(sys.argv)
sys.exit(result)
configure_file(
input: 'main.py',
output: 'your-first-application',
copy: true,
install: true,
install_dir: get_option('bindir')
)
.. _First_Application:
Your First Application
======================
In this tutorial we will create a simple Python 3 application that can be run
on the Librem 5. It is assumed that you have installed the tools mentioned in
the :ref:`workstation` and :ref:`workstation_gnome` sections of this manual
before trying to build and install it.
Summary
-------
When run, the application described in this tutorial simply shows a window
containing a message. A number of files are provided with the application that
provide basic metadata and resources so that the application can be launched by
the phone environment.
.. image:: images/screenshot.png
:scale: 50%
:align: center
:alt: A screenshot of the application running in the phone environment
We will cover the different components that are needed for a basic application
like this one, including the files used to build it and the manifest needed to
deploy it.
.. toctree::
:maxdepth: 1
Getting_the_App
Overview
Source_Files
Data_Files
Building_the_App
.. include:: /links.rst
.. _app_development_tutorials:
Tutorials
=========
This section contains a collection of tutorials that aim to introduce you to
aspects of application development for the Librem 5.
We have chosen to implement many of the tutorial applications using the
`Python 3`_ programming language because it is accessible to a wide range of
developers, and users of other languages should be able to read and understand
the source code. We encourage others to port the tutorials to other programming
languages -- see :ref:`contributing` if you are interested in doing this.
Before you begin, review the :ref:`workstation` and :ref:`workstation_gnome`
sections of this manual to ensure that you have installed the required
development tools and libraries.
.. toctree::
:maxdepth: 1
First_Application/index
.. include:: /links.rst
......@@ -24,6 +24,7 @@ features of the phone and its software environment.
.. toctree::
:maxdepth: 1
Tutorials/index
Guides/index
Packaging_Apps/index
PublishingApps
......
......@@ -26,6 +26,14 @@ and build applications. The versions of these available in modern GNU/Linux
distributions should be sufficient. Debian-based distributions, such as PureOS,
provide packages called ``meson`` and ``ninja-build``.
PyGObject
---------
Developers using the `Python 3`_ programming language should install the
PyGObject bindings for GObject-based libraries. Debian-based distributions
provide these in a package called ``python3-gi``. Installation on other
platforms is described in the `PyGObject documentation`_.
gitg
----
......
.. _`Building your first Flatpak`: http://docs.flatpak.org/en/latest/first-build.html
.. _`Debian`: https://www.debian.org
.. _`Debian package submission procedures`: https://www.debian.org/doc/manuals/distribute-deb/distribute-deb.html#adding-packages-to-debian
.. _`Desktop Entry`: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
.. _`developer.puri.sm issues`: https://source.puri.sm/Librem5/developer.puri.sm/issues
.. _`EmCraft i.MX 8M SoM`: https://www.emcraft.com/products/868
.. _`Flatpak`: https://flatpak.org/
.. _`Flatpak Builder documentation`: http://docs.flatpak.org/en/latest/flatpak-builder.html
.. _`Flatpak Building Introduction`: http://docs.flatpak.org/en/latest/building-introduction.html
.. _`Flatpak documentation`: http://docs.flatpak.org/en/latest/
.. _`Gio.GApplication documentation`: https://developer.gnome.org/gio/stable/GApplication.html#g-application-id-is-valid
.. _`git-buildpackage`: http://honk.sigxcpu.org/projects/git-buildpackage/manual-html/gbp.html
.. _`Glade`: https://glade.gnome.org/
.. _`Glade Tutorials`: https://wiki.gnome.org/action/show/Apps/Glade/Tutorials
......@@ -39,6 +41,7 @@
.. _`libhandy library`: https://source.puri.sm/Librem5/libhandy
.. _libhandy documentation : http://honk.sigxcpu.org/projects/libhandy/doc/
.. _libhandy website : https://source.puri.sm/Librem5/libhandy
.. _`Librem 5 developer documentation repository`: https://source.puri.sm/Librem5/developer.puri.sm
.. _`linux-emcraft issue 2`: https://source.puri.sm/Librem5/linux-emcraft/issues/2
.. _`Meson`: https://mesonbuild.com/
.. _`Nightly GNOME Apps`: https://wiki.gnome.org/Apps/Nightly
......@@ -46,6 +49,9 @@
.. _`Plasma Mobile`: https://www.plasma-mobile.org
.. _`Plasma Mobile application development`: https://community.kde.org/Plasma/Mobile/DevGuide#Plasma_Mobile_application_development
.. _`PureOS`: https://pureos.net
.. _`PyGObject documentation`: https://pygobject.readthedocs.io
.. _`Python 3`: https://www.python.org/
.. _`Python GTK+ 3 Tutorial`: https://python-gtk-3-tutorial.readthedocs.io
.. _`python-evdev`: https://python-evdev.readthedocs.io/en/latest/usage.html
.. _`python-evdev tutorial`: https://python-evdev.readthedocs.io/en/latest/tutorial.html
.. _`python-periphery`: https://python-periphery.readthedocs.io/en/latest/
......@@ -56,6 +62,7 @@
.. _`Qt Quick`: https://doc.qt.io/qt-5/qtquick-index.html
.. _`Qt Quick Controls 2`: https://doc.qt.io/qt-5/qtquickcontrols2-index.html
.. _`Running GTK+ Applications`: https://developer.gnome.org/gtk3/stable/gtk-running.html
.. _`Scalable Vector Graphics`: https://www.w3.org/TR/SVG/
.. _`FH34SRJ-6S-0.5SH(50) (Touch)`: https://www.hirose.com/product/download/?distributor=digikey&type=2d&lang=en&num=FH34SRJ-6S-0.5SH(50)
.. _`74LVC2G241DC,125`: https://assets.nexperia.com/documents/data-sheet/74LVC2G241.pdf
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment