How to fix Rust clang crate: symbol lookup error: undefined symbol: LLVMInitializeAArch64TargetInfo
Problem
When trying to run a Rust executable using the clang
crate, you see an error message such as
example.txt
$ cargo run clangtest.cpp
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/asx clangtest.cpp`
target/debug/clangtest: symbol lookup error: /lib/x86_64-linux-gnu/libclang-19.so.19: undefined symbol: LLVMInitializeAArch64TargetInfo, version LLVM_19.1
Solution
This error occurs because Cargo links the wrong libLLVM
. A common cause for this is that you have installed rocm
(AMD’s compute stack) which comes with its own libLLVM
that is incompatible with the one used by libclang
.
In order to fix that, add build.rs
build.rs
use std::{env, path::{Path, PathBuf}};
fn main() {
// Allow override via environment variable for flexibility.
// Example: LLVM19_LIB_DIR=/custom/llvm19/lib cargo build
let llvm_dir = env::var("LLVM19_LIB_DIR").unwrap_or_else(|_| "/usr/lib/llvm-19/lib".to_string());
let llvm_so_candidates = [
"libLLVM.so", // soname symlink
"libLLVM-19.so", // alternative naming pattern
"libLLVM.so.19", // versioned pattern
"libLLVM.so.19.1", // specific minor version
];
let dir_path = Path::new(&llvm_dir);
if !dir_path.is_dir() {
panic!("LLVM directory '{llvm_dir}' does not exist. Set LLVM19_LIB_DIR to the correct path.");
}
// Try to locate an actual existing lib file we can pass explicitly to the linker to avoid picking one from elsewhere (e.g., /opt/amdgpu)
let chosen_lib: Option<PathBuf> = llvm_so_candidates.iter()
.map(|name| dir_path.join(name))
.find(|p| p.exists());
if let Some(lib_path) = chosen_lib {
let lib_dir = lib_path.parent().unwrap();
// Ensure our desired directory is searched first
println!("cargo:rustc-link-search=native={}", lib_dir.display());
// We still emit the generic link-lib to satisfy symbols possibly split across components.
println!("cargo:rustc-link-lib=dylib=LLVM");
// Force the exact library by passing its absolute path as a linker arg (placed after objects so it is used for resolution)
println!("cargo:rustc-link-arg={}", lib_path.display());
// Add an rpath so the runtime loader also prefers this directory.
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display());
// Optionally prefer our path by adding it at RUNPATH as well (GNU ld treats rpath/runpath subtly; using rpath here is sufficient for most systems)
println!("cargo:rerun-if-env-changed=LLVM19_LIB_DIR");
} else {
panic!("Could not locate any libLLVM* candidate in {llvm_dir}. Candidates tried: {:?}", llvm_so_candidates);
}
}
Also you need to configure Cargo.toml
to use that build script:
Cargo.toml
[package]
build = "build.rs"
Check out similar posts by category:
Rust
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow