cpu: support GGML_CPU_ALL_VARIANTS with static linking
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
- Keep the existing
ggml_add_cpu_backend_variantcompilation of the backend per arch level. - 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:Undefined references to ggml-base stay external, so all variants share the one base library.ld -r --whole-archive libggml-cpu-haswell.a -o cpu-haswell.o objcopy --keep-global-symbols=<init,score renamed> cpu-haswell.o - In
ggml-backend-reg, when built this way, iterate the compiled-in variants, call eachscore(), and register the best-scoring one — the same selection the DL path already does inload_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.
Source: ggml-org/ggml