--- title: Packaging for Arch Linux summary: How I packaged a game to be distributed on the AUR publishedAt: 1700357203472 updatedAt: 1717543018000 --- The [AUR](https://aur.archlinux.org/) is insanely convenient for distributing and downloading software on Arch Linux. A while ago I wanted to package and distribute the modified version of [beatoraja](https://github.com/exch-bms2/beatoraja) - [lr2oraja](https://github.com/wcko87/lr2oraja). ## Why did I make a package? LR2oraja has modified timing windows to more accurately mimic the timing of the extremely old abandon-ware game Lunatic Rave 2 (LR2). People still play LR2 & both games play the same "levels" so comparing scores between them when both have different timing windows is impossible. With Beatoraja you can simply download the repo and run the shell script to play but lr2oraja only provides a patched `jar` file. I wanted an easy way for my friends and I to install this game on our linux systems. Since we commonly ran into issues with java versions and portaudio issues. ## Creating a PKGBUILD Following the Arch Wiki page with the [same name](https://wiki.archlinux.org/title/PKGBUILD), I was able to generate a basic PKGBuild file that did what I wanted. Bellow is the current PKGBUILD (minus the functions) as of the writing of this article. ```toml # Maintainer: Pfych pkgname=lr2oraja pkgver=build6711481041 pkgrel=2 pkgdesc="The latest build of beatoraja, but compiled using LR2 judges and gauges." arch=('x86_64') depends=('liberica-jre-8-full-bin' 'portaudio') makedepend=('unzip') source=( "https://github.com/wcko87/lr2oraja/releases/download/${pkgver}/LR2oraja.zip" 'https://github.com/pfych/lr2oraja-pkgbuild/releases/download/skin/skin.zip' 'https://github.com/TNG-dev/tachi-beatoraja-ir/releases/download/v3.0.0/bokutachiIR-3.0.0.jar' 'libjportaudio.so' 'beatoraja.sh' 'lr2oraja-icon.png' ) sha256sums=( '5f6dceccaeb0e786dd1658c1b481e8db114bc90a8a1056bf65753e8936ed3369' # LR2oraja.zip 'ef23b516537b4f52c306fd61ab9c4197192c06b7202b3b27b63481fec1042a26' # skin.zip '3754959d5d6f121dbeed3a78dec2b91a26e915ff4ce68fdee4262b89ad150cb9' # bokutachiIR 'a65d1290d3ee7710f9327c040e6369bf7587eb3609835ed782caaf0ac02d84ed' # libjportaudio.so 'a1c1d6ee606d042934ec1ee503a9300d5b225f3c4031be144a3c5bca24f0d042' # beatoraja.sh '0ec1382690cd847055d1b8e6da36ad6846598b45b25acca5eb5e301a5048da03' # lr2oraja-icon.png ) license=( 'GPL3' 'GPL3' 'MIT' 'unknown' 'unknown' ) prepare() {} build() {} package() {} ``` Going from top to bottom: - `pkgname` is the name of the package users will type to install the package, and what will appear on the AUR. - `pkgver` is the version of the package that will be displayed on the AUR. This can also be referenced with `${pkgver}` elsewhere in the file. This is convenient if you pull from git or an external source to get a specific released file. - `pkgrel` is the build-version of the package. You bump this value if you change the contents of the build script or a dependency. If you're `pkgver` is `1.0.0` and your `pkgrel` is `2` the final version number will appear on the AUR as `1.0.0-2` - `arch` is an array of architectures the build file supports - `depends` is an array of dependencies the package _requires_ to run - `makedepend` is an array of dependencies that are _only required_ during build - `source` is an array of files that are used by the build, if there are any URLs they will be fetched during the installation process - `sha256sums` is an array of `sha256` hashes for each of the files in `source` if any of these do not match during the build the package will fail to install. - `license` is an array of licenses for each of the files in `source` After these definitions you are then able to define functions that run during the packaging process. ### Prepare Define actions in this function that set up required files for the build step. beatoraja does not function without a skin folder so in my `prepare` function I extract the downloaded skin file fetching during setup. ```bash prepare() { # Beatoraja will fail to load without a default skin unzip -o skin.zip } ``` ### Build Define actions in this function to build your packages files, since we're downloading a zip containing a binary we don't need to run any compilers or any other actions here, so we can just extract the file. ```bash build() { unzip -o LR2oraja.zip } ``` ### Package The `package` function actually moves built files around and "installs" the package. Here we create required folders in `$pkgdir`, `$pkgdir` is a global variable that you can use to know where packages will be installed. You never refer to a path directly. The other useful global is `$srcdir` which is the path where `build()` and `prepare()` run. ```bash # Create required directories cd "$srcdir/" mkdir -p "$pkgdir/opt/beatoraja/ir" mkdir -p "$pkgdir/usr/lib" mkdir -p "$pkgdir/usr/share/applications" mkdir -p "$pkgdir/usr/share/pixmaps" ``` We then move all the files we created during `build()` and `prepare()` into those newly created directories & set permissions. ```bash # Move all required Beatoraja Files cp libjportaudio.so "$pkgdir/usr/lib" cp beatoraja.jar "$pkgdir/opt/beatoraja/beatoraja.jar" cp -r skin "$pkgdir/opt/beatoraja" cp "bokutachiIR-3.0.0.jar" "$pkgdir/opt/beatoraja/ir" chmod -R 777 "$pkgdir/opt/beatoraja" ``` We then create a `.desktop` entry to make the game easier to launch, it's a bit tedious but this `echo` append method is consistent. ```bash # Create Desktop entry cp lr2oraja-icon.png "$pkgdir/usr/share/pixmaps" desktopEntry="$pkgdir/usr/share/applications/lr2oraja.desktop" touch "$desktopEntry" echo "[Desktop Entry]" >> "$desktopEntry" echo "Type=Application" >> "$desktopEntry" echo "Terminal=true" >> "$desktopEntry" echo "Exec=/usr/bin/beatoraja" >> "$desktopEntry" echo "Version=$pkgver" >> "$desktopEntry" echo "Name=LR2oraja" >> "$desktopEntry" echo "Categories=Games;" >> "$desktopEntry" echo "Icon=lr2oraja-icon" >> "$desktopEntry" ``` Finally, we create a symlink to the games install location at the users `$XDG_CONFIG_HOME`, if this isn't set we create it at `~/.config`. The last line here just moves the start script into the users bin folder. We create this symlink since most users expect program configuration files to exist in their systems config folder, Since LR2oraja is not linux native all the config files exist in its installation directory - This symlink just connects `~/.config/beatoraja` to that install location. ```bash if [ -z "$XDG_CONFIG_HOME" ]; then XDG_CONFIG_HOME="$HOME/.config" fi # Create config symlink ln -sfn "$pkgdir/opt/beatoraja" "$XDG_CONFIG_HOME/beatoraja" # Install LR2oraja install -D beatoraja.sh "$pkgdir/usr/bin/beatoraja" ``` ## Distributing Once you've set up and configured your `PKGBUILD` file you need to generate a `.SRCINFO` file. This can be done with a single command: ```bash makepkg --printsrcinfo > .SRCINFO ``` You can then test your package installation by running: ```bash makepkg pacman -U myPackageName.pkg.tar.zst ``` Once you know your package is working you can initialise a git repo & push to the AUR. Here are a few gotchas that caught me as well as some tips: 1. Your entire repo & it's history must be smaller than around 1-2mb. Your repo should contain as little as possible - preferably only text files! 2. _Every_ commit in the repo must result in a successful build. No "WIP" commits. 3. **_Always_** remember to bump your `pkgrel` when making small changes to your build files 4. If you are working with a frequently changing code base or repo, ensure you configure your `source` urls and `pkgversion` in a way where you can avoid having to make major changes to the build file any time a change is made to the original codebase. The LR2oraja `PKGBUILD` refers only to the static release files on GitHub - where the package version number is the version number used in the releases URL. This allows me to just change the version number to fetch the latest version. [Here's the official guidelines and steps for submitting a package to the AUR](https://wiki.archlinux.org/title/AUR_submission_guidelines). If everything worked and your package is now appearing on the AUR you can install it using your favourite AUR helper! ```bash yay -Syu lr2oraja ``` If you want to view the final PKGBUILD for LR2oraja you can do so [here](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=lr2oraja).