Bundle a static pdftotext into the binary
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>
This commit is contained in:
@@ -56,6 +56,31 @@ Give it the package path, not `cmd/money/main.go`. Naming the file puts the go
|
||||
tool in file mode: it names the binary after the source file (`main`) and
|
||||
compiles only the files listed, which breaks the moment the package has two.
|
||||
|
||||
That build runs `pdftotext` from `PATH` for the PDF parsers, so the machine
|
||||
needs poppler-utils. To deploy one file with nothing to install alongside it,
|
||||
build with `pdftotext` inside:
|
||||
|
||||
```
|
||||
scripts/build-bundled.sh # → dist/money-linux-amd64
|
||||
scripts/build-bundled.sh arm64 # → dist/money-linux-arm64
|
||||
```
|
||||
|
||||
It needs podman or docker: `pdftotext` is compiled in a container from a
|
||||
checksum-pinned poppler release (`scripts/pdftotext.Containerfile`), as a fully
|
||||
static musl executable with only what text extraction needs, then embedded with
|
||||
`go build -tags bundled`. The result runs on any Linux of that architecture.
|
||||
The first PDF import writes the embedded copy to `~/.cache/money/` (or
|
||||
`$XDG_CACHE_HOME/money/`) and runs it from there; `money config` says which
|
||||
`pdftotext` is in use. Only Linux on amd64 and arm64 is offered — elsewhere,
|
||||
install poppler-utils.
|
||||
|
||||
Building arm64 from an x86 machine runs the container under emulation, so the
|
||||
host needs qemu-user-static and the first build is slow; the executable is then
|
||||
cached under `internal/parser/bundled/` and later builds only rebuild money.
|
||||
|
||||
Poppler is GPL, so a bundled binary is GPL-licensed as a whole. That matters
|
||||
only if you hand the binary to someone else.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
@@ -672,7 +697,8 @@ parser = "traderepublic"
|
||||
|
||||
The two PDF parsers shell out to `pdftotext -layout` (poppler-utils), exactly
|
||||
as the Python versions did; its layout reconstruction is what makes the
|
||||
column-based parsing work.
|
||||
column-based parsing work. A build made with `scripts/build-bundled.sh`
|
||||
carries its own copy instead (see Install).
|
||||
|
||||
Amount parsing is shared and deliberately tolerant: `1.234,56`, `-45.20`,
|
||||
`45,20-`, `(45.20)` and `45.20 EUR` all work, whichever parser reads them.
|
||||
|
||||
Reference in New Issue
Block a user