Wie man behebt: Rust clang crate: symbol lookup error: undefined symbol: LLVMInitializeAArch64TargetInfo

Problem

Beim Versuch, eine Rust-Executable mit dem clang-Crate auszuführen, sehen Sie eine Fehlermeldung wie

clang_symbol_lookup_error.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

Lösung

Dieser Fehler tritt auf, weil Cargo das falsche libLLVM linkt. Eine häufige Ursache dafür ist, dass Sie rocm (AMDs Compute-Stack) installiert haben, das mit seinem eigenen libLLVM kommt, das inkompatibel mit dem von libclang verwendeten ist.

Um dies zu beheben, fügen Sie build.rs hinzu

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);
    }
}

Außerdem müssen Sie Cargo.toml konfigurieren, um dieses Build-Skript zu verwenden:

Cargo.toml
[package]
build = "build.rs"

Check out similar posts by category: Rust