vex_sdk_build/
lib.rs

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}