Only run build script when necessary
The build script should only run if one of the generated files is changed.
This commit is contained in:
parent
cc30fcd34c
commit
a502e2132c
1 changed files with 110 additions and 37 deletions
167
tun/build.rs
167
tun/build.rs
|
|
@ -1,27 +1,134 @@
|
|||
#[cfg(not(windows))]
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
use std::io::{Cursor, Read};
|
||||
let out_dir = std::env::var("OUT_DIR")?;
|
||||
let path = std::path::PathBuf::from(out_dir);
|
||||
generate(&path).await?;
|
||||
|
||||
let buf = reqwest::get("https://www.wintun.net/builds/wintun-0.14.1.zip")
|
||||
.await?
|
||||
.bytes()
|
||||
.await?;
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
ssri::IntegrityChecker::new("sha256-B8JWGF1u42UuCfpVwLZz4mJLVl4CxLkJHHnKfS8k71E=".parse()?)
|
||||
.chain(&buf)
|
||||
#[cfg(windows)]
|
||||
async fn generate(out_dir: &std::path::Path) -> anyhow::Result<()> {
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
let bindings_path = out_dir.join("wintun.rs");
|
||||
let binary_path = out_dir.join("wintun.dll");
|
||||
println!("cargo:rerun-if-changed={}", bindings_path.to_str().unwrap());
|
||||
println!("cargo:rerun-if-changed={}", binary_path.to_str().unwrap());
|
||||
|
||||
if let (Ok(..), Ok(..)) = (File::open(&bindings_path), File::open(&binary_path)) {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let archive = download(out_dir)
|
||||
.await
|
||||
.context("Failed to download wintun")?;
|
||||
|
||||
let (bindings, binary) = parse(archive).context("Failed to parse wintun archive")?;
|
||||
|
||||
bindings
|
||||
.write_to_file(bindings_path)
|
||||
.context("Failed to write bindings")?;
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(binary_path)
|
||||
.context("Failed to write binary")?;
|
||||
file.write_all(&binary)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
async fn download(directory: &std::path::Path) -> anyhow::Result<std::fs::File> {
|
||||
use std::{io::Write, str::FromStr};
|
||||
|
||||
let path = directory.join(WINTUN_FILENAME);
|
||||
let mut file = match std::fs::OpenOptions::new().read(true).open(&path) {
|
||||
Ok(existing) => return Ok(existing),
|
||||
Err(_e) => std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path)?,
|
||||
};
|
||||
|
||||
let mut url = reqwest::Url::from_str("https://www.wintun.net/builds")?;
|
||||
url.path_segments_mut().unwrap().push(WINTUN_FILENAME);
|
||||
|
||||
let body = reqwest::get(url).await?.bytes().await?;
|
||||
|
||||
ssri::IntegrityChecker::new(WINTUN_INTEGRITY.parse()?)
|
||||
.chain(&body)
|
||||
.result()?;
|
||||
|
||||
let mut archive = zip::ZipArchive::new(Cursor::new(buf))?;
|
||||
file.set_len(0)?;
|
||||
file.write_all(&body)?;
|
||||
|
||||
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?);
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn parse(file: std::fs::File) -> anyhow::Result<(bindgen::Bindings, Vec<u8>)> {
|
||||
use anyhow::Context;
|
||||
use std::io::Read;
|
||||
|
||||
let reader = std::io::BufReader::new(file);
|
||||
let mut archive = zip::ZipArchive::new(reader)?;
|
||||
|
||||
let mut header = String::new();
|
||||
archive
|
||||
.by_name("wintun/include/wintun.h")?
|
||||
.read_to_string(&mut header)?;
|
||||
header.push_str(
|
||||
"WINTUN_CLOSE_ADAPTER_FUNC WintunCloseAdapter;
|
||||
header.push_str(WINTUN_BINDINGS_PREAMBLE);
|
||||
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header_contents("wintun.h", &header)
|
||||
.allowlist_function("Wintun.*")
|
||||
.allowlist_type("WINTUN_.*")
|
||||
.dynamic_library_name("wintun")
|
||||
.dynamic_link_require_all(true)
|
||||
.generate()
|
||||
.context("Failed to generate bindings from wintun archive")
|
||||
.unwrap();
|
||||
|
||||
let mut binary = Vec::new();
|
||||
let target = std::env::var("TARGET")?;
|
||||
let arch = match target.split('-').next() {
|
||||
Some("i686") => "x86",
|
||||
Some("x86_64") => "amd64",
|
||||
Some("aarch64") => "arm64",
|
||||
Some("thumbv7a") => "arm",
|
||||
Some(a) => panic!("{} is not a supported architecture", a),
|
||||
None => unreachable!(),
|
||||
};
|
||||
archive
|
||||
.by_name(&format!("wintun/bin/{}/wintun.dll", arch))?
|
||||
.read_to_end(&mut binary)
|
||||
.context("Failed to read binary from wintun archive")?;
|
||||
|
||||
Ok((bindings, binary))
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
const WINTUN_FILENAME: &str = "wintun-0.14.1.zip";
|
||||
|
||||
#[cfg(windows)]
|
||||
const WINTUN_INTEGRITY: &str = "sha256-B8JWGF1u42UuCfpVwLZz4mJLVl4CxLkJHHnKfS8k71E=";
|
||||
|
||||
#[cfg(windows)]
|
||||
const WINTUN_BINDINGS_PREAMBLE: &str = r#"
|
||||
WINTUN_CLOSE_ADAPTER_FUNC WintunCloseAdapter;
|
||||
WINTUN_OPEN_ADAPTER_FUNC WintunOpenAdapter;
|
||||
WINTUN_GET_ADAPTER_LUID_FUNC WintunGetAdapterLUID;
|
||||
WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC WintunGetRunningDriverVersion;
|
||||
|
|
@ -34,39 +141,5 @@ async fn main() -> anyhow::Result<()> {
|
|||
WINTUN_RECEIVE_PACKET_FUNC WintunReceivePacket;
|
||||
WINTUN_RELEASE_RECEIVE_PACKET_FUNC WintunReleaseReceivePacket;
|
||||
WINTUN_ALLOCATE_SEND_PACKET_FUNC WintunAllocateSendPacket;
|
||||
WINTUN_SEND_PACKET_FUNC WintunSendPacket;",
|
||||
);
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header_contents("wintun.h", &header)
|
||||
.allowlist_function("Wintun.*")
|
||||
.allowlist_type("WINTUN_.*")
|
||||
.dynamic_library_name("wintun")
|
||||
.dynamic_link_require_all(true)
|
||||
.generate()
|
||||
.unwrap();
|
||||
bindings.write_to_file(out_dir.join("wintun.rs"))?;
|
||||
|
||||
let mut library = Vec::new();
|
||||
let target = std::env::var("TARGET")?;
|
||||
let arch = match target.split("-").next() {
|
||||
Some("i686") => "x86",
|
||||
Some("x86_64") => "amd64",
|
||||
Some("aarch64") => "arm64",
|
||||
Some("thumbv7a") => "arm",
|
||||
Some(a) => panic!("{} is not a supported architecture", a),
|
||||
None => unreachable!(),
|
||||
};
|
||||
archive
|
||||
.by_name(&format!("wintun/bin/{}/wintun.dll", arch))?
|
||||
.read_to_end(&mut library)?;
|
||||
std::fs::write(out_dir.join("wintun.dll"), library)?;
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
}
|
||||
WINTUN_SEND_PACKET_FUNC WintunSendPacket;
|
||||
"#;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue