cubecl_hip_sys/
dynamic.rs1use libloading::{Library, Symbol};
2use std::{env, path::PathBuf, sync::OnceLock};
3
4struct Libraries {
5 hip: Library,
6 hiprtc: Library,
7}
8
9static LIBRARIES: OnceLock<Result<Libraries, String>> = OnceLock::new();
10
11pub fn is_available() -> bool {
13 libraries().is_ok()
14}
15
16pub(crate) unsafe fn load<T: Copy>(name: &[u8]) -> T {
22 let libraries = libraries()
23 .as_ref()
24 .unwrap_or_else(|error| panic!("{error}"));
25 let library = if name.starts_with(b"hiprtc") {
26 &libraries.hiprtc
27 } else {
28 &libraries.hip
29 };
30
31 let symbol: Symbol<'_, T> = unsafe { library.get(name) }.unwrap_or_else(|error| {
32 let symbol_name = name.strip_suffix(&[0]).unwrap_or(name);
33 let symbol = String::from_utf8_lossy(symbol_name);
34 panic!("HIP symbol `{symbol}` is unavailable: {error}");
35 });
36 *symbol
37}
38
39fn libraries() -> &'static Result<Libraries, String> {
40 LIBRARIES.get_or_init(|| unsafe { load_libraries() })
41}
42
43unsafe fn load_libraries() -> Result<Libraries, String> {
44 let search_paths = search_paths();
45 let hip = load_library("amdhip64", &search_paths)?;
46 let hiprtc = load_library("hiprtc", &search_paths)?;
47 Ok(Libraries { hip, hiprtc })
48}
49
50fn search_paths() -> Vec<PathBuf> {
51 ["ROCM_PATH", "HIP_PATH"]
52 .into_iter()
53 .filter_map(env::var_os)
54 .flat_map(|path| {
55 let path = PathBuf::from(path);
56 [path.join("lib"), path]
57 })
58 .collect()
59}
60
61unsafe fn load_library(name: &str, search_paths: &[PathBuf]) -> Result<Library, String> {
62 let names = library_names(name);
63 let mut errors = Vec::new();
64
65 for path in search_paths {
66 for library_name in &names {
67 let candidate = path.join(library_name);
68 match unsafe { Library::new(&candidate) } {
69 Ok(library) => return Ok(library),
70 Err(error) => errors.push(format!("{}: {error}", candidate.display())),
71 }
72 }
73 }
74
75 for library_name in &names {
76 match unsafe { Library::new(library_name) } {
77 Ok(library) => return Ok(library),
78 Err(error) => errors.push(format!("{library_name}: {error}")),
79 }
80 }
81
82 Err(format!(
83 "Could not load HIP library `{name}`. Install ROCm or set ROCM_PATH/HIP_PATH.\n{}",
84 errors.join("\n")
85 ))
86}
87
88fn library_names(name: &str) -> Vec<String> {
89 if cfg!(target_os = "windows") {
90 vec![format!("{name}.dll")]
91 } else if cfg!(target_os = "macos") {
92 vec![format!("lib{name}.dylib")]
93 } else {
94 vec![
95 format!("lib{name}.so"),
96 format!("lib{name}.so.1"),
97 format!("lib{name}.so.0"),
98 ]
99 }
100}