Проблема
Під час спроби запустити Rust-виконуваний файл, що використовує крейт clang, ви бачите таке повідомлення про помилку:
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Рішення
Ця помилка виникає через те, що Cargo компонує неправильну libLLVM. Поширеною причиною є те, що у вас встановлено rocm (обчислювальний стек AMD), який постачається зі власною libLLVM, несумісною з тією, що використовується libclang.
Щоб це виправити, додайте build.rs
build.rs
use std::{env, path::{Path, PathBuf}};
fn main() {
// Дозволяємо перевизначення через змінну середовища для гнучкості.
// Приклад: 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-симлінк
"libLLVM-19.so", // альтернативний шаблон найменування
"libLLVM.so.19", // версіонований шаблон
"libLLVM.so.19.1", // конкретна мінорна версія
];
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.");
}
// Намагаємося знайти реальний існуючий файл бібліотеки, який можна явно передати лінкеру, щоб уникнути вибору з іншого місця (наприклад, /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();
// Забезпечуємо, щоб наш бажаний каталог шукався першим
println!("cargo:rustc-link-search=native={}", lib_dir.display());
// Ми все одно випускаємо загальну link-lib, щоб задовольнити символи, які можуть бути розподілені між компонентами.
println!("cargo:rustc-link-lib=dylib=LLVM");
// Примусово вказуємо точну бібліотеку, передаючи її абсолютний шлях як аргумент лінкера (розміщується після об'єктів, тому використовується для розв'язання символів)
println!("cargo:rustc-link-arg={}", lib_path.display());
// Додаємо rpath, щоб завантажувач під час виконання також віддавав перевагу цьому каталогу.
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display());
// За бажанням віддаємо перевагу нашому шляху, також додаючи його до RUNPATH (GNU ld трактує rpath/runpath по-різному; використання rpath тут достатньо для більшості систем)
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);
}
}Також потрібно налаштувати Cargo.toml для використання цього скрипта збірки:
Cargo.toml
[package]
build = "build.rs"
Дивіться схожі статті за категоріями:
Rust
Якщо ця стаття допомогла вам, будь ласка, подумайте про те, щоб купити мені каву або зробити пожертву через PayPal на підтримку досліджень та публікації нових статей на TechOverflow