SoLo permite a binarios estáticos de Linux cargar los drivers gráficos del host
El proyecto añade un cargador ELF y un puente ABI de glibc sobre musl para que un ejecutable estático use los drivers Vulkan u OpenGL del sistema sin contenedores ni una segunda libc.
SoLo es un cargador de bibliotecas compartidas para binarios estáticos de Linux. El proyecto, publicado en GitHub, permite que un ejecutable enlazado con musl cargue en tiempo de ejecución drivers de GPU del sistema enlazados con glibc, como los de Vulkan y OpenGL. Sigues teniendo un único fichero estático, sin contenedor, sin AppImage y sin una segunda libc dentro del proceso.
El problema es conocido. Los binarios estáticos son cómodos: un archivo, sin dependencias. Pero cuando necesitan GPU, los drivers llegan como objetos compartidos del host, normalmente construidos contra glibc, y un binario musl estático no puede hacer dlopen() de ellos. SoLo cruza esa frontera con un cargador ELF propio para x86-64 y aarch64 y un puente de ABI de glibc sobre musl.
No es un vkCreateInstance de juguete. El repositorio incluye una prueba Vulkan completa: un ejecutable estático carga el driver sin modificar del host, ejecuta un shader de cómputo y escribe el resultado en un PNG. Probado en GPUs AMD con radv y radeonsi, Intel y NVIDIA bajo Linux, en Apple M1 con Asahi Linux, en Android con Termux y en WSL con el driver dzn de Mesa sobre Direct3D 12.
Qué hay dentro
elf_loader.cpp mapea segmentos ELF, recorre DT_NEEDED, resuelve símbolos versionados, aplica relocations de x86-64, soporta TLS y TLSDESC, materializa IFUNCs, aplica RELRO y ejecuta inicializadores. Las dependencias que también son DSOs ELF se cargan de forma recursiva. glibc no se carga: llamadas como malloc@GLIBC_2.2.5 las resuelve glibc_shim.cpp con adaptadores ABI sobre el runtime musl que ya está en el proceso. Las funciones no soportadas tienen stubs que fallan de forma explícita, con el símbolo y la versión exactos, en vez de corromper el proceso en silencio.
La biblioteca tampoco duplica los objetos de sincronización: un pthread_mutex_t que crea el driver se usa tal cual, porque musl los dimensiona conforme a la ABI glibc de cada arquitectura.
Antes de cargar un DSO desde disco, SoLo consulta su registro de proveedores estáticos. Así una aplicación puede satisfacer una dependencia —Wayland, por ejemplo— con funciones ya enlazadas en el ejecutable. LD_LIBRARY_PATH se respeta para bibliotecas fuera de los directorios estándar, salvo en modo de ejecución segura (AT_SECURE), donde el entorno se ignora igual que hace ld.so. LD_TRACE_LOADED_OBJECTS=1 imprime cada objeto en el formato de ldd, incluidos los nombres servidos sin mapeo.
Uso y verificación
El proyecto publica un binario precompilado del demo Vulkan para x86-64 y aarch64. El comando descubre el ICD de Vulkan instalado por la distribución y genera una imagen RGBA de 512×512. Se puede forzar un driver con --driver; los nombres de los manifiestos ICD varían entre distribuciones. Para comprobar que no hay enlace dinámico, el README propone readelf -lW y readelf -dW: no debe aparecer INTERP ni sección dinámica.
También se puede usar como biblioteca. La compilación por defecto genera libdlfcn.a y el enlace simbólico ./dlfcn. Incluyendo lib/dlfcn.h y enlazando el archivo estático en una aplicación musl, las llamadas normales a dlopen() y dlsym() se redirigen a SoLo. No hay llamada de arranque. El TLS estático que piden los invitados, incluido initial-exec, sale de un thread_local pad que la biblioteca enlaza en la aplicación.
La integración continua del repositorio va más allá: en cada commit carga las bibliotecas compartidas de los 1.000 paquetes Debian más instalados —más de 2.100 objetos del host— en x86-64 y aarch64.
Para quien despliegue software gráfico en Linux, la utilidad es concreta: menos capas para llegar al driver. Queda por ver si el puente cubre los casos reales de la ABI glibc que usan drivers propietarios, no solo los de Mesa.

