mirror of
https://github.com/mudler/LocalAI.git
synced 2026-07-30 18:09:05 -04:00
package.sh already left libcuda.so* and libnvidia-* to the host when copying, because the driver has to match the kernel module on whatever host runs the image, but the validation gate had no matching exemption. With BUILD_TYPE=cublas ggml is static and links CUDA::cuda_driver, so grpc-server carries DT_NEEDED libcuda.so.1 and the gate would have rejected the very absence the copy loop created, failing every cublas build in CI. One regex now feeds both. Building a control for that found a second defect: ld.so --list refuses to trace an object with an unresolvable dependency at all, exiting 127 without emitting a per-library line, so the "=> not found" rule was dead code and no exemption could have applied to it. The gate now traces with LD_TRACE_LOADED_OBJECTS and LD_LIBRARY_PATH, which reports the missing name and exits 0, and which is also what run.sh does at run time. Adds a layout assertion so a future move of the loader into lib/ fails the build instead of shipping a package that resolves bundled: models into lib/assets and finds no ggml CPU backend, and records for Task 16 that the Darwin script must not be a straight copy of privacy-filter-darwin.sh, which never calls package.sh and would silently drop assets/. Assisted-by: Claude:claude-opus-5 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
59 lines
3.0 KiB
Bash
Executable File
59 lines
3.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# Entry point for the audio-cpp backend image and for BACKEND_BINARY mode.
|
|
#
|
|
# The image's final stage is FROM scratch, so the package root is / and there is
|
|
# no system loader, no system libc and no fallback library path. Everything the
|
|
# process opens has to be inside the package, and it has to be findable by the
|
|
# two mechanisms that actually do the finding: the dynamic linker, and
|
|
# audio.cpp's own directory scans.
|
|
set -e
|
|
|
|
CURDIR=$(dirname "$(realpath "$0")")
|
|
|
|
if [ "$(uname -s)" = "Darwin" ]; then
|
|
export DYLD_LIBRARY_PATH="$CURDIR/lib:$CURDIR:$DYLD_LIBRARY_PATH"
|
|
exec "$CURDIR/grpc-server" "$@"
|
|
fi
|
|
|
|
# $CURDIR is on the path as well as $CURDIR/lib: the ggml shared objects the
|
|
# CPU-all-variants build produces sit in the package root, next to the binary,
|
|
# not in lib/. See the comment below for why they cannot live in lib/.
|
|
export LD_LIBRARY_PATH="$CURDIR/lib:$CURDIR:$LD_LIBRARY_PATH"
|
|
|
|
# THE BUNDLED LOADER IS AT THE PACKAGE ROOT, NOT AT lib/ld.so. DO NOT MOVE IT.
|
|
#
|
|
# Exec'ing the loader is what pins the bundled glibc to the matching ld.so, and
|
|
# every other C++ backend here does it. The cost is that /proc/self/exe then
|
|
# names the LOADER rather than grpc-server, and this backend has two consumers
|
|
# of /proc/self/exe that both have to land on the package root:
|
|
#
|
|
# - ggml's backend registry DISCOVERS the per-microarch libggml-cpu-*.so by
|
|
# scanning dirname(/proc/self/exe) and the current directory. Those files
|
|
# are dlopened, never linked, so no library path and no RUNPATH reaches
|
|
# them: they have to be in a directory ggml scans.
|
|
# - resolve_model_path() turns "bundled:<name>" into
|
|
# dirname(/proc/self/exe)/assets/<name>, which is how the bundled
|
|
# silero_vad and marblenet_vad models resolve with nothing downloaded.
|
|
#
|
|
# backend/cpp/llama-cpp/package.sh answers the first of these by keeping
|
|
# lib/ld.so and moving the ggml objects INTO lib/. That does not generalise
|
|
# here, because it would also drag assets/ into lib/ to keep the second
|
|
# consumer working. Putting the loader in the package root instead makes
|
|
# dirname(/proc/self/exe) the package root, so the binary, the ggml objects and
|
|
# assets/ all sit in the one directory that all three mechanisms agree on.
|
|
#
|
|
# The ggml half has a second chance that the bundled: half does not: LocalAI
|
|
# sets the backend process cwd to the directory holding run.sh
|
|
# (pkg/model/process.go), so ggml's fs::current_path() fallback would find the
|
|
# objects in normal operation whatever the loader's placement. That fallback is
|
|
# worth little here. It holds only for the launcher that sets that cwd, it is
|
|
# gone the moment anyone runs the binary by hand or through a wrapper that
|
|
# chdirs, and resolve_model_path has no equivalent, which would leave the only
|
|
# zero-download path in this backend resting on it. Rooting the loader is the
|
|
# one layout where all three mechanisms agree without depending on the cwd.
|
|
if [ -f "$CURDIR/ld.so" ]; then
|
|
exec "$CURDIR/ld.so" "$CURDIR/grpc-server" "$@"
|
|
fi
|
|
|
|
exec "$CURDIR/grpc-server" "$@"
|