use std::{fs::File, io::Write, process::Command}; use chrono::Local; use handlebars::Handlebars; use serde_json::json; use zip::{write::FileOptions, ZipWriter}; static VERSION: [u8; 4] = include!("../../kextinterface/version.txt"); static LIB_PATH: &'static str = "./build/x86_64-pc-windows-msvc/release/driver.lib"; fn main() { build_driver(); let filename = format!( "portmaster-kext-release-bundle-v{}-{}-{}-{}.zip", VERSION[0], VERSION[1], VERSION[2], VERSION[3] ); println!("Building KEXT: {}", filename); // Create Zip that will hold all the release files and scripts. let file = File::create(&filename).unwrap(); let mut zip = zip::ZipWriter::new(file); // Write files to zip zip.add_directory("cab", FileOptions::default()).unwrap(); // Write driver.lib write_lib_file_zip(&mut zip); // Write ddf file write_to_zip(&mut zip, "PortmasterKext.ddf", get_ddf_content()); // Write build cab script write_to_zip(&mut zip, "build_cab.ps1", get_build_cab_script_content()); // Write metadata file write_to_zip(&mut zip, "version.rc", get_metadata_file_content()); // Write inf file write_to_zip(&mut zip, "cab/PortmasterKext64.inf", get_inf_content()); zip.finish().unwrap(); } fn version_str() -> String { return format!( "{}.{}.{}.{}", VERSION[0], VERSION[1], VERSION[2], VERSION[3] ); } fn build_driver() { let output = Command::new("cargo") .current_dir("../driver") .arg("build") .arg("--release") .args(["--target", "x86_64-pc-windows-msvc"]) .args(["--target-dir", "../release/build"]) .output() .unwrap(); println!("{}", String::from_utf8(output.stderr).unwrap()); } fn get_inf_content() -> String { let reg = Handlebars::new(); let today = Local::now(); reg.render_template( include_str!("../templates/PortmasterKext64.inf"), &json!({"date": today.format("%m/%d/%Y").to_string(), "version": version_str()}), ) .unwrap() } fn get_ddf_content() -> String { let reg = Handlebars::new(); let cab_file = format!( "PortmasterKext_v{}-{}-{}.cab", VERSION[0], VERSION[1], VERSION[2] ); reg.render_template( include_str!("../templates/PortmasterKext.ddf"), &json!({"cab_file": cab_file}), ) .unwrap() } fn get_metadata_file_content() -> String { let reg = Handlebars::new(); let version = format!( "{}, {}, {}, {}", VERSION[0], VERSION[1], VERSION[2], VERSION[3] ); reg.render_template( include_str!("../templates/version.rc"), &json!({"version": version, "version_str": version_str()}), ) .unwrap() } fn get_build_cab_script_content() -> String { let reg = Handlebars::new(); let cab_file = format!( "PortmasterKext_v{}-{}-{}.cab", VERSION[0], VERSION[1], VERSION[2] ); reg .render_template( include_str!("../templates/build_cab.ps1"), &json!({"sys_file": "PortmasterKext64.sys", "pdb_file": "PortmasterKext64.pdb", "lib_file": "driver.lib", "cab_file": &cab_file }), ) .unwrap() } fn write_to_zip(zip: &mut ZipWriter, filename: &str, content: String) { zip.start_file(filename, FileOptions::default()).unwrap(); zip.write(&content.into_bytes()).unwrap(); } fn write_lib_file_zip(zip: &mut ZipWriter) { zip.start_file("driver.lib", FileOptions::default()) .unwrap(); let mut driver_file = File::open(LIB_PATH).unwrap(); std::io::copy(&mut driver_file, zip).unwrap(); }