An opinionated build tool for Anki add-ons. Used in most of my major Anki projects.
This is still very much a work-in-progress. Neither the API, nor the implementation are set in stone. At this point the project's main purpose lies in replacing the variety of different build scripts I am employing across all of my add-ons, making the build chain more standardized and maintainable.
aab
has only been tested on Linux so far, but it might also work on other POSIX-compliant environments like macOS.
pip install aab
pip install --upgrade git+https://github.com/glutanimate/anki-addon-builder.git#egg=aab
aab
optionally supports building UI forms created with Qt designer. To make sure you have all the pre-requisites installed you can add [qt5,qt6]
to the command above, i.e.:
pip install --upgrade git+https://github.com/glutanimate/anki-addon-builder.git#egg=aab[qt5,qt6]
This will enable aab to build Qt forms that are compatible with both Qt5 and Qt6 builds of Anki. If you are only targeting Qt5 or Qt6, you can adjust the command above to only install that particular Qt version.
You can get an overview of all supported actions by accessing the built-in help (options below reflect latest main branch state and might not be available in pypi builds, yet):
$ aab -h
usage: aab [-h] [-v] {build,ui,manifest,clean,create_dist,build_dist,package_dist} ...
positional arguments:
{build,ui,manifest,clean,create_dist,build_dist,package_dist}
build Build and package add-on for distribution
ui Compile add-on user interface files
manifest Generate manifest file from add-on properties in addon.json
clean Clean leftover build files
create_dist Prepare source tree distribution for building under build/dist. This is
intended to be used in build scripts and should be run before `build_dist`
and `package_dist`.
build_dist Build add-on files from prepared source tree under build/dist. This step
performs all source code post-processing handled by aab itself (e.g.
building the Qt UI and writing the add-on manifest). As with `create_dist`
and `package_dist`, this command is meant to be used in build scripts
where it can provide an avenue for performing additional processing ahead
of packaging the add-on.
package_dist Package pre-built distribution of add-on files under build/dist into a
distributable .ankiaddon package. This is inteded to be used in build
scripts and called after both `create_dist` and `build_dist` have been
run.
optional arguments:
-h, --help show this help message and exit
-v, --verbose Enable verbose output
Each subcommand also comes with its own help screen, e.g.:
$ aab build -h
usage: aab build [-h] [-t {qt6,qt5,all,anki21}] [-d {local,ankiweb,all}] [version]
positional arguments:
version Version to (pre-)build as a git reference (e.g. 'v1.2.0' or 'd338f6405').
Special keywords: 'dev' - working directory, 'current' – latest commit,
'release' – latest tag. Leave empty to build latest tag.
optional arguments:
-h, --help show this help message and exit
-t {qt6,qt5,all,anki21}, --target {qt6,qt5,all,anki21}
Anki release type to build for. Use 'all' (deprecated alias: 'anki21') to
target both Qt5 and Qt6.
-d {local,ankiweb,all}, --dist {local,ankiweb,all}
Distribution channel to build for
Build latest tagged add-on release
aab build -d local -t all release
or simply
aab build
The output artifacts will be, by default, written into ./build/
.
Compile Qt UI forms and resources for Qt6 builds of Anki
aab ui -t qt6
In order for aab
to work correctly, your project should generally follow the directory structure below:
project root
├── src [required] (contains add-on package)
│ ├── {module_name} [required] (add-on package)
├── designer [optional] (contains Qt designer .ui files that aab should compile)
├── resources [optional] (contains Qt designer .qrc files that aab should compile)
└── addon.json [required] (contains add-on meta information read by aab)
For a more detailed look at the entire directory tree please feel free to take a look at some of the add-ons I've published recently.
All of the metadata needed by aab
to work correctly is stored in an addon.json
file at the root of the project tree. For more information on its fields and their specifications please refer to the schema file.
aab
creates a package under src/<module_name>/gui/forms
that automatically takes care of choosing between forms for Qt5 builds of Anki and Qt6 builds. For instance, to import a UI form saved as options.ui
in the designer
folder, in your add-on __init__.py
you would do:
from gui.forms.options import Ui_Dialog # or whichever class name you chose for the widget/dialog
Starting with Qt6, PyQt no longer supports Qt resource files. To make the transition easier for add-on authors, aab
will automatically try to convert any resource files found under ./resources
into a Qt6-supported file structure that is then registered as a QDir
searchpath.
Alongside creating the file structure as such, aab
will also attempt to convert any references to the respective resources in your Qt forms to point to the QDir
structure. That way icons and other resources embedded into designer forms via the Qt resource system should continue working. References in other parts of your source code will have to be updated manually.
To utilize this feature, please do the following:
Pre-supposing that you have generated the gui
module using aab ui
(during development) or aab build
(for builds), initialize the QDir
searchpath by adding the following to your add-on's __init__.py
:
from .gui.resources import initialize_qt_resources
initialize_qt_resources()
This only has to execute once at add-on initialization time.
Anki Add-on Builder is Copyright © 2019-2022 Aristotelis P. (Glutanimate)
With code contributions by the following awesome people:
Anki Add-on Builder is free and open-source software. Its source-code is released under the GNU AGPLv3 license, extended by a number of additional terms. For more information please see the license file that accompanies this program.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. Please see the license file for more details.