aya_rustc_llvm_proxy/lib.rs
1#![deny(warnings)]
2#![allow(
3 non_snake_case,
4 unused_imports,
5 unused_macros,
6 deprecated,
7 clippy::missing_safety_doc
8)]
9
10//! This is a **fork** of the [rustc-llvm-proxy](https://github.com/denzp/rustc-llvm-proxy) crate.
11//!
12//! Dynamically proxy LLVM calls into Rust own shared library! 🎉
13//!
14//! ## Use cases
15//! Normally there is no much need for the crate, except a couple of exotic cases:
16//!
17//! * Your crate is some kind build process helper that leverages LLVM (e.g. [bpf-linker](https://github.com/aya-rs/bpf-linker)),
18//! * Your crate needs to stay up to date with Rust LLVM version (again [bpf-linker](https://github.com/aya-rs/bpf-linker)),
19//! * You would prefer not to have dependencies on host LLVM libs (as always [bpf-linker](https://github.com/aya-rs/bpf-linker)).
20//!
21//! ## Usage
22//! First, you need to make sure no other crate links your binary against system LLVM library.
23//! In case you are using `llvm-sys`, this can be achieved with a special feature:
24//!
25//! ``` toml
26//! [dependencies.llvm-sys]
27//! version = "70"
28//! features = ["no-llvm-linking"]
29//! ```
30//!
31//! Then all you need to do is to include the crate into your project:
32//!
33//! ``` toml
34//! [dependencies]
35//! rustc-llvm-proxy = "0.4"
36//! ```
37//!
38//! ``` rust
39//! extern crate aya_rustc_llvm_proxy;
40//! ```
41
42use libloading::Library;
43
44pub mod init;
45
46static SHARED_LIB: std::sync::LazyLock<Library> = std::sync::LazyLock::new(|| {
47 for (var, is_bin) in [
48 ("LD_LIBRARY_PATH", false),
49 ("DYLD_FALLBACK_LIBRARY_PATH", false),
50 ("PATH", true),
51 ] {
52 let Some(unparsed) = std::env::var_os(var) else {
53 continue;
54 };
55 let paths = std::env::split_paths(&unparsed);
56 for mut path in paths {
57 if is_bin {
58 path.pop();
59 path.push("lib");
60 }
61 let files = match path.read_dir() {
62 Ok(files) => files,
63 Err(err) => {
64 eprintln!("unable to read dir {}: {}", path.display(), err);
65 continue;
66 }
67 };
68 for (i, file) in files.enumerate() {
69 let file = match file {
70 Ok(file) => file,
71 Err(err) => {
72 eprintln!(
73 "unable to read dir entry {} in {}: {}",
74 i,
75 path.display(),
76 err
77 );
78 continue;
79 }
80 };
81 let path = file.path();
82 let Some(stem) = path.file_stem() else {
83 continue;
84 };
85 let Some(stem) = stem.to_str() else { continue };
86 if stem.starts_with("libLLVM") {
87 match unsafe { Library::new(&path) } {
88 Ok(library) => return library,
89 Err(error) => {
90 eprintln!(
91 "unable to open LLVM shared lib {}: {}",
92 path.display(),
93 error
94 );
95 continue;
96 }
97 }
98 }
99 }
100 }
101 }
102 panic!("unable to find LLVM shared lib")
103});
104
105/// LLVM C-API symbols with dynamic resolving.
106pub mod proxy {
107 use super::SHARED_LIB;
108
109 include!(concat!(env!("OUT_DIR"), "/llvm_gen.rs"));
110}