-
Notifications
You must be signed in to change notification settings - Fork 68
/
Copy pathstatic.rs
146 lines (127 loc) · 4.54 KB
/
static.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: Apache-2.0
use std::path::{Path, PathBuf};
use glob::Pattern;
use super::common;
//================================================
// Searching
//================================================
/// Clang static libraries required to link to `libclang` 3.5 and later.
const CLANG_LIBRARIES: &[&str] = &[
"clang",
"clangAST",
"clangAnalysis",
"clangBasic",
"clangDriver",
"clangEdit",
"clangFrontend",
"clangIndex",
"clangLex",
"clangParse",
"clangRewrite",
"clangSema",
"clangSerialization",
];
/// Gets the name of an LLVM or Clang static library from a path.
fn get_library_name(path: &Path) -> Option<String> {
path.file_stem().map(|p| {
let string = p.to_string_lossy();
if let Some(name) = string.strip_prefix("lib") {
name.to_owned()
} else {
string.to_string()
}
})
}
/// Gets the LLVM static libraries required to link to `libclang`.
fn get_llvm_libraries() -> Vec<String> {
common::run_llvm_config(&["--libs", "--link-static"])
.unwrap()
.split_whitespace()
.filter_map(|p| {
// Depending on the version of `llvm-config` in use, listed
// libraries may be in one of two forms, a full path to the library
// or simply prefixed with `-l`.
if let Some(path) = p.strip_prefix("-l") {
Some(path.into())
} else {
get_library_name(Path::new(p))
}
})
.collect()
}
/// Gets the Clang static libraries required to link to `libclang`.
fn get_clang_libraries<P: AsRef<Path>>(directory: P) -> Vec<String> {
// Escape the directory in case it contains characters that have special
// meaning in glob patterns (e.g., `[` or `]`).
let directory = Pattern::escape(directory.as_ref().to_str().unwrap());
let directory = Path::new(&directory);
let pattern = directory.join("libclang*.a").to_str().unwrap().to_owned();
if let Ok(libraries) = glob::glob(&pattern) {
libraries
.filter_map(|l| l.ok().and_then(|l| get_library_name(&l)))
.collect()
} else {
CLANG_LIBRARIES.iter().map(|l| (*l).to_string()).collect()
}
}
/// Finds a directory containing LLVM and Clang static libraries and returns the
/// path to that directory.
fn find() -> PathBuf {
let name = if target_os!("windows") {
"libclang.lib"
} else {
"libclang.a"
};
let files = common::search_libclang_directories(&[name.into()], "LIBCLANG_STATIC_PATH");
if let Some((directory, _)) = files.into_iter().next() {
directory
} else {
panic!(
"could not find the required `{name}` static library, see the \
README for more information on how to link to `libclang` statically: \
https://github.com/KyleMayes/clang-sys?tab=readme-ov-file#static"
);
}
}
//================================================
// Linking
//================================================
/// Finds and links to `libclang` static libraries.
pub fn link() {
let cep = common::CommandErrorPrinter::default();
let directory = find();
// Specify required Clang static libraries.
println!("cargo:rustc-link-search=native={}", directory.display());
for library in get_clang_libraries(directory) {
println!("cargo:rustc-link-lib=static={}", library);
}
// Determine the shared mode used by LLVM.
let mode = common::run_llvm_config(&["--shared-mode"]).map(|m| m.trim().to_owned());
let prefix = if mode.map_or(false, |m| m == "static") {
"static="
} else {
""
};
// Specify required LLVM static libraries.
println!(
"cargo:rustc-link-search=native={}",
common::run_llvm_config(&["--libdir"]).unwrap().trim_end()
);
for library in get_llvm_libraries() {
println!("cargo:rustc-link-lib={}{}", prefix, library);
}
// Specify required system libraries.
// MSVC doesn't need this, as it tracks dependencies inside `.lib` files.
if cfg!(target_os = "freebsd") {
println!("cargo:rustc-flags=-l ffi -l ncursesw -l c++ -l z");
} else if cfg!(any(target_os = "haiku", target_os = "linux")) {
if cfg!(feature = "libcpp") {
println!("cargo:rustc-flags=-l c++");
} else {
println!("cargo:rustc-flags=-l ffi -l ncursesw -l stdc++ -l z");
}
} else if cfg!(target_os = "macos") {
println!("cargo:rustc-flags=-l ffi -l ncurses -l c++ -l z");
}
cep.discard();
}