“libomp.so: Cannot Open Shared Object File” Running llama.cpp
9 min read · updated August 11, 2026
error while loading shared libraries: libomp.so: cannot open shared object file: No such file or directory — printed before any of your code runs, by the dynamic loader, about a library the binary was linked against but cannot find.
The error, and what stage it comes from
Nothing in llama.cpp produced this message. It comes from ld.so, the dynamic linker, at process start. The executable records the shared objects it needs in its ELF headers; the loader resolves each one against the library search path before handing control to main. A name it cannot resolve stops the process immediately, which is why you see no banner, no model load line and no usage text.
Two facts follow. First, the build succeeded — linking at build time found the library, so this is a runtime environment that differs from the build environment. Second, no llama.cpp flag or model change can affect it, because nothing in llama.cpp has run.
Confirm exactly what is missing before installing anything:
ldd ./build/bin/llama-cli | grep -i -e "not found" -e omp # example output # libgomp.so.1 => not found # libomp.so.5 => /usr/lib/x86_64-linux-gnu/libomp.so.5
ldd lists every dependency and marks the unresolvable ones. Read the exact soname it prints — libomp.so, libomp.so.5 and libgomp.so.1 are three different files from two different projects, and that distinction is the whole of this page.
libomp or libgomp: they are not the same package
llama.cpp uses OpenMP for CPU threading. OpenMP is a specification, and each compiler ships its own runtime implementation of it:
- GCC links against
libgomp.so.1, GNU’s OpenMP runtime. It normally arrives with the compiler, but on a minimal runtime image it is a separate package. - Clang and LLVM link against
libomp.so, the LLVM OpenMP runtime, which is packaged separately from clang on most distributions. This is the common case for anyone building with clang, and for many prebuilt binaries. - Intel’s compilers use
libiomp5.so, which is binary-compatible with the LLVM runtime and ships inside oneAPI and inside some PyTorch and MKL distributions.
Installing the wrong one is the single most common wasted step here: a binary asking for libomp.so.5 is not satisfied by installing libgomp1, and the error repeats verbatim. Match the soname ldd printed.
A related trap: having the library present but not on the search path. If the file exists somewhere the loader does not look — a conda environment, a manual /opt install, a oneAPI tree — the fix is ldconfig with a config file in /etc/ld.so.conf.d/, not an exported LD_LIBRARY_PATH. The exported variable works for one shell and then confuses the next person, and it also overrides library resolution for every other program you launch from that shell.
The package name per distribution
# Debian / Ubuntu sudo apt-get update sudo apt-get install -y libgomp1 # GCC runtime (libgomp.so.1) sudo apt-get install -y libomp5 libomp-dev # LLVM runtime (libomp.so.5, libomp.so) # Fedora / RHEL / Rocky / Alma sudo dnf install -y libgomp # GCC runtime sudo dnf install -y libomp libomp-devel # LLVM runtime # Arch sudo pacman -S openmp # LLVM runtime; libgomp ships with gcc # openSUSE sudo zypper install libgomp1 libomp-devel # Alpine (musl) apk add libgomp # GCC runtime apk add libomp # LLVM runtime
The -dev or -devel package provides the unversioned libomp.so symlink used at link time; the runtime package provides the versioned file used at load time. If the missing name has no version suffix, you need the development package even though you are only trying to run something.
libomp.dylib rather than an ELF loader message, and the library comes from Homebrew’s libomp formula. Apple’s bundled clang does not ship an OpenMP runtime, which is why a Homebrew-built binary can need one that the system does not have.Containers, wheels and the slim-image trap
Most instances of this error are a multi-stage Docker build. The build stage has a full toolchain, so linking succeeds; the runtime stage is a slim or distroless base with no compiler and therefore no OpenMP runtime, and the copied binary cannot start. The fix is one line in the runtime stage:
FROM debian:bookworm-slim RUN apt-get update \ && apt-get install -y --no-install-recommends libgomp1 \ && rm -rf /var/lib/apt/lists/* COPY --from=build /src/build/bin/llama-cli /usr/local/bin/
The same thing happens through Python. Importing llama_cpp loads a compiled extension, and a missing OpenMP runtime surfaces as a failure to load a shared library at import time rather than at process start. The remedy is identical — install the runtime package in the image — and it is unrelated to a wheel that fails to build, which happens earlier and for different reasons.
Hosted notebook environments produce a third variant, where the base image has the GCC runtime but a wheel was built against LLVM’s. Both can be installed side by side; they are different files and do not conflict at the package-manager level, though loading two OpenMP runtimes into one process can cause oversubscription and, in some combinations, a warning about multiple initialisations.
Removing the dependency instead
If you control the build and want a binary that does not need any of this — a container image, a distributable, an air-gapped machine — there are two routes.
- Build with OpenMP disabled:
cmake -B build -DGGML_OPENMP=OFF. llama.cpp falls back to its own thread pool. Threading behaviour changes and you may want to set-texplicitly, but the dependency is gone. - Or link statically.
-DBUILD_SHARED_LIBS=OFFplus-static-libgccand the compiler’s static OpenMP option folds the runtime into the binary. The result is larger and must be rebuilt to pick up a runtime security fix, which is the trade. - Verify before shipping:
lddon the final binary in the final image, not on the build host. That check takes a second and catches every instance of this error before a user sees it.
Neither route is required for a workstation. On a machine where you already have a compiler, installing the matching runtime package is the right answer, and the only real skill is reading which one ldd asked for.
One thing to watch after the library is in place: OpenMP defaults to one thread per logical core, and llama.cpp also takes a thread count of its own. If another OpenMP-using library is loaded in the same process — PyTorch and NumPy both are — you can end up with several runtimes each spawning a full complement of threads, and the resulting oversubscription makes inference slower than a single-threaded run. OMP_NUM_THREADS caps it globally, and llama.cpp’s -t should generally be set to the number of physical cores rather than logical ones, because the memory-bound part of generation gains nothing from hyperthreads. A newly working binary that is mysteriously slow is usually this rather than a model problem.