1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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.
|