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
notepacfrom anywhere
The rust script needs to be:
- packaged using the
cargo buildcommand (which is configured by aCargo.tomlfile) - be named
note-manager(this is done throughcargo 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
mancommand) - moved to a location where it is accessible by the
mancommand.
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:
- The directory is changed to
$_gitname, usingcd $_gitname - Any local rust packages are compiled and moved to the
target/releasedirectory usingcargo build --release - A manpage directory is created if it does not already exist using
mkdir -p target/release/man - 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
mancommand), and sent to the previously createdtarget/release/man/directory, usingpandoc --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:
The directory is changed to
$_gitname, usingcd $_gitnameCopy 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), usinginstall -Dm755 --no-target-directory "src/args-collector.sh" "${pkgdir}/usr/bin/${pkgname}"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, usinginstall -Dm755 --target-directory="${pkgdir}/usr/lib/${pkgname}" "target/release/note-manager"Copy the manpage to a location accessible by
man, usinginstall -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.