The PDF parsers shell out to pdftotext, so every machine running money needed poppler-utils installed. scripts/build-bundled.sh now builds a deployable binary that carries its own: pdftotext is compiled in a container from a checksum-pinned poppler release as a fully static musl executable, then embedded with `go build -tags bundled`. The result is one file that runs on any Linux of that architecture with nothing installed alongside it. It is still the real pdftotext, run as a subprocess. Linking poppler through cgo would have cost the pure-Go build, and its C++ text API is not guaranteed to space columns the way pdftotext -layout does, which is what the parsers were tuned on. Only what text extraction needs is compiled in -- no fontconfig, cairo or image codecs -- and its output is byte-identical to a full distro build on the same PDF. At runtime the embedded copy is written to the user cache directory, not /tmp, which servers often mount noexec. It is named by content hash, so a newer build never runs an older copy, and verified before reuse, so a write cut short by a killed process is replaced rather than trusted. `money config` says which pdftotext is in use. The tag is opt-in: plain go build and go test never need the 5 MB executable, which is gitignored rather than committed. Building with the tag for anything but linux/amd64 or linux/arm64 fails with a message saying so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
1.3 KiB
Bash
Executable File
41 lines
1.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# Builds money with a static pdftotext inside it: one file to copy to a server,
|
|
# with nothing to install there — not even poppler-utils.
|
|
#
|
|
# scripts/build-bundled.sh # linux, this machine's architecture
|
|
# scripts/build-bundled.sh arm64 # linux/arm64 (podman/docker need qemu)
|
|
#
|
|
# pdftotext is built in a container from a checksum-pinned poppler release
|
|
# (scripts/pdftotext.Containerfile) and cached under internal/parser/bundled/,
|
|
# so later runs only rebuild money. Delete that file to rebuild it.
|
|
set -eu
|
|
cd "$(dirname "$0")/.."
|
|
|
|
arch=${1:-$(go env GOARCH)}
|
|
case $arch in
|
|
amd64 | arm64) ;;
|
|
*)
|
|
echo "build-bundled: no static pdftotext for linux/$arch; use amd64 or arm64" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
bin=internal/parser/bundled/pdftotext-linux-$arch
|
|
if [ ! -f "$bin" ] || [ scripts/pdftotext.Containerfile -nt "$bin" ]; then
|
|
engine=$(command -v podman || command -v docker) || {
|
|
echo "build-bundled: building pdftotext needs podman or docker" >&2
|
|
exit 1
|
|
}
|
|
out=$(mktemp -d)
|
|
trap 'rm -rf "$out"' EXIT
|
|
"$engine" build --platform "linux/$arch" -f scripts/pdftotext.Containerfile \
|
|
--output "type=local,dest=$out" scripts
|
|
mkdir -p internal/parser/bundled
|
|
mv "$out/pdftotext" "$bin"
|
|
fi
|
|
|
|
mkdir -p dist
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=$arch \
|
|
go build -tags bundled -trimpath -o "dist/money-linux-$arch" ./cmd/money
|
|
echo "dist/money-linux-$arch"
|