Packaging rofimoji
rofimoji
is a character picker for
rofi. It is written in Python and it’s
compatible with PEP 517.
If you want to follow along, run this:
rm -r srcpkgs/rofimoji
- Gathering info
- Python’s packaging systems
- Creating the template
- Dependencies for interpreted packages
- Hunting for dependencies
- Comparing with the upstream template
- The end?
Gathering info
Repository used for gathering the info: https://github.com/fdw/rofimoji
-
latest
version
:6.2.0
-
build style
:python3-pep517
(described below) -
short_desc
:Emoji, unicode and general character picker for rofi and rofi-likes
(taken from GitHub description, something more concise could be used) -
license
:MIT
-
homepage
: https://github.com/fdw/rofimoji -
changelog
: https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md -
distfiles
: https://github.com/fdw/rofimoji/archive/refs/tags/6.2.0.tar.gz
Python’s packaging systems
Python is known for its complicated build systems. Explaining them is beyond the scope of this tutorial (and beyond the scope of my comprehension to be honest).
But thankfully xbps-src
’s build systems do most of the job. It provides the
following build styles: python2-module
, python3-module
and python3-pep517
The -module
styles use setup.py
which is kinda deprecated (I recommend you
read this
article
for more info) and the python3-pep517
(as the name implies) uses PEP
517.
rofimoji
uses python3-pep517
.
Creating the template
xnew rofimoji
# Template file for 'rofimoji'
pkgname=rofimoji
version=
revision=1
#archs="i686 x86_64"
#build_wrksrc=
build_style=gnu-configure
#configure_args=""
#make_build_args=""
#make_install_args=""
#conf_files=""
#make_dirs="/var/log/dir 0755 root root"
hostmakedepends=""
makedepends=""
depends=""
short_desc=""
maintainer="meator <meator.dev@gmail.com>"
license="GPL-3.0-or-later"
homepage=""
#changelog=""
distfiles=""
checksum=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb
Let’s fill it out:
# Template file for 'rofimoji'
pkgname=rofimoji
version=6.2.0
revision=1
build_style=python3-pep517
hostmakedepends=""
makedepends=""
depends=""
short_desc="Emoji, unicode and general character picker for rofi and rofi-likes"
maintainer="meator <meator.dev@gmail.com>"
license="MIT"
homepage="https://github.com/fdw/rofimoji"
changelog="https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md"
distfiles="https://github.com/fdw/rofimoji/archive/refs/tags/${version}.tar.gz"
checksum=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb
xgensum -i rofimoji
# Template file for 'rofimoji'
pkgname=rofimoji
version=6.2.0
revision=1
build_style=python3-pep517
hostmakedepends=""
makedepends=""
depends=""
short_desc="Emoji, unicode and general character picker for rofi and rofi-likes"
maintainer="meator <meator.dev@gmail.com>"
license="MIT"
homepage="https://github.com/fdw/rofimoji"
changelog="https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md"
distfiles="https://github.com/fdw/rofimoji/archive/refs/tags/${version}.tar.gz"
checksum=21da8e6879ac16d774f3ce6dfcd1783cec891ad172617eead2c10597f477d9a9
Let’s do some housekeeping for good measure:
./xbps-src clean
git pull --rebase upstream master
Now, we can build:
> ./xbps-src pkg rofimoji
=> xbps-src: updating repositories for host (x86_64)...
[*] Updating repository `https://repo-default.voidlinux.org/current/bootstrap/x86_64-repodata' ...
[*] Updating repository `https://repo-default.voidlinux.org/current/x86_64-repodata' ...
[*] Updating repository `https://repo-default.voidlinux.org/current/nonfree/x86_64-repodata' ...
[*] Updating repository `https://repo-default.voidlinux.org/current/debug/x86_64-repodata' ...
[*] Updating repository `https://repo-default.voidlinux.org/current/multilib/bootstrap/x86_64-repodata' ...
[*] Updating repository `https://repo-default.voidlinux.org/current/multilib/x86_64-repodata' ...
[*] Updating repository `https://repo-default.voidlinux.org/current/multilib/nonfree/x86_64-repodata' ...
=> xbps-src: updating software in / masterdir...
=> xbps-src: cleaning up / masterdir...
=> rofimoji-6.2.0_1: removing autodeps, please wait...
=> rofimoji-6.2.0_1: building with [python3-pep517] [python3] for x86_64...
[host] python3-build-1.2.2_1: found (https://repo-default.voidlinux.org/current)
[host] python3-installer-0.7.0_2: found (https://repo-default.voidlinux.org/current)
=> rofimoji-6.2.0_1: installing host dependencies: python3-build-1.2.2_1 python3-installer-0.7.0_2 ...
=> rofimoji-6.2.0_1: running do-fetch hook: 00-distfiles ...
=> rofimoji-6.2.0_1: running do-extract hook: 00-distfiles ...
=> rofimoji-6.2.0_1: extracting distfile(s), please wait...
=> rofimoji-6.2.0_1: running do-patch hook: 00-patches ...
=> rofimoji-6.2.0_1: running pre-configure hook: 00-gnu-configure-asneeded ...
=> rofimoji-6.2.0_1: running pre-configure hook: 01-override-config ...
=> rofimoji-6.2.0_1: running pre-configure hook: 02-script-wrapper ...
=> rofimoji-6.2.0_1: running pre-build hook: 02-script-wrapper ...
=> rofimoji-6.2.0_1: running do_build ...
* Getting build dependencies for wheel...
Traceback (most recent call last):
File "/usr/lib/python3.12/site-packages/pyproject_hooks/_impl.py", line 402, in _call_hook
raise BackendUnavailable(
pyproject_hooks._impl.BackendUnavailable: Cannot import 'poetry.core.masonry.api'
ERROR Backend 'poetry.core.masonry.api' is not available.
=> ERROR: rofimoji-6.2.0_1: do_build: 'python3 -m build --no-isolation --wheel ${make_build_args} ${make_build_target}' exited with 1
=> ERROR: in do_build() at common/build-style/python3-pep517.sh:17
ERROR Backend 'poetry.core.masonry.api' is not available.
poetry
is missing.
xbps-query
shows us this:
> xbps-query -Rs poetry
[-] python3-poetry-core-1.5.0_2 Poetry PEP 517 Build Backend & Core Utilities
This is our dependency. But I should talk about dependencies more.
Dependencies for interpreted packages
As I’ve mentioned in the cross-compilation section of packaging j4-dmenu-desktop, cross-compilation isn’t really a thing for interpreted languages like Python.
This is true for pure Python. Some Python code can have C or C++ extensions (usually handled by Cython). If that is the case, the rules of cross-compilation described earlier still hold.
Because of this, a lot of things that require close attention for compiled packages can be ignored for interpreted ones.
For example, you usually don’t have to distinguish hostmakedepends
and
makedepends
. All dependencies which should be present in the masterdir should
be defined in hostmakedepends
. makedepends
isn’t usually used.
One exception to this rule is Python compiled extensions. These usually have
makedepends="python3-devel"
One disadvantage of interpreted packages is that Shlib
detection doesn’t exist for them. This means
that you have to manually add all dependencies to depends
.
Hunting for dependencies
As you may know, the main package manager for Python is pip
. It uses the
PyPI repository.
Because Python projects already integrate with a package manager, they have to be aware of their dependencies. This can greatly simplify dependency hunting.
To quote the Manual
Python packages that rely on
python3-setuptools
should generally mapsetup_requires
dependencies insetup.py
tohostmakedepends
in the template andinstall_requires
dependencies todepends
in the template; includepython3
independs
if there are no other python dependencies.
This advice applies to PEP 517 too, you’ll just have to look for the dependencies in different places.
Let’s look at rofimoji
’s
pyproject.toml
:
[tool.poetry]
name = "rofimoji"
version = "6.2.0"
...
[tool.poetry.dependencies]
python = "^3.8"
ConfigArgParse = "^1.3"
...
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
...
Here we see that rofimoji
depends on Python (this isn’t much of a surprise)
and it depends on ConfigArgParse
.
It also depends on its build system, poetry-core
.
Upstream’s build system will help you figure out the dependencies, but it won’t find them for you. The dependencies will likely have a different name in PyPI than on Void. They also might not be packaged or they might be packaged differently compared to the PyPI version (but this is unlikely).
xbps-query -Rs
is usually enough to figure out dependencies:
> xbps-query -Rs poetry-core
[-] python3-poetry-core-1.5.0_2 Poetry PEP 517 Build Backend & Core Utilities
> xbps-query -Rs ConfigArgParse
[-] python3-ConfigArgParse-1.7_1 Drop-in replacement for argparse
Let’s fix the template:
# Template file for 'rofimoji'
pkgname=rofimoji
version=6.2.0
revision=1
build_style=python3-pep517
hostmakedepends="python3 python3-poetry-core"
depends="python3-ConfigArgParse"
short_desc="Emoji, unicode and general character picker for rofi and rofi-likes"
maintainer="meator <meator.dev@gmail.com>"
license="MIT"
homepage="https://github.com/fdw/rofimoji"
changelog="https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md"
distfiles="https://github.com/fdw/rofimoji/archive/refs/tags/${version}.tar.gz"
checksum=21da8e6879ac16d774f3ce6dfcd1783cec891ad172617eead2c10597f477d9a9
And that’s it. The template builds without issues now.
Let’s run xlint
:
> xlint rofimoji
rofimoji:10: license 'MIT', but no use of vlicense
That’s a simple fix:
# Template file for 'rofimoji'
pkgname=rofimoji
version=6.2.0
revision=1
build_style=python3-pep517
hostmakedepends="python3 python3-poetry-core"
depends="python3-ConfigArgParse"
short_desc="Emoji, unicode and general character picker for rofi and rofi-likes"
maintainer="meator <meator.dev@gmail.com>"
license="MIT"
homepage="https://github.com/fdw/rofimoji"
changelog="https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md"
distfiles="https://github.com/fdw/rofimoji/archive/refs/tags/${version}.tar.gz"
checksum=21da8e6879ac16d774f3ce6dfcd1783cec891ad172617eead2c10597f477d9a9
post_install() {
vlicense LICENSE
}
Comparing with the upstream template
This is our template:
# Template file for 'rofimoji'
pkgname=rofimoji
version=6.2.0
revision=1
build_style=python3-pep517
hostmakedepends="python3 python3-poetry-core"
depends="python3-ConfigArgParse"
short_desc="Emoji, unicode and general character picker for rofi and rofi-likes"
maintainer="meator <meator.dev@gmail.com>"
license="MIT"
homepage="https://github.com/fdw/rofimoji"
changelog="https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md"
distfiles="https://github.com/fdw/rofimoji/archive/refs/tags/${version}.tar.gz"
checksum=21da8e6879ac16d774f3ce6dfcd1783cec891ad172617eead2c10597f477d9a9
post_install() {
vlicense LICENSE
}
This is the official template:
# Template file for 'rofimoji'
pkgname=rofimoji
version=6.2.0
revision=1
build_style=python3-pep517
hostmakedepends="python3-poetry-core"
depends="python3-ConfigArgParse"
short_desc="Simple character picker using rofi"
maintainer="Marcin Puc <tranzystorek.io@protonmail.com>"
license="MIT"
homepage="https://github.com/fdw/rofimoji"
changelog="https://raw.githubusercontent.com/fdw/rofimoji/main/CHANGELOG.md"
distfiles="https://github.com/fdw/rofimoji/archive/refs/tags/${version}.tar.gz"
checksum=21da8e6879ac16d774f3ce6dfcd1783cec891ad172617eead2c10597f477d9a9
post_install() {
vlicense LICENSE
vman src/picker/docs/rofimoji.1
}
These two templates are almost identical, which is a good sign.
The official template’s short_desc
is more concise than ours. It also installs
the manpage, which is useful.
The end?
Well, you’ve made it. This is the end of the practical part of this tutorial.
You should now be able to package your own programs, libraries or other things
using xbps-src
. You now know the many helpful features of xbps-src
that
should simplify packaging.
This tutorial doesn’t cover the entirety of xbps-src
and it doesn’t try to do
so. Look in the
Manual for
that. Now that you know the basics, you should be able to comprehend it well.
Knowing the basics is also good when asking for
help. I have often seen people in
#voidlinux
trying to solve some problem with their template while not knowing
the basics of xbps-src
. This can complicate troubleshooting for both parties.
You should now have working package(s). You might want to contribute them. If yes, continue reading: