content/wiki/package/create.md

9.8 KiB

On this page, you will learn how you can create your first MatterLinux package for the official pools.

Pre-requirements

  • You should have an up-to-date MatterLinux installation
  • You should have general understanding of software packaging
  • You should have general understanding of building/compiling software
  • You should know the basics of bash scripting
  • You should know the basics of git version control system

Getting started

If you want to add your package to the official pools, then please check the official pool guidelines. Make sure that your package follows the guidelines or your pull request may be rejected.

Also, create an account on Gitea server and configure your editor as specified in the contribution guide.

Install requirements

To follow this tutorial you will need a working MatterLinux installation (minimum version 24.05). You also need to install the following packages from the base pool:

  • an editor (vim and nano is avaliable on the base pool)
  • build-essential
  • mtsc
  • git

Selecting a pool

If you want to add a new package to the official pools, you should first choose the pool you want to add the package to. You should check the list of official pools, and figure out which pool your package belongs to.

Fork the pool

After selecting the pool, fork it on Gitea and clone it to MatterLinux system:

$ git clone <git repository url>

Create a new branch for your package:

$ git branch -m new-package

To build and create packages, you should install the build-essential package from the base pool. This package will provide you with all the base tools required, such as the GNU C compiler. You will also need

Create the package template

Change directory into the src folder of the pool you cloned, and use the mp-new command (a script from mp-build) to create an empty package script:

$ cd src 
$ mp-new <name of the package>_<version of the package>

Package name should be full lowercase, it should not contain any non-English characters, and it should not contain underscore (_). If there is an underscore in the package name, replace it with -. Package name also should NOT contain a version number.

Version name ideally should contain a version number separated with dots. However this may heavily change based on how the upstream actually versions the software. Version should also be updated after every modification. If the modification does not change the upstream version, then you should suffix the version with m<number of changes>, for example 1.2m1, 8.7.3m7 etc. Version name should also not contain underscores (_), you should replace them with -.

For this example we will be packaging the LXTerminal (version 0.4.0) from LXDE:

$ cd src 
$ mp-new lxterminal_0.4.0

Modify the package script

mp-new will create a directory for the new package, named after the package, which will contain a pkg.sh script. This script is called the package script. Open this script with the configured editor:

# general info
NAME="lxterminal"
DESC=""
VERSION="0.4.0"

# required files
FILES=()
HASHES=()

# install and build depends
DEPENDS=()
BUILD=()

PACKAGE() {
  tar xf "${NAME}-${VERSION}.tar.gz"
  cd "${NAME}-${VERSION}"

  cd .. && rm -r "${NAME}-${VERSION}"
}

Description

First of all you should add a description. Description should be short (less than 200 characters), and it should explain details about the package. Ideally, description should not contain words such as "contains" and "includes". Here are some bad examples:

  • LXTerminal package contains a VTE-based terminal emulator
  • LXTerminal includes the LXDE terminal emulator

And here are some good examples:

  • VTE-based terminal emulator for LXDE
  • LXDE terminal emulator

Version

You should package a stable version of the software, do not package the latest git commit or something like that. Package an official released version.. For this example we will be packaging the version 0.4.0.

Files

List of files needed for this package, you can specify HTTP(S) or FTP(s) URLs. Or you can specify simply just filenames to pull the packages from the local source directory.

If possible, you should replace the version number in the URL with the VERSION variable.

Hashes

Specify hashes for the files you specified, you can use the NOHASH as the hash to disable hash verification for a specific file.

Depends

Run-time dependencies for the package, do not specify the make or the build dependencies that are only used for compiling the software.

Build

Build-time dependencies for the package, dot not specify any run-time dependencies again if they are also needed for the build process. Also do not specify any package that is part of build-essential.

With the addition of the details above, here is how our example package script looks like:

# general info
NAME="lxterminal"
DESC="Commands for manipulating POSIX Access Control Lists"
VERSION="0.4.0"

# required files
FILES=("https://downloads.sourceforge.net/lxde/lxterminal-$VERSION.tar.xz")
HASHES=("7938dbd50e3826c11f4735a742b278d3")

# install and build depends
DEPENDS=("vte")
BUILD=()

PACKAGE() {
  tar xf "${NAME}-${VERSION}.tar.gz"
  cd "${NAME}-${VERSION}"

  cd .. && rm -r "${NAME}-${VERSION}"
}

Package function

The package function contains the instructions for building the package itself. When building the package, mp-build will download all the files and remove them after the build, so you do not have to deal with that.

To make your life simpler, mp-new creates a boilerplate PACKAGE() function template. Now will modify it to make it work our package.

First, we should do is to extract the downloaded file, and change directory into the newly extracted folder:

tar xf "${NAME}-${VERSION}.tar.gz"
cd "${NAME}-${VERSION}"

Then we can change directory into the pool source directory and run the build and install instructions:

./configure --enable-man --prefix=/usr
make && make install 

With this configuration, make install will try to install the package to the actual system, however we want to install the package to the package build directory, so we will use the DESTDIR flag for that:

./configure --enable-man --prefix=/usr
make
make DESTDIR="${ROOTDIR}" install 

$ROOTDIR is a custom variable that is set during the package build. During the build it will point to the package build directory.

After building and installing the package, we can change directory back up, and remove the extracted folder:

cd .. && rm -r "${NAME}-${VERSION}"

So the final script should look like this:

# general info
NAME="lxterminal"
DESC="Commands for manipulating POSIX Access Control Lists"
VERSION="0.4.0"

# required files
FILES=("https://downloads.sourceforge.net/lxde/lxterminal-$VERSION.tar.xz")
HASHES=("7938dbd50e3826c11f4735a742b278d3")

# install and build depends
DEPENDS=("vte")
BUILD=("intltool")

PACKAGE() {
  tar xf "${NAME}-${VERSION}.tar.xz"
  cd "${NAME}-${VERSION}"

  ./configure --enable-man --prefix=/usr 
  make
  make DESTDIR="${ROOTDIR}" install

  cd .. && rm -r "${NAME}-${VERSION}"
}

Formatting the package script

When you are done, format the package script following these rules:

  • If you have multiple files, put each one of them to a new line, same for the hashes.
  • If you have more than 5 depends, split them into new lines, grouping 3 depends together.
  • If you have long commands in the build function, split them to new lines using a backslash (\)
  • Prevent using && unless it's absolutely necessary, it usually ends up messing the error checking
  • Split unrelated instructions with a newline

You can use the mp-check script to automatically check for some of these issues:

$ mp-check lxterminal

Building the package

To build the newly created package, run the following in the src directory:

$ mp-build --no-sign lxterminal

This will install all the required dependencies, and only build the specified package.

Testing the package

When build is completed, you will have a new .mpf package archive in the dist directory of the package directory. You can check this archive for any potential issues using mp-check again:

$ mp-check lxterminal/dist/lxterminal_0.4.0.mpf

After fixing any potential issues and warnings, you can install your newly created package using the package manager and test it out:

# matt install --yes lxterminal/dist/lxterminal_0.4.0.mpf 
$ lxterminal

Stage and commit your changes

After making sure that the package is working as intended, go back to the root of the pool source directory, and use git add . to stage all the changes. Then use git commit -m <message> command to commit them. For the commit message, follow the guidelines on the contribution page. For our example, the following message should be fine:

$ git commit -m "new: lxterminal package"

Then push your branch to the remote:

$ git push -u origin new-package 

Creating a pull request

Back on the Gitea, create a pull request to the official repository. Provide information about the package you added, and explain why you think its important to include this package.

Please patiently wait for a response from the maintainer(s) after creating your pull request, if find out any problems with your package after creating the pull request, fix them and make more commits to your new branch, they should automatically be added to the pull request.

You are done!

If you follow every step correctly your pull request will be merged. After the merge, your package will be added to the development (next) pools and after some testing it will make it's way to the stable pools.