godot-testability-runtime 0.1.2

Embedded Godot runtime for comprehensive Rust testing
Documentation
//! Build script for godot-testability-runtime
//!
//! This build script handles linking against libgodot when the embedded_runtime feature is enabled.

use std::env;
use std::path::{Path, PathBuf};

fn main() {
    println!("cargo:rerun-if-changed=build.rs");

    if cfg!(feature = "embedded_runtime") {
        link_libgodot();
    }
}

fn link_libgodot() {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();

    match target_os.as_str() {
        "macos" => link_macos_libgodot(&target_arch),
        "linux" => {
            println!(
                "cargo:warning=libgodot not yet available for Linux - using stub implementation"
            );
        }
        "windows" => {
            println!(
                "cargo:warning=libgodot not yet available for Windows - using stub implementation"
            );
        }
        _ => {
            println!(
                "cargo:warning=libgodot not available for target OS {} - using stub implementation",
                target_os
            );
        }
    }
}

fn link_macos_libgodot(target_arch: &str) {
    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = PathBuf::from(&out_dir);

    // Download to OUT_DIR instead of source directory
    let libgodot_dir = out_path.join("libgodot");
    let libgodot_path = libgodot_dir
        .join("libgodot.xcframework")
        .join("macos-arm64_x86_64");

    let dylib_path = libgodot_path.join("libgodot.dylib");

    if !dylib_path.exists() {
        println!(
            "cargo:warning=libgodot.dylib not found, downloading from SwiftGodotKit releases..."
        );
        download_libgodot(&libgodot_dir);
    }

    println!("cargo:rustc-link-search=native={}", libgodot_path.display());

    copy_dylib_to_target_dir(&dylib_path);

    println!("cargo:rustc-link-lib=dylib=godot");

    println!(
        "cargo:rustc-link-arg=-Wl,-rpath,{}",
        libgodot_path.display()
    );

    let target_dir = env::var("CARGO_TARGET_DIR")
        .map(PathBuf::from)
        .or_else(|_| {
            env::var("OUT_DIR")
                .map(|out| PathBuf::from(out).ancestors().nth(4).unwrap().to_path_buf())
        })
        .unwrap_or_else(|_| PathBuf::from("target"));

    let debug_dir = target_dir.join("debug");
    println!("cargo:rustc-link-arg=-Wl,-rpath,{}", debug_dir.display());

    println!(
        "cargo:warning=Linking against libgodot.dylib for {} on macOS",
        target_arch
    );
}

fn copy_dylib_to_target_dir(src_dylib: &Path) {
    let target_dir = env::var("CARGO_TARGET_DIR")
        .map(PathBuf::from)
        .or_else(|_| {
            env::var("OUT_DIR")
                .map(|out| PathBuf::from(out).ancestors().nth(4).unwrap().to_path_buf())
        })
        .unwrap_or_else(|_| PathBuf::from("target"));

    let debug_dir = target_dir.join("debug");

    if let Err(e) = std::fs::create_dir_all(&debug_dir) {
        eprintln!("Warning: Failed to create debug directory: {}", e);
        return;
    }

    if src_dylib.exists() {
        let deps_dir = debug_dir.join("deps");
        if let Ok(()) = std::fs::create_dir_all(&deps_dir) {
            let deps_dylib = deps_dir.join("libgodot.dylib");
            if let Err(e) = std::fs::copy(src_dylib, &deps_dylib) {
                eprintln!(
                    "Warning: Failed to copy libgodot.dylib to deps directory: {}",
                    e
                );
            } else {
                println!(
                    "cargo:warning=Copied libgodot.dylib to {}",
                    deps_dylib.display()
                );
            }
        }
    }
}

fn download_libgodot(libgodot_dir: &Path) {
    use std::process::Command;

    if let Err(e) = std::fs::create_dir_all(libgodot_dir) {
        panic!("Failed to create libgodot directory: {}", e);
    }

    let zip_path = libgodot_dir.join("libgodot.xcframework.zip");
    let url = "https://github.com/migueldeicaza/SwiftGodotKit/releases/download/4.3.5/libgodot.xcframework.zip";

    println!("cargo:warning=Downloading libgodot from: {}", url);

    let download_result = Command::new("curl")
        .args(["-L", "-o", zip_path.to_str().unwrap(), url])
        .status();

    match download_result {
        Ok(status) => {
            if !status.success() {
                panic!("Failed to download libgodot.xcframework.zip");
            }
        }
        Err(e) => {
            panic!(
                "Failed to run curl command: {}. Please ensure curl is installed.",
                e
            );
        }
    }

    let extract_result = Command::new("unzip")
        .args([
            "-o",
            zip_path.to_str().unwrap(),
            "-d",
            libgodot_dir.to_str().unwrap(),
        ])
        .status();

    match extract_result {
        Ok(status) => {
            if !status.success() {
                panic!("Failed to extract libgodot.xcframework.zip");
            }
        }
        Err(e) => {
            panic!(
                "Failed to run unzip command: {}. Please ensure unzip is installed.",
                e
            );
        }
    }

    if let Err(e) = std::fs::remove_file(&zip_path) {
        println!("cargo:warning=Failed to remove zip file: {}", e);
    }

    println!("cargo:warning=Successfully downloaded and extracted libgodot.xcframework");
}