aboutsummaryrefslogtreecommitdiff
path: root/docs/writing_abuild.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/writing_abuild.md')
-rw-r--r--docs/writing_abuild.md229
1 files changed, 229 insertions, 0 deletions
diff --git a/docs/writing_abuild.md b/docs/writing_abuild.md
new file mode 100644
index 00000000..2a82d86b
--- /dev/null
+++ b/docs/writing_abuild.md
@@ -0,0 +1,229 @@
+# Writing an abuild recipe
+
+An `abuild` file is a POSIX shell snippet that tells apkg how to build a package. The directory containing it must have the same name as the package.
+
+See `man apkg` for full details on all options and environment variables, and `man apkg-genabuild` for the recipe scaffolding tool.
+
+To quickly scaffold a new recipe from a source URL, use `apkg-genabuild`:
+
+```sh
+apkg-genabuild https://example.com/mypkg-1.2.3.tar.gz
+```
+
+This creates the directory and a skeleton `abuild` with `name`, `version`, `release`, and `source` already populated.
+
+## Directory structure
+
+```
+mypkg/
+ abuild - package recipe (required)
+ info - package metadata template (description, homepage, license, maintainer)
+ depends - dependency list, one per line (optional)
+ preinstall - script run before the package is built (optional)
+ postinstall - script run after the package is installed (optional)
+ .shasum - source checksums, auto-generated (regenerate with `apkg -g`)
+ .files - package file list, auto-generated (regenerate with `apkg -k`)
+```
+
+## Minimal recipe
+
+```sh
+name=mypkg
+version=1.2.3
+release=1
+source="https://example.com/$name-$version.tar.gz"
+```
+
+### Required variables
+
+- **`name`**: package name. Must match the directory name exactly.
+- **`version`**: upstream version string. Use the `$name` and `$version` variables in the source URL so updates are easier.
+- **`release`**: an incrementing integer starting at 1. Reset to 1 when `version` changes. Bump when the package needs a rebuild without a source change.
+
+## Source formats
+
+The `source` variable accepts a whitespace-separated list. Five formats are supported:
+
+- **`https://example.com/pkg-1.0.tar.gz`**: A remote URL, downloaded with curl
+- **`mypkg-1.0.tar.gz::https://example.com/v1.0.tar.gz`**: Custom local filename for a remote URL
+- **`https://example.com/pkg.tar.gz::noextract`**: Download but do not unpack
+- **`my-file`**: A local file in the recipe directory (not downloaded)
+- (empty): Create a meta/dummy package with only `/usr`
+
+Multiple sources can be specified:
+
+```sh
+source="https://example.com/$name-$version.tar.gz
+ fix-build.patch
+ default-config::noextract"
+```
+
+If `source` is empty, apkg creates a dummy package: useful for meta packages that exist only to pull in dependencies.
+
+## Optional variables
+
+### Build control
+
+- **`build_type`**: force a specific build system instead of auto-detection. One of: `meson_build`, `configure_build`, `cmake_build`, `python_build`, `perlmodule_build`, `makefile_build`.
+- **`build_dir`**: subdirectory within the extracted source tree to enter before building. Useful when a tarball extracts into a differently-named directory.
+- **`build_opt`**: extra flags appended to the build system command. The defaults (`--prefix=/usr`, `--sysconfdir=/etc`, etc.) are always included; this adds on top.
+- **`skip_patch`**: set to `1` to skip automatic patch application. Use this if you need to call `apply_patch` manually from `build()`.
+- **`patch_opt`**: options for `patch(1)`. Default: `-p1`.
+
+### Package content control
+
+- **`keep_static`**: set to keep `*.a` static libraries (removed by default).
+- **`keep_libtool`**: set to keep `*.la` libtool archives (removed by default).
+- **`keep_locale`**: set to keep locale files in `/usr/share/locale` and `/usr/lib/locale`.
+- **`keep_doc`**: set to keep documentation in `/usr/share/doc` and `/usr/doc`.
+- **`no_strip`**: set to skip ELF binary and library stripping.
+
+### Runit services
+
+- **`sv`**: service files to install into `/etc/sv`. Accepts:
+ - `run` → `/etc/sv/$name/run`
+ - `finish` → `/etc/sv/$name/finish`
+ - `<name>.run` → `/etc/sv/<name>/run`
+ - `<name>.finish` → `/etc/sv/<name>/finish`
+ - `<name>.<ext>` → `/etc/sv/<name>/<ext>`
+
+```sh
+sv="run finish mydaemon.run mydaemon.finish"
+```
+
+## Build hooks
+
+### Custom build function
+
+If a `build()` function is defined, it completely replaces the auto-detected build system. Two variables are available:
+
+- **`$SRC`**: where sources were extracted
+- **`$PKG`**: the fakeroot directory where files must be installed
+
+Several `DESTDIR`-style variables are pre-exported: `DESTDIR`, `DEST_DIR`, `INSTALLROOT`, `install_root`, `INSTALL_ROOT`.
+
+```sh
+build() {
+ cd "$SRC/$name-$version"
+ ./configure --prefix=/usr --sysconfdir=/etc
+ make
+ make DESTDIR="$PKG" install
+}
+```
+
+`build()` runs with `set -ex`, so the script exits on any error and prints each command.
+
+### Pre/post build hooks
+
+Without a `build()` function, you can use `prebuild()` and `postbuild()`:
+
+```sh
+prebuild() {
+ sed -i 's/broken/fixed/g' src/whatever.c
+}
+
+postbuild() {
+ mv "$PKG/usr/bin/wrongname" "$PKG/usr/bin/rightname"
+}
+```
+
+The execution order is: `prebuild()` → auto-detected build system → `postbuild()`.
+
+## Build system auto-detection
+
+When no `build()` is defined and no `build_type` is set, apkg checks for these files in order:
+
+1. `meson.build`: meson with LTO, PIE, `wrap_mode=nodownload`, `buildtype=plain`
+2. `configure`: autotools `./configure --prefix=/usr --sysconfdir=/etc ...`
+3. `CMakeLists.txt`: cmake with `Release` build type, prefers ninja
+4. `setup.py`: `python3 setup.py build && install --root=$PKG`
+5. `Makefile.PL`: `perl Makefile.PL && make && make install`
+6. `Makefile` / `makefile` / `GNUmakefile`: raw make with standard variables
+
+The exact flags for each build system are documented in `doc/defaultbuildopts`.
+
+## Post-build processing
+
+After compilation, apkg automatically:
+
+- Compresses man pages (man1–man8 only, gzip) and info pages
+- Removes common conflict files: `fonts.dir`, `fonts.scale`, `perllocal.pod`, `charset.alias`
+- Removes static libraries (`*.a`), libtool archives (`*.la`), locales, and docs unless the corresponding `keep_*` variable is set
+- Strips ELF binaries (`--strip-all`), shared objects (`--strip-unneeded`), and static archives (`--strip-debug`) unless `no_strip` is set
+- Installs runit service files from the `sv` variable
+
+## The info file
+
+`apkg-genabuild` creates an `info` file alongside the `abuild` with package metadata:
+
+```
+description:
+homepage:
+license:
+maintainer: name <name at mail dot com>
+```
+
+Fill in each field as appropriate. The `maintainer` line uses the format `name <email>`.
+
+## The depends file
+
+One dependency per line. Lines starting with `#` are comments. Dependencies are just package names: no version constraints.
+
+```
+# Direct dependencies of mypkg
+zlib
+libpng
+freetype
+```
+
+Dependencies are recursive: when installing with `-I`, apkg will resolve the full tree. Only list direct dependencies; transitive ones are handled automatically. Use `apkg-redundantdeps` to find and clean up transitive entries.
+
+## preinstall / postinstall scripts
+
+These are optional executable scripts in the recipe directory:
+
+- **`preinstall`**: runs before the package is built (only during `apkg -i` or `apkg -u`). Good for pre-flight checks or preparing the system.
+- **`postinstall`**: runs after the package is installed or upgraded. Good for one-time setup that can't be done at build time.
+
+If `APKG_ROOT` is set (alternative install root), these scripts run inside a chroot.
+
+## Checksums and file lists
+
+- **`.shasum`**: sha3sum of each source file, auto-generated on first build. Regenerate with `apkg -g <pkg>`.
+- **`.files`**: sorted list of every file in the built `.spm`, auto-generated after packaging. Regenerate with `apkg -k <pkg>`. Used by `apkg -S` for file search.
+
+## Complete example
+
+```sh
+name=hello
+version=2.12.1
+release=1
+source="https://ftp.gnu.org/gnu/hello/$name-$version.tar.gz"
+
+build() {
+ cd "$SRC/$name-$version"
+ ./configure --prefix=/usr
+ make
+ make DESTDIR="$PKG" install
+}
+```
+
+With a `depends` file:
+
+```
+zlib
+```
+
+With a `postinstall` script:
+
+```sh
+#!/bin/sh
+echo "hello was installed!"
+```
+
+## Tips
+
+- Use `apkg-genabuild <url>` to scaffold a recipe from a source URL quickly.
+- Use `$name` and `$version` in source URLs so bumping the version only requires changing two variables.
+- Patches (`.patch` / `.diff` files) listed in `source` are applied automatically with `patch -p1` before the build. Use `patch_opt` to change the strip level.
+- Set `APKG_KEEP_WORKDIR=1` in your environment to inspect the build tree when debugging a failed build.