#1608·ggml

cpu: support GGML_CPU_ALL_VARIANTS with static linking

Author: thewh1teagleCreated Aug 27, 2026Updated Aug 27, 2026

GGML_CPU_ALL_VARIANTS currently requires GGML_BACKEND_DL, so runtime CPU-variant selection is only available when backends ship as shared modules. Projects that distribute a single static binary can't use it, and are forced to choose between -march=native-style builds that crash on older CPUs (SIGILL on pre-AVX2 machines) and a conservative baseline that leaves AVX2/AVX512 performance on the table for everyone.

Static all-variants looks feasible without touching any kernels, because each CPU variant only needs to export two symbols — ggml_backend_init and ggml_backend_score, the same interface the DL loader consumes:

Proposal

  1. Keep the existing ggml_add_cpu_backend_variant compilation of the backend per arch level.
  2. For static builds, partially link each variant into a single relocatable object and localize all symbols except the two entry points, renamed per variant (e.g. ggml_backend_cpu_haswell_init / _score). Roughly:
    ld -r --whole-archive libggml-cpu-haswell.a -o cpu-haswell.o
    objcopy --keep-global-symbols=<init,score renamed> cpu-haswell.o
    Undefined references to ggml-base stay external, so all variants share the one base library.
  3. In ggml-backend-reg, when built this way, iterate the compiled-in variants, call each score(), and register the best-scoring one — the same selection the DL path already does in load_best.

ELF and Mach-O make step 2 trivial with binutils; COFF/MSVC is the fiddly part (llvm-objcopy), which could land as a follow-up with the feature initially gated to GCC/Clang toolchains.