use std::env;
use std::path::PathBuf;
fn main() {
println!("cargo:warning=Build script starting...");
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
println!("cargo:info=Target OS: {}", target_os);
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
println!("cargo:warning=Manifest dir: {}", manifest_dir.display());
if target_os == "macos" {
println!("cargo:info=Building for macOS...");
let source_files = [
manifest_dir
.join("bindings")
.join("macos")
.join("Monitor.m"),
manifest_dir
.join("bindings")
.join("macos")
.join("AccessibilityUtils.m"),
manifest_dir
.join("bindings")
.join("macos")
.join("Application.m"),
manifest_dir
.join("bindings")
.join("macos")
.join("Blocker.m"),
manifest_dir
.join("bindings")
.join("macos")
.join("AccessibilityElement.m"),
manifest_dir.join("bindings").join("macos").join("UI.m"),
];
let header_files = [
manifest_dir
.join("bindings")
.join("macos")
.join("Monitor.h"),
manifest_dir
.join("bindings")
.join("macos")
.join("Application.h"),
manifest_dir
.join("bindings")
.join("macos")
.join("WindowUtils.h"),
manifest_dir
.join("bindings")
.join("macos")
.join("Blocker.h"),
manifest_dir
.join("bindings")
.join("macos")
.join("AccessibilityElement.h"),
manifest_dir.join("bindings").join("macos").join("UI.h"),
];
let out_dir = std::env::var("OUT_DIR").unwrap();
let out_path = PathBuf::from(out_dir);
let include_dir = source_files[0].parent().unwrap();
println!("cargo:info=Source files: {:?}", source_files);
println!("cargo:warning=Output directory: {}", out_path.display());
let target_arch =
env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_else(|_| "aarch64".to_string());
println!("cargo:info=Target architecture: {}", target_arch);
let mut arch_flags: Vec<&str> = Vec::new();
match target_arch.as_str() {
"x86_64" => {
arch_flags.push("-arch");
arch_flags.push("x86_64");
}
"aarch64" => {
arch_flags.push("-arch");
arch_flags.push("arm64");
}
_ => {}
};
println!("cargo:info=Using architecture flags: {:?}", arch_flags);
println!("cargo:info=Compiling Objective-C code...");
let mut clang_args = vec![
"-fobjc-arc",
"-fmodules",
"-framework",
"Cocoa",
"-dynamiclib",
"-install_name",
"@rpath/libMacMonitor.dylib",
];
clang_args.extend(arch_flags);
let status = std::process::Command::new("clang")
.args(&clang_args)
.args(source_files.iter().map(|p| p.to_str().unwrap()))
.args(&[
"-I",
include_dir.to_str().unwrap(),
"-o",
out_path.join("libMacMonitor.dylib").to_str().unwrap(),
])
.status()
.expect("Failed to execute clang command");
if !status.success() {
panic!("Objective-C compilation failed");
}
println!("cargo:warning=Linking to path: {}", out_path.display());
println!("cargo:info=Setting up library paths...");
println!("cargo:rustc-link-search=native={}", out_path.display());
for file in source_files.iter().chain(header_files.iter()) {
println!("cargo:rerun-if-changed={}", file.display());
}
} else if target_os == "windows" {
println!("cargo:info=Building for Windows...");
let source_path = manifest_dir
.join("bindings")
.join("windows_monitor")
.join("windows_monitor")
.join("monitor.c");
let output_dir = manifest_dir
.join("bindings")
.join("windows_monitor")
.join("windows_monitor")
.join("release");
println!("cargo:info=Source path: {}", source_path.display());
println!("cargo:info=Output directory: {}", output_dir.display());
std::fs::create_dir_all(&output_dir).unwrap();
println!("cargo:info=Compiling C code...");
cc::Build::new()
.file(&source_path)
.static_flag(false) .out_dir(&output_dir) .compile("WindowsMonitor");
println!("cargo:info=Setting up library paths...");
println!("cargo:rustc-link-search=native={}", output_dir.display());
println!("cargo:rustc-link-lib=WindowsMonitor");
println!("cargo:rustc-link-lib=user32");
println!("cargo:rerun-if-changed={}", source_path.display());
println!("cargo:warning=Build script completed successfully");
}
}