-
Notifications
You must be signed in to change notification settings - Fork 10
/
build.rs
116 lines (102 loc) · 4.74 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
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();
}
// 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();
}
// install the dylib to system path
let libffi_out_path =
drift_ffi_sys_crate.join(Path::new(&format!("target/{profile}/{LIB}.{lib_ext}")));
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");
if !output.status.success() {
eprintln!(
"{LIB} could not be installed: {}",
String::from_utf8_lossy(output.stderr.as_slice())
);
}
}
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);
}