-
Notifications
You must be signed in to change notification settings - Fork 9
/
build.rs
176 lines (152 loc) · 5.48 KB
/
build.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
fn main() {
println!("cargo:rustc-check-cfg=cfg(unified_cl)");
println!("cargo:rerun-if-changed=build.rs");
if std::env::var("DOCS_RS").is_ok() {
return;
}
#[cfg(not(docsrs))]
#[cfg(feature = "opencl")]
if has_device_unified_mem() {
println!("cargo:rustc-cfg=unified_cl");
}
#[cfg(not(docsrs))]
#[cfg(feature = "opencl")]
cl_check_kernel_exec();
{
#[cfg(target_os = "macos")]
{
// check if debug or release
if Ok("debug".into()) == std::env::var("PROFILE") {
std::env::set_var("CUSTOS_CUDA_LINK_ON_BUILD", "false");
}
}
#[cfg(not(docsrs))]
#[cfg(feature = "cuda")]
if check_cuda_link() {
link_cuda();
}
}
}
#[cfg(not(docsrs))]
#[cfg(feature = "opencl")]
fn cl_check_kernel_exec() {
use min_cl::CLDevice;
println!("cargo:rerun-if-env-changed=CUSTOS_CL_KERNEL_EXEC_ON_BUILD");
let run_cl_check = std::env::var("CUSTOS_CL_KERNEL_EXEC_ON_BUILD")
.unwrap_or_else(|_| "false".into())
.parse::<bool>()
.expect("CUSTOS_CL_KERNEL_EXEC_ON_BUILD must be either true or false");
if run_cl_check {
// Runs a simple kernel to measure performance and functionality in general
CLDevice::fastest().unwrap();
}
}
#[cfg(not(docsrs))]
#[cfg(feature = "opencl")]
fn has_device_unified_mem() -> bool {
println!("cargo:rerun-if-env-changed=CUSTOS_CL_DEVICE_IDX");
println!("cargo:rerun-if-env-changed=CUSTOS_CU_DEVICE_IDX");
println!("cargo:rerun-if-env-changed=CUSTOS_USE_UNIFIED");
let device_idx = std::env::var("CUSTOS_CL_DEVICE_IDX")
.unwrap_or_else(|_| "0".into())
.parse::<usize>()
.expect("Value in variable 'CUSTOS_CL_DEVICE_IDX' must be a usize value.");
// this environment variable (CUSTOS_USE_UNIFIED) is used to either:
// ... disable unified memory on unified memory devices, or
// ... activate unified memory on devices with dedicated memory to check if
// the code would compile on a device with unified memory.
if let Ok(value) = std::env::var("CUSTOS_USE_UNIFIED") {
if &value.to_ascii_lowercase() != "default" {
let force_unified_mem = value.parse()
.expect("'CUSTOS_USE_UNIFIED' must be either true, false or default.
[
default=it is checked whether the device can use unified memory automatically.
true='simulates' unified memory to know if your code would compile on a device with unified memory.
false=deactivates unified memory
]");
if force_unified_mem {
println!("Device forcefully uses unified memory!")
} else {
println!("Device won't use unified memory!")
}
return force_unified_mem;
}
}
min_cl::CLDevice::new(device_idx)
.unwrap_or_else(|_| panic!("Could not get an OpenCL device (at index {device_idx}). Set `CUSTOS_CL_DEVICE_IDX` to a valid device index."))
.unified_mem
}
#[cfg(feature = "cuda")]
use std::path::{Path, PathBuf};
#[cfg(feature = "cuda")]
fn check_cuda_link() -> bool {
println!("cargo:rerun-if-env-changed=CUSTOS_CUDA_LINK_ON_BUILD");
std::env::var("CUSTOS_CUDA_LINK_ON_BUILD")
.unwrap_or_else(|_| "true".into())
.parse::<bool>()
.expect("CUSTOS_CUDA_LINK_ON_BUILD must be either true or false")
}
// https://github.com/coreylowman/cudarc/blob/main/build.rs
#[cfg(feature = "cuda")]
fn link_cuda() {
println!("cargo:rerun-if-env-changed=CUDA_ROOT");
println!("cargo:rerun-if-env-changed=CUDA_PATH");
println!("cargo:rerun-if-env-changed=CUDA_TOOLKIT_ROOT_DIR");
let candidates: Vec<PathBuf> = root_candidates().collect();
let toolkit_root = root_candidates()
.find(|path| path.join("include").join("cuda.h").is_file())
.unwrap_or_else(|| {
panic!(
"Unable to find `include/cuda.h` under any of: {candidates:?}. Set the `CUDA_ROOT` environment variable to `$CUDA_ROOT/include/cuda.h` to override path.",
)
});
for path in lib_candidates(&toolkit_root) {
println!("cargo:rustc-link-search=native={}", path.display());
}
println!("cargo:rustc-link-lib=dylib=cuda");
println!("cargo:rustc-link-lib=dylib=nvrtc");
println!("cargo:rustc-link-lib=dylib=curand");
println!("cargo:rustc-link-lib=dylib=cublas");
}
#[cfg(feature = "cuda")]
fn root_candidates() -> impl Iterator<Item = PathBuf> {
let env_vars = [
"CUDA_PATH",
"CUDA_ROOT",
"CUDA_TOOLKIT_ROOT_DIR",
"CUDNN_LIB",
];
let env_vars = env_vars
.into_iter()
.map(std::env::var)
.filter_map(Result::ok);
let roots = [
"/usr",
"/usr/local/cuda",
"/opt/cuda",
"/usr/lib/cuda",
"C:/Program Files/NVIDIA GPU Computing Toolkit",
"C:/CUDA",
];
let roots = roots.into_iter().map(Into::into);
env_vars.chain(roots).map(Into::<PathBuf>::into)
}
#[cfg(feature = "cuda")]
fn lib_candidates(root: &Path) -> Vec<PathBuf> {
[
"lib",
"lib/x64",
"lib/Win32",
"lib/x86_64",
"lib/x86_64-linux-gnu",
"lib64",
"lib64/stubs",
"targets/x86_64-linux",
"targets/x86_64-linux/lib",
"targets/x86_64-linux/lib/stubs",
]
.iter()
.map(|&p| root.join(p))
.filter(|p| p.is_dir())
.collect()
}