There's also a tutorial with example commands.
[[TOC]]
Create a plain text file with the list of package metainfo URLs. Make sure you end the last URL too with a newline character.
Create a certificate with cert --repo
, and append it to the text file.
Upload the file to a static webserver (you can have multiple files with different lists using the same cert, like "base.txt", "community.txt", etc.).
If your repo is open, accept requests and URLs from developers (via email, github/gitlab issues whatever), sign their
certs with cert --sign
, send it back to them and add their metainfo URLs to the list.
Generate a signed url list with build
(and optionally an html for a webpage frontend).
By specifying a html file name on the command line, build
will generate a searchable package catalog too for you.
$ syspkg build repolist.txt index.html url=https://somewhere.com/repolist.txt
The page will be generated for packages using the system's locale, but the translatable labels must be specified for non-English
pages. For that, you can use the following command line options:
| Label | Description |
|------------------|---------------------------------------------------------------------------------|
| url
| the real url of the repository (if the first argument to build is a local file) |
| title
| title of the page (default's to canonical name in the repository certificate) |
| Repository
| text of the repository link |
| Search
| search input field's placeholder |
| Package Size
| name of the package size coloumn |
| Installed Size
| name of the installed size coloumn |
| Download
| name of the coloumn with the download links |
| Homepage
| label for the package's homepage |
| Bugtracker
| label for the package's bugtracker |
| Maintainer
| label for the package's maintainer |
| License
| label for the package's license |
| Depends
| label for the package's mandatory dependencies list |
| Suggests
| label for the package's optional dependencies list |
| Conflicts
| label for the package's blocking dependencies list |
| any other | translated package category name |
First of all, if you don't have a developer cert already, create one with cert
. You can have it signed with a repository
owner. Users can only install packages which are signed by a trusted cert or by a cert issued by the repository's cert.
Create a metainfo JSON, describing your package (name, version, description, etc.).
Run syspkg's build
command, this will create the payloads and add or update fields in the metainfo as well as the signature.
You can use a git branch and then rely on github's or gitlab's "Download ZIP" feature. Otherwise upload your payloads to a static
webserver.
Upload your metainfo file to a static webserver next to the payloads (or to github, gitlab etc.)
If you haven't done already, add your metainfo URL to one of the repositories, or create your own repository file and upload it to a static webserver.
For a new release, one need to repeat steps 3. and 4.
To check your certificate, simply do
$ syspkg cert | openssl x509 -text
You must specify an UTF-8 encoded, local JSON file with the package metainfo. Don't care about all the fields, build will add some of them.
Field | Description |
---|---|
id |
unix name of your package, must only contain the letters a-zA-Z0-9_-. |
description |
an array with three string objects, language code, name, description |
version |
canonical version string, (major).(featureset).(bugfix/patch) |
release |
free form version string, could contain "-beta", "-pre", "-stable" etc. |
url |
payload URL mask, may contain $VERSION, $RELEASE, $ARCH, $OSVER strings |
category |
exactly one of the available category ids |
license |
your project's license (MIT, GPLv3 etc.) |
Field | Description |
---|---|
depends |
list of required dependencies (optional) |
suggests |
list of optional dependencies (optional) |
conflits |
list of packages that this package is conflicting (optional) |
eula |
your project's End User License Agreement URL (optional) |
homepage |
your project's homepage URL with additional information (optional) |
bugtracker |
your project's online bugtracker's URL (optional) |
screenshots |
array of URLs, must be PNG (preferably with quantized palette, optional) |
override |
struct for overriding default file categories (optional, see below) |
postinst.env |
postinstall environment variables configuration (optional, see below) |
postinst.commands |
postinstall commands to be executed (optional, see below) |
The URL fields eula
, homepage
, bugtracker
and screenshots
might contain $LANG, this will be substituted by the
user's locale two letter language code. If there's no such description translation in the json, then the first description's
language code will be used.
This local json file is the first parameter to syspkg's build
, and if no more arguments given, or they are in (arch)=(url)
form, then the payloads are downloaded and checked (also with (arch)=(zipfile)
). If they are given in the form (arch)=(dir)
,
then payloads are generated to the current working directory by the name (packageid)-(version)-(arch).zip
. This is preferred
over github's and gitlab's "Download ZIP" URLs, because it generates a much better compressed ZIP64 files (using zstd instead
of deflate).
Notes: for packages without native binaries, $ARCH is "any". If the "id" contains a "." dot, then only the first part of the name will be used when checking for dependencies.
$ syspkg build mypackage.json any=builddir
When you specify a directory as payload, a ZIP will be created for you in the current working directory.
$ syspkg build mypackage.json any=mypackage.zip
When you specify a local payload file, it will be scanned for files.
$ syspkg build mypackage.json any=https://some.org/mypackage.zip
Similarly to local payload files, you can specify a remote URL which will be downloaded and scanned for files.
If you have architecture specific payloads, you must list them all. You can mix the different payload methods. Example:
$ syspkg build mypackage.json x86_64=mypackage-x64.zip aarch64=build/arm64 riscv64=https://some.org/mypackage-rv64.zip
Running this command will add (or update) the payloads
and files
json fields and signature after. First field is an array of
structs, each element with architecture, compressed payload size, uncompressed size, SHA checksum fields. The second is just
an array of file sizes and string with file names.
Example
{
"id": "myproject",
"description": [
{ "en_US", "My Project", "English description\nanother line\nthird line" },
{ "en_GB", "Me Project", "British description" },
{ "de", "Meine Projekt", "Deutche Beschreibung" },
{ "es", "Mi Proyecto", "Español descripción" }
],
"version": "1.0.1",
"release": "1.0-beta-rc",
"url": "https://github.com/myuser/myproject/archive/$VERSION-$ARCH.zip",
"category": "tools",
"depends": [ "libc 1.0.0", "libx11 6.0.0" ],
"suggests": [ "libpng", "libjpeg 2.0.0" ],
"license": "MIT",
"eula": "https://github.com/myuser/myproject/raw/master/LICENSE",
"homepage": "https://myuser.github.io/myproject",
"bugtracker": "https://github.com/myuser/myproject/issues",
"screenshots": [
"https://github.com/myuser/myproject/raw/master/docs/screen1.png",
"https://github.com/myuser/myproject/raw/master/docs/screen2.png"
],
"postinst": {
"env": [
{ "name": "FEAT1", "type": "chk(disable,enable)", "desc": [ { "en", "Some feature", "Adds X feature" } ] },
{ "name": "CFLAGS", "type": "str(-ansi -Wall)", "desc": [ { "en", "Compiler flags", "Specify gcc flags" } ] },
{ "name": "LDFLAGS", "type": "str(-nostdlibs)", "desc": [ { "en", "Linker flags", "Specify ld flags" } ] },
{ "name": "MAKEJ", "type": "num(1,16,2)", "desc": [ { "en", "Threads", "Number of threads" } ] }
],
"commands": [
"$SRCDIR/configure --with-cflags=$CFLAGS --with-ldflags=$LDFLAGS --$FEAT1-somefeature",
"make -C $SRCDIR -j $MAKEJ all",
"make -C $SRCDIR install"
]
},
"payloads": [
{ "x86_64", 1234, 23456, "be82deeabe8f4a38cdd6d5b195c287f32f7287d6861ca591b88b180d29b87f78" },
{ "aarch64", 1245, 23567, "d4056f2ff1a01ac23cbed8ad767f61f421f60a4d54ffab14c724ce1bd7000d13" },
{ "riscv64", 1256, 23678, "c0e8b735574fbd2261b1c738c1949fb6f35aae38cc05ab6661c00eaf1add81a9" }
],
"files": [
{ 128, "bin/myproject" },
{ 256, "inc/myproject/myproject.h" },
{ 256, "inc/myproject/myproject.hpp" },
{ 512, "lib/libmyproject.so" }
]
}
------BEGIN SIGNATURE------
MIIE8jCCAtqgAwIBAgIEYBDuvzANBgkqhkiG9w0BAQsFADAwMQwwCgYDVQQDDANi
enQxEzARBgNVBAoMCm1haW50YWluZXIxCzAJBgNVBAYTAkhVMCAXDTIxMDEwMTAw
... more lines like these ...
1DzRRdPpbwviuVczINx7lr+qzjB13IFhlfh60AYhPtxkLof/qcqHlUT/EAhn9Hfx
cpZ2Wq/ehpYw=
------END SIGNATURE------
In this case you should specify directories with compiled executables for syspkg build
. If no payloadspec given, syspkg
will use the "url" field in the metajson and will iterate on all available architectures (given in config.h) to find payloads.
Here you must specify a playload for architecture "any". The files in the payload must be source files, and you must specify "postinst" in the metajson describing how to compile the source.
Only ZIP (and ZIP64) supported. ZIP is standardized, well-supported on all operating systems, and code hosting servers can generate it dynamically out of a git branch. Supported compression methods: 0 - store, 8 - deflate (compatibility) and 93 - zstd (prefered).
The payload might contain a main directory (like "myproject-master/"), or it can include the specific directories in its root.
To simplify the package management significantly, syspkg expects special directory names in the payloads to categorize installed files. Where these should be extracted is configurable at compilation time, see config.h. There's one exception to the rule, the package that provides "base" (in json "id": "base"). That package is extracted to the root directory as-is, and cannot be uninstalled. It is a special package for updating the base operating system.
It is very important to understand that top level directories in payloads do not represent the directory structure that's going to be installed (only sub-directories do). Instead top level directories are categories. There's only one exception to this rule, when the package is called "base".
Content | Destination | Description |
---|---|---|
bin/* |
BINDIR | executable binaries and scripts |
lib/* |
LIBDIR | dynamically linkable, shared libraries (.so, .dll) |
inc/* |
INCDIR | include files |
etc/* |
ETCDIR | configuration files |
shr/* |
SHRDIR | shared files |
var/* |
VARDIR | variable files (if any, could be empty) |
man/* |
DOCDIR | manual pages and other help files |
src/* |
SRCDIR | source files |
The payload directories (first coloumn above) is also configurable in config.h in general with BINPDR, LIBPDR etc. defines. If
this does not suit a specific payload (because it comes from a 3rd party), you can override the category directories in the
metajson with the override
field, like this:
{
"id": "myproject",
"description": [
{ "en_US", "My Project", "English description" }
],
"version": "1.0.1",
"release": "1.0-beta-rc",
"url": "https://github.com/myuser/myproject/archive/$VERSION-$ARCH.zip",
"category": "tools",
"license": "MIT",
"override": {
"bin": "build/cli",
"lib": "build/so",
"src": "code",
"inc": "code/headers"
}
}
If postinst
exists, it's a form definition and list of commands in json. The packager will generate a form according to that
spec and the field's values (provided by the user) will be passed as environment variables to the commands (along with the
actual destination directories), which in turn can create further configuration files (based on the user input), or they can
compile the sources by calling configure
/ cmake
and then make
etc. Whatever needed to properly set up the package.
The environment variables' type can be:
Type | Description |
---|---|
str(default) |
a string, defaults to default |
num(min,max,default) |
a decimal numeric value |
chk(unchecked,checked) |
a checkbox, string unchecked or checked is used as value |
sel(opt1,opt2, ...) |
a selectbox, selects one of the optX strings |
With string arguments, \\
, \,
and \)
can be used to escape special characters in the strings.
It is possible to create a meta-package, that is a package which doesn't have payloads, only dependencies. Such a package can be used to install a group of packages at once.
Example:
{
"id": "gui",
"description": [
{ "en_US", "Graphical desktop", "Installs the entire graphical environment" }
],
"version": "1.0.0",
"category": "tools",
"depends": [ "libc", "libx11", "xorg-xserver", "xterm", "openbox", "xbill", "xroach" ]
}
Package unix names may contain one dot, and it represents an alternative. For example, if the package "id": "cron.vixie" is installed, that satisfies all packages that depend on "cron".