1use std::{fs::File, io::Cursor, path::Path};
2
3#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq)]
4struct Manifest {
5 latest: String,
6 catalog: Vec<String>,
7}
8
9pub fn link_sdk(version: &str) {
10 let target = std::env::var("TARGET").expect("TARGET environment variable not set");
11 let target_env = std::env::var("CARGO_CFG_TARGET_ENV")
12 .expect("CARGO_CFG_TARGET_ENV environment variable not set");
13 let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set");
14
15 if !target.contains("vex") {
16 panic!("`vex-sdk-build` only supports building for VEX targets.")
17 }
18
19 let (cdn_base, folder_name, runtime_library_name) = match target_env.as_ref() {
20 "v5" => ("https://content.vexrobotics.com/vexos/public/V5/vscode/sdk/cpp", "vexv5", "v5rt"),
21 "exp" => ("https://content.vexrobotics.com/vexos/public/EXP/vscode/sdk/cpp", "vexexp", "exprt"),
22 "iq2" => ("https://content.vexrobotics.com/vexos/public/IQ2/vscode/sdk/cpp", "vexiq2", "viq2rt"),
23 _ => panic!("unsupported `target_vendor` value. `vex-sdk-build` only supports building for VEX targets.")
24 };
25
26 let manifest: Manifest = ureq::get(format!("{cdn_base}/manifest.json"))
27 .call()
28 .expect("failed to download VEX SDK manifest")
29 .body_mut()
30 .read_json()
31 .expect("failed to parse VEX SDK manifest");
32
33 if !manifest.catalog.contains(&version.to_string()) {
34 panic!("{} is not a valid VEX SDK version", version);
35 }
36
37 let zip_data = ureq::get(format!("{cdn_base}/{version}.zip"))
38 .call()
39 .expect("failed to download VEX SDK")
40 .body_mut()
41 .read_to_vec()
42 .expect("failed to read VEX SDK");
43
44 let runtime_library_file = format!("lib{runtime_library_name}.a");
45 let mut archive =
46 zip::ZipArchive::new(Cursor::new(zip_data)).expect("failed to read VEX SDK zip archive");
47 let runtime_library_path = format!("{version}/{folder_name}/{runtime_library_file}");
48
49 std::io::copy(
50 &mut archive.by_name(&runtime_library_path).expect(&format!(
51 "VEX SDK is missing runtime library {runtime_library_path}"
52 )),
53 &mut File::create(&Path::new(&out_dir).join(runtime_library_file)).unwrap(),
54 )
55 .unwrap();
56
57 println!("cargo::rerun-if-changed=build.rs");
58 println!("cargo:rustc-link-search=native={out_dir}");
59 println!("cargo:rustc-link-lib=static={runtime_library_name}");
60}