Skip to content

No CCACHE_ export reaches a cross compile, because crossdirect execs with a literal environment

scope: generic · severity: trap · confidence: proven · subsystem: build

Symptom — you export CCACHE_MAXSIZE, CCACHE_DIR or CCACHE_BASEDIR before a package build, the build runs normally, and the setting has no effect at all. No error, no warning, nothing in the log. Setting it in pmbootstrap’s environment, in porthole’s config, or in the APKBUILD makes no difference either.

crossdirect is the shim pmbootstrap puts in front of the compiler in a cross build. It does not add to the environment it was called with – it replaces it, with three entries:

// crossdirect.c:114
char *env[] = { "LD_PRELOAD=",
"LD_LIBRARY_PATH=/native/lib:/native/usr/lib",
"CCACHE_PATH=/native/usr/bin",
NULL };
...
// crossdirect.c:135
if (execve(newExecutable, newargv, env) == -1) {

execve with an explicit env argument discards the caller’s environment entirely. Those three strings are the whole environment the cross compiler – and therefore ccache – is given. Nothing porthole exports, nothing pmbootstrap exports, and nothing an APKBUILD exports is present by the time ccache reads its settings.

ccache’s own config file, inside the cache directory, which is what ccache -M <size> writes. It has to be run in the chroot that owns that arch’s cache:

porthole build ccache --max 25G

That is why the verb exists rather than a documented environment variable, and why porthole sandbox up sets the ceiling rather than exporting one. lib/porthole_cmd_build.py::_ccache is the implementation.

What this does not cover

Section: What this does not cover

The link half. A link never reaches this code at all: crossdirect re-executes it as /usr/bin/<name>, a target-arch ELF that binfmt hands to qemu-<arch>-static, several lines earlier and before this environment is ever built. Deliberate, to dodge a broken cross-ld. That is a different note: crossdirect-hands-the-linker-to-qemu-on-purpose.

So the rule to carry: for a cross build, a compiler setting is a file, not a variable. If a knob has no config file, there is no way to set it from outside, and the answer is usually the APKBUILD’s own flags rather than the environment.

Related: two-pmbootstrap-builds-destroy-each-other for what else is true of the buildroot these caches live in.