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 aCargo.toml
file) - 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
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:
- The directory is changed to
$_gitname
, usingcd $_gitname
- Any local rust packages are compiled and moved to the
target/release
directory 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
man
command), 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 $_gitname
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), 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.