-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbuild.rs
95 lines (83 loc) · 3.13 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
#![warn(clippy::all, clippy::pedantic)]
fn main() {
#[cfg(feature = "vendored")]
vendored::vendor_flatc().expect("failed to vendor flatc");
}
#[cfg(feature = "vendored")]
mod vendored {
use flate2::read::GzDecoder;
use ring::digest::{Context, SHA256};
use std::{
fs::File,
io::{BufReader, Read},
path::{Path, PathBuf},
};
use tar::Archive;
const SOURCE_URL: &str =
"https://github.com/google/flatbuffers/archive/refs/tags/v{version}.tar.gz";
const SUPPORTED_FLATC_VERSION: &str = "24.3.25";
const CHECKSUM_SHA256: &str =
"4157c5cacdb59737c5d627e47ac26b140e9ee28b1102f812b36068aab728c1ed";
const EXTRACT_DIRECTORY_PREFIX: &str = "flatbuffers-{version}";
pub fn vendor_flatc() -> anyhow::Result<()> {
let tmpdir = tempfile::tempdir()?;
let tarball_path = download_source_tarball(&tmpdir)?;
checksum_check(&tarball_path, CHECKSUM_SHA256)?;
// Extract the source tarball
let extract_path = tmpdir.path().join("flatbuffers");
unpack_tarball(tarball_path, &extract_path)?;
let source_dir = extract_path
.join(EXTRACT_DIRECTORY_PREFIX.replace("{version}", SUPPORTED_FLATC_VERSION));
let dest = compile_flatc(source_dir);
let flatc_path = dest.join("bin/flatc");
println!("cargo::rustc-env=FLATC_PATH={}", flatc_path.display());
Ok(())
}
fn download_source_tarball<P: AsRef<Path>>(dir: P) -> anyhow::Result<PathBuf> {
let tarball_path = dir.as_ref().join("flatbuffers.tar.gz");
let mut file = File::create(&tarball_path)?;
let mut response = reqwest::blocking::get(get_full_source_url())?;
response.copy_to(&mut file)?;
Ok(tarball_path)
}
fn unpack_tarball<P: AsRef<Path>, Q: AsRef<Path>>(
tarball_path: P,
extraction_path: Q,
) -> anyhow::Result<()> {
let tar_gz = File::open(tarball_path)?;
let tar = GzDecoder::new(tar_gz);
let mut archive = Archive::new(tar);
archive.unpack(extraction_path)?;
Ok(())
}
fn checksum_check<P: AsRef<Path>>(file_path: P, expected_checksum: &str) -> anyhow::Result<()> {
let mut digester = Context::new(&SHA256);
let mut file = File::open(file_path)?;
let mut reader = BufReader::new(&mut file);
let mut buffer = [0u8; 4096];
loop {
let byte_count = reader.read(&mut buffer)?;
if byte_count == 0 {
break;
}
digester.update(&buffer[..byte_count]);
}
let digest = digester.finish();
let digest_str = hex::encode(digest.as_ref());
if digest_str == expected_checksum {
Ok(())
} else {
Err(anyhow::anyhow!(
"checskum for file did not match; expected {}, got {}",
expected_checksum,
digest_str
))
}
}
fn compile_flatc<P: AsRef<Path>>(source_dir: P) -> PathBuf {
cmake::build(source_dir)
}
fn get_full_source_url() -> String {
SOURCE_URL.replace("{version}", SUPPORTED_FLATC_VERSION)
}
}