Expand description
macOS flat-package (.pkg) builder — product archives on any OS.
build writes the same shape productbuild emits: a xar archive
holding a Distribution script plus a <name>.pkg/ component directory
with PackageInfo, Bom, a gzipped odc-cpio Payload, and (with
PkgSpec::scripts) a Scripts archive in the same format. Every layer
was pinned against Apple tooling on macOS 26.5 (pkgbuild/productbuild
output dissected byte-by-byte; results verified with pkgutil --expand-full, lsbom, and installer).
Lower-level pieces are public for reuse and testing: write_xar
(xar archives with nested directories) and write_bom (Bill of
Materials over a staged tree).
Spike outcomes the implementation rests on:
- xar:
apple-xar0.20 has no turn-key writer, but its primitives compose:TableOfContents/File/FileDataare public withto_xml(),ChecksumType::digest_dataprovides digests, andXarHeaderderives scrollIOwrite. The only wrinkle is thatTableOfContents’s inner field is private with no constructor, so we bootstrap one by parsing a minimal template TOC viafrom_readerand mutating it through itsDerefMut<Target = XarToC>impl. No hand-rolled writer needed. - BOM:
apple-bom0.3’s shippedBomBuilderis unusable — itsbuild_bom()panics unconditionally, and beneath that lie a dozen more writer bugs (wrong checksum algorithm, wrong B-tree order, missing free list, …; seebom_builder.rsfor the catalog). Bounded fallback taken:bom_builderports the assembly on top of apple-bom’s publicformattypes with those fixes; the output matches bothmkbomand pkgbuild’s embeddedBomunderlsbom -p fmugsc(paths, modes, uid, gid, size, cksum). Per-file modes must include the file-type bits (e.g.0o100755). - cpio: the Payload is odc/ASCII cpio (magic
070707), hand-rolled here because the format is a 76-byte octal header and pkgbuild’s conventions (sequential inodes, dir nlink = 2 + children, zero pad to a 512-byte boundary) need exact control no crate offered.
Structs§
- DirSpec
- A payload directory declared explicitly, to give it a mode or to ship it
with nothing under it. Directories only implied by file dests are
0o755. - File
Spec - A payload file:
srcon disk (already resolved to a real path),destthe/-separated path relative to the install location. - PkgSpec
- Everything needed to author one product archive. Deliberately independent of the embala config types so the crate is usable on its own.
- XarEntry
- An entry to store in a xar archive.
Enums§
Functions§
- build
- Build the product-archive
.pkgdescribed byspecatout(parent dirs are created). Output is deterministic: fixed timestamps everywhere (xar TOC, cpio, gzip) and sorted payload entries. - validate
- Check
specwithout touching the filesystem: dests are relative and unique, no file sits where a directory must be, and modes are permission bits only.buildruns this first; it is public so callers can reject a bad layout before building anything. - write_
bom - Build a BOM over the file tree rooted at
root, recordinguid:gidas the owner of every entry (pkgbuild’s convention is0:0, root:wheel). - write_
xar - Write a xar archive holding
entries(files and directories).