aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 699466e698ffbb21f3326c649c2ae2cd6c7b42ba (plain)
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
# autils

Alice Linux Utilities: a collection of POSIX shell scripts for source-based package management on [Alice Linux](https://codeberg.org/emmett1/alicelinux).

## Overview

**apkg** is the core package manager. It reads an `abuild` recipe (a POSIX shell snippet defining the package name, version, sources, and optional build hooks), downloads and verifies source tarballs, auto-detects one of 6 supported build systems, compiles the software, post-processes the result (strip binaries, compress man pages, install runit services), packages it into the `.spm` format, and installs or upgrades the package via the **spm**(8) backend.

A set of `apkg-*` helper scripts handle binary package management, dependency analysis, repo syncing, orphan detection, cleanup, and more. Standalone utilities cover reverse-dependency checking (`revdep`), configuration file merging (`updateconf`), and environment-driven git repository synchronization (`reposync`).

## Installation

```sh
make install
```

Installs all scripts into `/usr/bin` and man pages into `/usr/share/man/man8`.
Override with `DESTDIR`, `PREFIX`, `BINDIR`, or `MANDIR`. Individual scripts are
self-contained and can be run directly from the source tree for testing.

## Quick start

```sh
# Build and install a package (from inside its recipe directory)
cd /path/to/repo/mypkg
apkg -i

# Install with automatic dependency resolution
apkg -I firefox

# Search available packages
apkg -s icon

# List outdated packages on the system
apkg -l

# Full system upgrade
apkg -U

# Remove a package and its unneeded dependencies
apkg-purge -p mypkg

# Find broken library links after an upgrade
revdep

# Merge .new config files after an upgrade
updateconf
```

## Tools

### Core

| Tool | Description |
|---|---|
| `apkg` | Build packages from source, resolve dependencies, install/upgrade/remove, search repos, system upgrade |
| `spm` | Low-level `.spm` package installer (external, not in this repo) |

### Helpers

| Script | Purpose |
|---|---|
| `apkg-chroot` | Enter a chroot with `/dev`, `/proc`, `/sys`, `/run` bind-mounted |
| `apkg-clean` | List stale `.spm` files and orphaned source tarballs (pipe to `xargs rm`) |
| `apkg-deps` | Show runtime library dependencies of an installed package via `ldd` |
| `apkg-foreign` | List installed packages not found in any configured repo |
| `apkg-genabuild` | Scaffold an `abuild` recipe file from a source URL |
| `apkg-orphan` | List installed packages that have no dependents installed |
| `apkg-purge` | Remove a package and its dependencies that are no longer needed by others (`-p` to actually remove) |
| `apkg-redundantdeps` | Detect transitive dependencies explicitly listed in `depends` files (`-f` to fix) |

### Standalone utilities

| Tool | Description |
|---|---|
| `revdep` | Scan system binaries and libraries for missing library links (run after major upgrades) |
| `updateconf` | Interactive `.new` config file merge tool: diff, keep, discard, or edit |
| `reposync` | Git repo sync driven by `REPOSYNC_*` environment variables (no `/etc/apkg.conf` dependency) |

## The abuild recipe

An `abuild` file is a POSIX shell snippet sourced by apkg. The directory containing it must have the same name as the `name` variable.

A minimal recipe:

```sh
name=mypkg
version=1.2.3
release=1
source="https://example.com/$name-$version.tar.gz"
```

### Source formats

The `source` variable accepts five formats:

| Format | Description |
|---|---|
| `https://example.com/pkg-1.0.tar.gz` | A remote URL |
| `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 |
| (empty) | Create a dummy/meta package with only `/usr` |

### Optional recipe variables

| Variable | Purpose |
|---|---|
| `build_opt` | Extra flags appended to the auto-detected build system |
| `build_type` | Force a specific build system (`meson_build`, `configure_build`, `cmake_build`, `python_build`, `perlmodule_build`, `makefile_build`) |
| `build_dir` | Subdirectory within the extracted source to enter before building |
| `sv` | Runit service files to install into `/etc/sv` |
| `skip_patch` | Skip automatic `.patch` / `.diff` application |
| `patch_opt` | Options for `patch` (default: `-p1`) |
| `keep_static` | Keep `*.a` static libraries |
| `keep_libtool` | Keep `*.la` libtool archives |
| `keep_locale` | Keep locale files |
| `keep_doc` | Keep documentation |
| `no_strip` | Skip ELF binary stripping |

### Build hooks

If a `build()` function is defined, it replaces the auto-detected build system entirely. Use `$SRC` (source extraction directory) and `$PKG` (fakeroot staging directory) to compile and install files. Several `DESTDIR`-style variables are pre-exported: `DESTDIR`, `DEST_DIR`, `INSTALLROOT`, `install_root`, `INSTALL_ROOT`.

```sh
build() {
    ./configure --prefix=/usr
    make
    make DESTDIR=$PKG install
}
```

Without `build()`, optional `prebuild()` and `postbuild()` hooks run before and after the auto-detected build system.

### Other recipe files

| File | Purpose |
|---|---|
| `depends` | Dependencies, one per line (`#` for comments) |
| `preinstall` | Script run before the package is built (only during `-i` or `-u`) |
| `postinstall` | Script run after the package is installed or upgraded |
| `.shasum` | Source checksums (auto-generated, regenerate with `apkg -g`) |
| `.files` | Package file list (auto-generated, regenerate with `apkg -k`) |

## Build systems

When no `build()` function is defined, apkg auto-detects the build system by checking for these files in order:

1. **meson.build**: `meson setup` with LTO, PIE, `wrap_mode=nodownload`, `buildtype=plain`
2. **configure**: `./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 prefix variables

See `doc/defaultbuildopts` for the exact flags used by each build system.

### Post-build processing

After compilation, apkg automatically:
- Compresses man pages (man1–man8, 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 kept via `keep_*`)
- Strips ELF binaries (`--strip-all`), shared objects (`--strip-unneeded`), and static archives (`--strip-debug`)

## Triggers

After install or upgrade, apkg can automatically refresh system caches when the package provides relevant files:

- **fontconfig**: `fc-cache -sf`
- **GDK-Pixbuf**: `gdk-pixbuf-query-loaders --update-cache`
- **GIO modules**: `gio-querymodules /usr/lib/gio/modules`
- **GSettings schemas**: `glib-compile-schemas /usr/share/glib-2.0/schemas`
- **GTK2/GTK3 input methods**: `gtk-query-immodules-2.0/3.0 --update-cache`
- **Icon themes**: `gtk-update-icon-cache`
- **udev hardware database**: `udevadm hwdb --update`
- **X font indices**: `mkfontdir` / `mkfontscale`
- **Desktop MIME cache**: `update-desktop-database`
- **Shared MIME database**: `update-mime-database /usr/share/mime`

Run `apkg -t` to trigger these manually for all installed packages.

## Environment variables

### apkg

| Variable | Default | Purpose |
|---|---|---|
| `APKG_REPO` | `$PWD` | Space-separated repo directories (first match wins) |
| `APKG_PACKAGE_DIR` | `$PWD` | Where built `.spm` files are stored |
| `APKG_SOURCE_DIR` | `$PWD` | Source tarball cache directory |
| `APKG_WORK_DIR` | `$PWD` | Build working tree (extraction + fakeroot) |
| `APKG_ROOT` | `/` | Alternative install root |
| `APKG_NOPROMPT` | (unset) | Skip confirmation prompt (for scripting) |
| `APKG_KEEP_WORKDIR` | (unset) | Keep build tree on failure (for debugging) |
| `APKG_ALIAS` | (unset) | Dependency substitution: `real:alias` pairs |
| `APKG_MASK` | (unset) | Packages to skip during `-l` and `-U` |
| `APKG_LOG` | (unset) | Enable build logging |
| `APKG_LOG_DIR` | (unset) | Log file directory (filename: `$name.log`) |

### reposync

| Variable | Format | Purpose |
|---|---|---|
| `REPOSYNC_<name>` | `url\|branch\|path` | Define a git repo to sync |

## Bugs

Issue tracker: [codeberg.org/emmett1/autils/issues](https://codeberg.org/emmett1/autils/issues)

## License

See [LICENSE](./LICENSE).