-
Notifications
You must be signed in to change notification settings - Fork 13
/
build.rs
132 lines (115 loc) · 5.34 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
use std::{collections::HashMap, fs::File, io::Write, path::Path};
const LIB: &str = "libdrift_ffi_sys";
fn main() {
let current_dir = std::env::current_dir().unwrap().canonicalize().unwrap();
// Generate rust types from anchor IDL
let idl_source_path = ¤t_dir.join(Path::new("res/drift.json"));
let idl_mod_rs = match drift_idl_gen::generate_rust_types(idl_source_path) {
Ok(idl_mod_rs) => idl_mod_rs,
Err(err) => panic!("generating IDL failed: {err:?}"),
};
let idl_mod_path = current_dir.join(Path::new("crates/src/drift_idl.rs"));
let mut file = File::create(&idl_mod_path).expect("create IDL .rs");
file.write_all(idl_mod_rs.as_bytes())
.expect("wrote IDL .rs");
if std::env::var("CARGO_DRIFT_FFI_STATIC").is_ok()
|| std::env::var("CARGO_DRIFT_FFI_PATH").is_err()
{
// Build + Link FFI crate from source
println!("{LIB}: building from source...");
let drift_ffi_sys_crate = current_dir.join(Path::new("crates/drift-ffi-sys"));
// the x86_64 target must exist
let host_target = std::env::var("TARGET").unwrap();
let (lib_target, lib_ext) = if host_target.contains("apple") {
("x86_64-apple-darwin", "dylib")
} else if host_target.contains("linux") {
("x86_64-unknown-linux-gnu", "so")
} else {
eprintln!("Unsupported host platform: {host_target}, please open an issue at: https://github.com/drift-labs/drift-rs/issues");
fail_build();
};
// "RUSTC" is set as the cargo version of the main SDK build, it must be unset for the ffi build
// "CARGO*" envs are also configured for the main SDK build
// https://users.rust-lang.org/t/switching-toolchains-in-build-rs-use-nightly-for-data-generation-and-stable-for-main-compilation/114443/5
let ffi_build_envs: HashMap<String, String> = std::env::vars()
.filter(|(k, _v)| !k.starts_with("CARGO") && !k.starts_with("RUSTC"))
.collect();
println!("{ffi_build_envs:?}");
let profile = std::env::var("PROFILE").expect("cargo PROFILE set");
// force drift-ffi-sys to build with specific toolchain (arch=x86_64, version=<=1.76.0)
// this ensures zero copy deserialization works correctly with the onchain data layout
let ffi_toolchain = format!("1.76.0-{lib_target}");
let installed_toolchains_query = std::process::Command::new("rustup")
.args(["toolchain", "list"])
.output()
.expect("rustup installed");
if !installed_toolchains_query.status.success() {
println!("Check 'rustup' is installed and discoverable in system PATH");
}
let installed_toolchains = String::from_utf8_lossy(&installed_toolchains_query.stdout);
if !installed_toolchains.contains(&ffi_toolchain) {
eprintln!("Required toolchain: {ffi_toolchain} is missing. Run: 'rustup install {ffi_toolchain}' to install and retry the build");
fail_build();
}
// install the dylib to system path
let libffi_out_path =
drift_ffi_sys_crate.join(Path::new(&format!("target/{profile}/{LIB}.{lib_ext}")));
// Build ffi crate and link
let mut ffi_build = std::process::Command::new("rustup");
ffi_build
.env_clear()
.envs(ffi_build_envs)
.current_dir(drift_ffi_sys_crate.clone())
.args(["run", &ffi_toolchain, "cargo", "build"]);
match profile.as_str() {
"debug" => (),
"release" => {
ffi_build.arg("--release");
}
custom => {
ffi_build.arg(format!("--profile={custom}"));
}
}
let output = ffi_build.output().expect("drift-ffi-sys built");
if !output.status.success() {
eprintln!(" {}", String::from_utf8_lossy(output.stderr.as_slice()));
fail_build();
}
if !output.status.success() {
eprintln!(
"{LIB} could not be installed: {}",
String::from_utf8_lossy(output.stderr.as_slice())
);
}
if let Ok(out_dir) = std::env::var("OUT_DIR") {
let _output = std::process::Command::new("cp")
.args([
libffi_out_path.to_str().expect("ffi build path"),
out_dir.as_str(),
])
.output()
.expect("install ok");
println!("{LIB}: searching for lib at: {out_dir}");
println!("cargo:rustc-link-search=native={out_dir}");
}
let _output = std::process::Command::new("ln")
.args([
"-sf",
libffi_out_path.to_str().expect("ffi build path"),
"/usr/local/lib/",
])
.output()
.expect("install ok");
println!("{LIB}: searching for lib at: /usr/local/lib");
println!("cargo:rustc-link-search=native=/usr/local/lib");
}
if let Ok(lib_path) = std::env::var("CARGO_DRIFT_FFI_PATH") {
println!("{LIB}: searching for lib at: {lib_path}");
println!("cargo:rustc-link-search=native={lib_path}");
}
println!("cargo:rustc-link-lib=dylib=drift_ffi_sys");
}
fn fail_build() -> ! {
eprintln!("{LIB} build failed");
std::process::exit(1);
}