Creating Packages
A package is a recipe in packages/<name>/. Every recipe is a declarative bpm.toml, built into a native .bpm by tools/build-bpm-pkg.sh (which drives bpmbuild in an ephemeral Arch container). The old PKGBUILD / makepkg path has been fully retired.
Anatomy of a bpm.toml recipe
# packages/hello/bpm.toml
[package]
name = "hello"
version = "2.12.1"
release = 1
summary = "GNU Hello — example package"
license = ["GPL-3.0-or-later"]
arch = ["x86_64"]
depends = ["glibc"] # runtime — Blueberry package names
makedepends = ["make", "gcc"] # build-only — pulled from Arch in the container
enable = ["hello.service"] # optional: systemd units to enable on install
[[source]]
url = "https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz"
sha256 = "..." # pin the source (or "SKIP")
[steps]
build = '''
cd "$name-$version"
./configure --prefix=/usr
make
'''
package = '''
cd "$name-$version"
make DESTDIR="$pkgdir" install
'''
The shell steps get $name $version $release $arch $pkgdir. Build it:
ENGINE=podman tools/build-bpm-pkg.sh ../out hello
# → ../out/hello-2.12.1-1-x86_64.bpm
bpm install ../out/hello-2.12.1-1-x86_64.bpm
Key rules:
dependsare runtime deps and must be Blueberry package names (resolved
from our mirror at install). makedepends are build-only and are pulled from Arch inside the throwaway build container.
- Pin
sha256per[[source]]for reproducibility. For vendor binaries that
should always fetch "latest," SKIP is acceptable.
- Install into
$pkgdirwith a/usrprefix.
build-bpm-pkg.sh:
- spins up
archlinux:latest, installsbase-devel+ the recipe'smakedepends, - runs
bpmbuildas a non-root builder with a fixedSOURCE_DATE_EPOCH, - writes the
.bpmto your out-dir, - is idempotent — a package whose
.bpmis newer than itsbpm.tomlis
skipped.
Patterns that come up a lot
- GCC 16 strictness. The build container ships GCC 16. Old K&R / C23 code
often needs -std=gnu17; some builds need -Werror=format-security stripped from CFLAGS.
- CFLAGS via ENV, not make args. Pass overrides through the environment
(export CFLAGS=...) rather than make CFLAGS=..., which can clobber a package's own -I include paths.
- Extraction dir vs
$name-$version. GitLab/GitHub archive tarballs may
extract to a differently-named directory (e.g. foo-v1.2); cd into the real directory in your steps.
- Autotools from a VCS archive. A git-archive tarball often ships no
configure; run ./autogen.sh first (add autoconf automake libtool gettext to makedepends).
- Arch name mismatches. A Blueberry package name may differ from Arch's; use
provides = [...] and reference the Arch name where a build needs it.
Submitting a recipe
Open a pull request adding packages/<name>/. See Contributing.
Blueberry