PKGBUILD, AUR - Making a PKGBUILD (for the AUR)

In this guide, I will use an example package called notepac (see the git repository here) to explain the contents of a fairly basic PKGBUILD file.

A PKGBUILD file is all that is required to build a package using the makepkg command, and is required to upload a package to the Arch User Repository (AUR). You can learn more about PKGBUILD by using the command man pkgbuild.

Example PKGBUILD file for a program:

# Maintainer: myname <me@email.com>
pkgname=notepac
_gitname=notepac-git
pkgver=0.0.1
pkgrel=1
pkgdesc="Make notes about your installed packages"
url="https://gitlab.com/vaba/notepac"
license=("GPL3")
source=("git+$url#tag=v$pkgver")
md5sums=("SKIP")
arch=("x86_64")
depends=("bash")
makedepends=("git" "cargo" "pandoc")

build() {
    cd $_gitname
    cargo build --release
    mkdir -p target/release/man
    pandoc --standalone -f markdown -t man man/${pkgname}.1.md > "target/release/man/${pkgname}.1"
}

package() {
    cd $_gitname
    install -Dm755 --no-target-directory "src/args-collector.sh" "${pkgdir}/usr/bin/${pkgname}"
    install -Dm755 --target-directory="${pkgdir}/usr/lib/${pkgname}" "target/release/note-manager"
    install -Dm644 --target-directory="${pkgdir}/usr/share/man/man1" "target/release/man/${pkgname}.1" 
}

What the PKGBUILD should do

The following section should help you think about what you need to do with your files in order for them to become a working package on the system.

To give some context to this specific package build, I will explain what the notepac git repository contains, and what it should do. The notepac repository contains two scripts: one bash script (called args-collector.sh) to handle user arguments, and one rust script (called main.rs) to deal with reading and writing to a file. It also contains a manpage in Markdown format. All of these files need to be adjusted for the system to access them properly.

The bash script needs to be:

  • executable by the system
  • renamed as notepac
  • moved to a location where it can be accessed by typing notepac from anywhere

The rust script needs to be:

  • packaged using the cargo build command (which is configured by a Cargo.toml file)
  • be named note-manager (this is done through cargo build)
  • allowed to be executed by the system
  • moved to a library directory for the extra scripts of the main package (notepac)

The manpage needs to be:

  • converted from Markdown to proper manpage format (readable by the man command)
  • moved to a location where it is accessible by the man command.

PKGBUILD Explanation

# Maintainer: myname <me@email.com>

This describes who the maintainer is (myname), and their email address (me@email.com). This line does not impact how the package is built.

Options and directives

pkgname

pkgname=notepac

This is the name of the package (notepac). It is an essential to include this.


_gitname=notepac-git

This is the repository name (notepac-git) on the git hosting platform which the package is being downloaded from. This is not a standard variable in PKGBUILD - which know because there is an underscore _ in front of the variable name. Hence, this is certainly not necessary to include if the pkgname is the same as the repository name.

pkgver

pkgver=0.0.1

The version number (0.0.1) of the package.

pkgrel

pkgrel=1

The release number (1) specific to the distribution. For a simple PKGBUILD like this, using 1 will be just fine.

pkgdesc

pkgdesc="Make notes about your installed packages"

A description (Make notes about your installed packages) of the package.

url

url="https://gitlab.com/vaba/notepac"

The url (https://gitlab.com/vaba/notepac) of the repository where the package files reside.

license

license=("GPL3")

The license (GPL3) which the software is licensed under. There are some common licenses which exist in most GNU/Linux systems by default. If you are using a rarer license, consider installing the license alongside the package using the package() function.

source

source=("git+$url#tag=v$pkgver")

Where the package files exist. This typically points to a specific release of the package files, which are also called tags in git. Hence the example source contains the command git, and the $url, along with the specific version $pkgver. So git+$url#tag=v$pkgver expands to be the command git https://gitlab.com/vaba/notepac#tag=v0.0.1.

md5sums

md5sums=("SKIP")

md5 checksums of the files which should match the given array. If you don’t want to bother with this, use the array ("SKIP") instead.

arch

arch=("x86_64")

An array of architectures (x86_64) of the systems which the package is to be installed on. If in doubt, just choose the architecture of your own system.

depends

depends=("bash")

This is an array of packages (bash) which this program will not function properly without. Hence, removing this package after the main package (notepac) has been installed will render the main package unusable.

makedepends

makedepends=("git" "cargo" "pandoc")

An array of packages (git, cargo, bash) which are required to build the package. These will be installed if not already installed, and can be removed after the main package (notepac) has been installed.

Functions

build() function

build() {
    cd $_gitname
    cargo build --release
    mkdir -p target/release/man
    pandoc --standalone -f markdown -t man man/${pkgname}.1.md > "target/release/man/${pkgname}.1"
}

The commands in this function prepare the files for installation via the package(). In this example:

  1. The directory is changed to $_gitname, using cd $_gitname
  2. Any local rust packages are compiled and moved to the target/release directory using cargo build --release
  3. A manpage directory is created if it does not already exist using mkdir -p target/release/man
  4. The manpage - which is in Markdown format in the git repository - is converted to the proper manpage format (one that can be read by the man command), and sent to the previously created target/release/man/ directory, using pandoc --standalone -f markdown -t man man/${pkgname}.1.md > "target/release/man/${pkgname}.1"

package() function

package() {
    cd $_gitname
    install -Dm755 --no-target-directory "src/args-collector.sh" "${pkgdir}/usr/bin/${pkgname}"
    install -Dm755 --target-directory="${pkgdir}/usr/lib/${pkgname}" "target/release/note-manager"
    install -Dm644 --target-directory="${pkgdir}/usr/share/man/man1" "target/release/man/${pkgname}.1" 
}

The commands in this function install the files in their necessary locations. Before we go over this example, I want to talk about the install command.

install

The install command enables the copying of files, and the changing of the copy’s permissions. The numbers used in m flag of the install command correspond to certain read, write and execute permissions. If you want to explore more about install, simply enter man install in your terminal.


So, breaking down the package() function in this example:

  1. The directory is changed to $_gitname, using cd $_gitname

  2. Copy the bash script to a location where binaries files typically go (/usr/bin for x86_64 systems), rename the copy as $pkgname (notepac), and convert the copy to an executable (by changing its permissions), using install -Dm755 --no-target-directory "src/args-collector.sh" "${pkgdir}/usr/bin/${pkgname}"

  3. Copy the rust executable (note-manager) to a location where extra executables of a package typically go (usr/lib for x86_64 systems), within the child directory $pkgname, using install -Dm755 --target-directory="${pkgdir}/usr/lib/${pkgname}" "target/release/note-manager"

  4. Copy the manpage to a location accessible by man, using install -Dm644 --target-directory="${pkgdir}/usr/share/man/man1" "target/release/man/${pkgname}.1"

Testing your PKGBUILD

I highly recommend using the nampac package to test your package build. It ensures the robustness of your PKGBUILD by checking for common errors or warnings.

Systemd - Periodically run a command, script, process, or service

Chromium - PDF viewer keyboard shortcuts