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.1Solution
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