Initial commit
This commit is contained in:
170
tauri/src-tauri/build.rs
Normal file
170
tauri/src-tauri/build.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
// Link Swift runtime libraries for screencapturekit crate
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// ScreenCaptureKit does not exist on macOS 11, so weak-link it to
|
||||
// allow the app to launch and gate usage at runtime instead.
|
||||
println!("cargo:rustc-link-arg=-Wl,-weak_framework,ScreenCaptureKit");
|
||||
|
||||
// Add Swift runtime library paths to RPATH
|
||||
println!("cargo:rustc-link-arg=-Wl,-rpath,/usr/lib/swift");
|
||||
println!("cargo:rustc-link-arg=-L/usr/lib/swift");
|
||||
|
||||
// Also try Xcode's Swift libraries
|
||||
if let Ok(output) = Command::new("xcode-select").arg("-p").output() {
|
||||
if output.status.success() {
|
||||
let xcode_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
let swift_lib_path = format!(
|
||||
"{}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx",
|
||||
xcode_path
|
||||
);
|
||||
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", swift_lib_path);
|
||||
println!("cargo:rustc-link-arg=-L{}", swift_lib_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let project_root = env!("CARGO_MANIFEST_DIR");
|
||||
let gen_dir = format!("{}/gen", project_root);
|
||||
std::fs::create_dir_all(&gen_dir).expect("Failed to create gen directory");
|
||||
|
||||
// Compile macOS Liquid Glass icon
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// voicebox.icon is in tauri/assets/voicebox.icon (one level up from src-tauri)
|
||||
let icon_source = format!("{}/../assets/voicebox.icon", project_root);
|
||||
|
||||
if std::path::Path::new(&icon_source).exists() {
|
||||
println!("cargo:rerun-if-changed={}", icon_source);
|
||||
println!("cargo:rerun-if-changed={}/icon.json", icon_source);
|
||||
println!("cargo:rerun-if-changed={}/Assets", icon_source);
|
||||
|
||||
let partial_plist = format!("{}/partial.plist", gen_dir);
|
||||
let output = Command::new("xcrun")
|
||||
.args([
|
||||
"actool",
|
||||
"--compile",
|
||||
&gen_dir,
|
||||
"--output-format",
|
||||
"human-readable-text",
|
||||
"--output-partial-info-plist",
|
||||
&partial_plist,
|
||||
"--app-icon",
|
||||
"voicebox",
|
||||
"--include-all-app-icons",
|
||||
"--target-device",
|
||||
"mac",
|
||||
"--minimum-deployment-target",
|
||||
"11.0",
|
||||
"--platform",
|
||||
"macosx",
|
||||
&icon_source,
|
||||
])
|
||||
.output();
|
||||
|
||||
match output {
|
||||
Ok(output) => {
|
||||
if !output.status.success() {
|
||||
eprintln!("actool stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
eprintln!("actool stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||
panic!("actool failed to compile icon");
|
||||
}
|
||||
println!("Successfully compiled icon to {}", gen_dir);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to execute xcrun actool: {}", e);
|
||||
eprintln!("Make sure you have Xcode Command Line Tools installed");
|
||||
panic!("Icon compilation failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Generate voicebox.icns from the source PNG via sips + iconutil
|
||||
let icns_path = format!("{}/voicebox.icns", gen_dir);
|
||||
if !std::path::Path::new(&icns_path).exists() {
|
||||
let source_png = format!("{}/Assets/Voicebox.png", icon_source);
|
||||
if std::path::Path::new(&source_png).exists() {
|
||||
let iconset_dir = format!("{}/voicebox.iconset", gen_dir);
|
||||
std::fs::create_dir_all(&iconset_dir).ok();
|
||||
|
||||
let sizes: &[(u32, &str)] = &[
|
||||
(16, "icon_16x16.png"),
|
||||
(32, "icon_16x16@2x.png"),
|
||||
(32, "icon_32x32.png"),
|
||||
(64, "icon_32x32@2x.png"),
|
||||
(128, "icon_128x128.png"),
|
||||
(256, "icon_128x128@2x.png"),
|
||||
(256, "icon_256x256.png"),
|
||||
(512, "icon_256x256@2x.png"),
|
||||
(512, "icon_512x512.png"),
|
||||
(1024, "icon_512x512@2x.png"),
|
||||
];
|
||||
|
||||
for (size, name) in sizes {
|
||||
let dest = format!("{}/{}", iconset_dir, name);
|
||||
let status = Command::new("sips")
|
||||
.args([
|
||||
"-z",
|
||||
&size.to_string(),
|
||||
&size.to_string(),
|
||||
&source_png,
|
||||
"--out",
|
||||
&dest,
|
||||
])
|
||||
.output();
|
||||
if let Ok(out) = status {
|
||||
if !out.status.success() {
|
||||
eprintln!(
|
||||
"sips failed for {}: {}",
|
||||
name,
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let iconutil_output = Command::new("iconutil")
|
||||
.args(["-c", "icns", "-o", &icns_path, &iconset_dir])
|
||||
.output();
|
||||
|
||||
match iconutil_output {
|
||||
Ok(out) if out.status.success() => {
|
||||
println!("Generated voicebox.icns");
|
||||
}
|
||||
Ok(out) => {
|
||||
eprintln!("iconutil failed: {}", String::from_utf8_lossy(&out.stderr));
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to run iconutil: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up iconset directory
|
||||
std::fs::remove_dir_all(&iconset_dir).ok();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!(
|
||||
"cargo:warning=Icon source not found at {}, skipping icon compilation",
|
||||
icon_source
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all resource files exist so Tauri's bundler doesn't fail.
|
||||
// On non-macOS these are always stubs. On macOS, actool may not produce
|
||||
// Assets.car if the Xcode version doesn't support the .icon format.
|
||||
{
|
||||
let required = ["Assets.car", "voicebox.icns", "partial.plist"];
|
||||
for name in required {
|
||||
let path = format!("{}/{}", gen_dir, name);
|
||||
if !std::path::Path::new(&path).exists() {
|
||||
std::fs::write(&path, b"").ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tauri_build::build()
|
||||
}
|
||||
Reference in New Issue
Block a user