130 lines
4.4 KiB
Rust
130 lines
4.4 KiB
Rust
use embed_manifest::embed_manifest;
|
|
use std::env;
|
|
use std::fs;
|
|
use std::io::{self, Write};
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::Command;
|
|
|
|
const UI_BUNDLE_MAGIC: &[u8] = b"COVENANT_SETUP_UI_BUNDLE_V1\n";
|
|
|
|
fn main() {
|
|
println!("cargo:rustc-check-cfg=cfg(covenant_setup_embedded_ui)");
|
|
publish_csharp_ui();
|
|
embed_manifest(embed_manifest::new_manifest("Comctl32"))
|
|
.expect("unable to embed application manifest");
|
|
}
|
|
|
|
fn publish_csharp_ui() {
|
|
println!("cargo:rerun-if-changed=ui/Covenant.Setup.Ui/Covenant.Setup.Ui.csproj");
|
|
println!("cargo:rerun-if-changed=ui/Covenant.Setup.Ui/Program.cs");
|
|
println!("cargo:rerun-if-changed=ui/Covenant.Setup.Ui/InstallerUiWindow.cs");
|
|
println!("cargo:rerun-if-changed=ui/Covenant.Setup.Ui/UiProtocol.cs");
|
|
println!("cargo:rerun-if-changed=ui/Covenant.Setup.Ui/app.manifest");
|
|
|
|
let manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
|
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
|
let project = manifest_dir.join("ui/Covenant.Setup.Ui/Covenant.Setup.Ui.csproj");
|
|
let publish_dir = out_dir.join("csharp-ui");
|
|
let dotnet_home = out_dir.join("dotnet-home");
|
|
let status = Command::new("dotnet")
|
|
.env("DOTNET_CLI_HOME", &dotnet_home)
|
|
.env("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1")
|
|
.env("DOTNET_CLI_TELEMETRY_OPTOUT", "1")
|
|
.arg("publish")
|
|
.arg(&project)
|
|
.arg("--nologo")
|
|
.arg("--configuration")
|
|
.arg("Release")
|
|
.arg("--runtime")
|
|
.arg("win-x64")
|
|
.arg("--self-contained")
|
|
.arg("true")
|
|
.arg("-p:WindowsPackageType=None")
|
|
.arg("-p:WindowsAppSDKSelfContained=true")
|
|
.arg("-p:PublishSingleFile=false")
|
|
.arg("-p:PublishTrimmed=false")
|
|
.arg("-p:DebugType=none")
|
|
.arg("-p:DebugSymbols=false")
|
|
.arg("-o")
|
|
.arg(&publish_dir)
|
|
.status();
|
|
let status = match status {
|
|
Ok(status) => status,
|
|
Err(err) => {
|
|
println!(
|
|
"cargo:warning=C# UI helper was not bundled because dotnet publish could not start: {err}"
|
|
);
|
|
return;
|
|
}
|
|
};
|
|
if !status.success() {
|
|
println!(
|
|
"cargo:warning=C# UI helper was not bundled because dotnet publish failed with {status}"
|
|
);
|
|
return;
|
|
}
|
|
|
|
let ui_exe = publish_dir.join("Covenant.Setup.Ui.exe");
|
|
if !ui_exe.exists() {
|
|
println!(
|
|
"cargo:warning=C# UI helper was not bundled because dotnet publish did not produce {}",
|
|
ui_exe.display()
|
|
);
|
|
return;
|
|
}
|
|
let ui_bundle = out_dir.join("csharp-ui.bundle");
|
|
if let Err(err) = write_ui_bundle(&publish_dir, &ui_bundle) {
|
|
println!(
|
|
"cargo:warning=C# UI helper was not bundled because bundle creation failed: {err}"
|
|
);
|
|
return;
|
|
}
|
|
println!("cargo:rustc-cfg=covenant_setup_embedded_ui");
|
|
println!(
|
|
"cargo:rustc-env=COVENANT_SETUP_UI_BUNDLE={}",
|
|
ui_bundle.display()
|
|
);
|
|
}
|
|
|
|
fn write_ui_bundle(publish_dir: &Path, bundle_path: &Path) -> io::Result<()> {
|
|
let mut files = Vec::new();
|
|
collect_files(publish_dir, publish_dir, &mut files)?;
|
|
files.sort_by(|left, right| left.0.cmp(&right.0));
|
|
|
|
let mut bundle = fs::File::create(bundle_path)?;
|
|
bundle.write_all(UI_BUNDLE_MAGIC)?;
|
|
for (relative_path, path) in files {
|
|
let relative_path = relative_path.to_string_lossy().replace('\\', "/");
|
|
let relative_path_bytes = relative_path.as_bytes();
|
|
let data = fs::read(path)?;
|
|
bundle.write_all(&(relative_path_bytes.len() as u32).to_le_bytes())?;
|
|
bundle.write_all(&(data.len() as u64).to_le_bytes())?;
|
|
bundle.write_all(relative_path_bytes)?;
|
|
bundle.write_all(&data)?;
|
|
}
|
|
bundle.write_all(&0u32.to_le_bytes())?;
|
|
bundle.write_all(&0u64.to_le_bytes())?;
|
|
Ok(())
|
|
}
|
|
|
|
fn collect_files(
|
|
root: &Path,
|
|
current: &Path,
|
|
files: &mut Vec<(PathBuf, PathBuf)>,
|
|
) -> io::Result<()> {
|
|
for entry in fs::read_dir(current)? {
|
|
let entry = entry?;
|
|
let path = entry.path();
|
|
if path.is_dir() {
|
|
collect_files(root, &path, files)?;
|
|
} else if path.is_file() {
|
|
let relative_path = path
|
|
.strip_prefix(root)
|
|
.map_err(io::Error::other)?
|
|
.to_path_buf();
|
|
files.push((relative_path, path));
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|