|
| 1 | +#!/usr/bin/env python3 |
| 2 | +import os |
| 3 | +import subprocess |
| 4 | +import shutil |
| 5 | +import sys |
| 6 | + |
| 7 | +print("=== Building Rust FFI Library for All Platforms ===") |
| 8 | + |
| 9 | +# Get the directory where this script is located |
| 10 | +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) |
| 11 | +os.chdir(SCRIPT_DIR) |
| 12 | + |
| 13 | +# Destination base directory |
| 14 | +DEST_BASE = os.path.abspath("../src/main/resources/assets/optimizationsandtweaks/natives") |
| 15 | + |
| 16 | +# Setup osxcross PATH if available |
| 17 | +OSXCROSS_PATH = os.path.expanduser("~/osxcross/target/bin") |
| 18 | +if os.path.isdir(OSXCROSS_PATH): |
| 19 | + os.environ["PATH"] = f"{OSXCROSS_PATH}:{os.environ.get('PATH', '')}" |
| 20 | + print(f"✓ osxcross found at {OSXCROSS_PATH}") |
| 21 | + |
| 22 | +def run(cmd, check=True): |
| 23 | + print(f"$ {' '.join(cmd)}") |
| 24 | + subprocess.run(cmd, check=check) |
| 25 | + |
| 26 | +def check_target(target): |
| 27 | + result = subprocess.run(["rustup", "target", "list"], capture_output=True, text=True) |
| 28 | + if f"{target} (installed)" not in result.stdout: |
| 29 | + print(f"Installing target {target}...") |
| 30 | + run(["rustup", "target", "add", target]) |
| 31 | + |
| 32 | +def build_for_target(target, os_dir, lib_name): |
| 33 | + print(f"\n=== Building for {target} ===") |
| 34 | + run(["cargo", "build", "--release", "--target", target]) |
| 35 | + |
| 36 | + dest_dir = os.path.join(DEST_BASE, os_dir) |
| 37 | + os.makedirs(dest_dir, exist_ok=True) |
| 38 | + |
| 39 | + # Try with "lib" prefix first (Linux/macOS convention) |
| 40 | + src_path = os.path.join(SCRIPT_DIR, "target", target, "release", lib_name) |
| 41 | + src_path_with_lib = os.path.join(SCRIPT_DIR, "target", target, "release", f"lib{lib_name}") |
| 42 | + |
| 43 | + # Check which file exists |
| 44 | + if os.path.isfile(src_path_with_lib): |
| 45 | + src_path = src_path_with_lib |
| 46 | + elif not os.path.isfile(src_path): |
| 47 | + print(f"✗ Warning: Library not found at {src_path} or {src_path_with_lib}") |
| 48 | + return |
| 49 | + |
| 50 | + dest_path = os.path.join(dest_dir, lib_name) |
| 51 | + shutil.copy2(src_path, dest_path) |
| 52 | + print(f"✓ Copied {lib_name} to {dest_path}") |
| 53 | + |
| 54 | +# Linux x86_64 |
| 55 | +check_target("x86_64-unknown-linux-gnu") |
| 56 | +build_for_target("x86_64-unknown-linux-gnu", "linux", "liboptimizationsandtweaks_pathfinding.so") |
| 57 | + |
| 58 | +# Windows x86_64 |
| 59 | +check_target("x86_64-pc-windows-gnu") |
| 60 | +if shutil.which("x86_64-w64-mingw32-gcc"): |
| 61 | + build_for_target("x86_64-pc-windows-gnu", "windows", "optimizationsandtweaks_pathfinding.dll") |
| 62 | +else: |
| 63 | + print("⚠ Warning: MinGW-w64 not found. Skipping Windows build.\n Install with: sudo apt-get install mingw-w64") |
| 64 | + |
| 65 | +# macOS - Build both architectures and create universal binary |
| 66 | +macos_x86_built = False |
| 67 | +macos_arm_built = False |
| 68 | + |
| 69 | +check_target("x86_64-apple-darwin") |
| 70 | +if sys.platform == "darwin" or shutil.which("x86_64-apple-darwin23.5-clang"): |
| 71 | + print("\n=== Building for x86_64-apple-darwin ===") |
| 72 | + run(["cargo", "build", "--release", "--target", "x86_64-apple-darwin"]) |
| 73 | + macos_x86_built = True |
| 74 | +else: |
| 75 | + print("⚠ Warning: macOS x86_64 build requires macOS host or osxcross. Skipping.") |
| 76 | + |
| 77 | +check_target("aarch64-apple-darwin") |
| 78 | +if sys.platform == "darwin" or shutil.which("aarch64-apple-darwin23.5-clang"): |
| 79 | + print("\n=== Building for aarch64-apple-darwin ===") |
| 80 | + run(["cargo", "build", "--release", "--target", "aarch64-apple-darwin"]) |
| 81 | + macos_arm_built = True |
| 82 | +else: |
| 83 | + print("⚠ Warning: macOS ARM64 build requires macOS host or osxcross. Skipping.") |
| 84 | + |
| 85 | +# Create universal binary if both architectures were built |
| 86 | +if macos_x86_built and macos_arm_built: |
| 87 | + print("\n=== Creating macOS Universal Binary ===") |
| 88 | + dest_dir = os.path.join(DEST_BASE, "macos") |
| 89 | + os.makedirs(dest_dir, exist_ok=True) |
| 90 | + |
| 91 | + x86_lib = os.path.join(SCRIPT_DIR, "target", "x86_64-apple-darwin", "release", "liboptimizationsandtweaks_pathfinding.dylib") |
| 92 | + arm_lib = os.path.join(SCRIPT_DIR, "target", "aarch64-apple-darwin", "release", "liboptimizationsandtweaks_pathfinding.dylib") |
| 93 | + universal_lib = os.path.join(dest_dir, "liboptimizationsandtweaks_pathfinding.dylib") |
| 94 | + |
| 95 | + if shutil.which("lipo"): |
| 96 | + run(["lipo", "-create", "-output", universal_lib, x86_lib, arm_lib]) |
| 97 | + print(f"✓ Created universal binary at {universal_lib}") |
| 98 | + else: |
| 99 | + print("⚠ Warning: 'lipo' not found. Copying ARM64 version only.") |
| 100 | + shutil.copy2(arm_lib, universal_lib) |
| 101 | + print(f"✓ Copied ARM64 library to {universal_lib}") |
| 102 | +elif macos_x86_built: |
| 103 | + dest_dir = os.path.join(DEST_BASE, "macos") |
| 104 | + os.makedirs(dest_dir, exist_ok=True) |
| 105 | + x86_lib = os.path.join(SCRIPT_DIR, "target", "x86_64-apple-darwin", "release", "liboptimizationsandtweaks_pathfinding.dylib") |
| 106 | + dest_path = os.path.join(dest_dir, "liboptimizationsandtweaks_pathfinding.dylib") |
| 107 | + shutil.copy2(x86_lib, dest_path) |
| 108 | + print(f"✓ Copied x86_64 library to {dest_path}") |
| 109 | +elif macos_arm_built: |
| 110 | + dest_dir = os.path.join(DEST_BASE, "macos") |
| 111 | + os.makedirs(dest_dir, exist_ok=True) |
| 112 | + arm_lib = os.path.join(SCRIPT_DIR, "target", "aarch64-apple-darwin", "release", "liboptimizationsandtweaks_pathfinding.dylib") |
| 113 | + dest_path = os.path.join(dest_dir, "liboptimizationsandtweaks_pathfinding.dylib") |
| 114 | + shutil.copy2(arm_lib, dest_path) |
| 115 | + print(f"✓ Copied ARM64 library to {dest_path}") |
| 116 | + |
| 117 | +print("\n=== Build Complete ===") |
| 118 | +print(f"Native libraries have been copied to:\n {DEST_BASE}/linux/\n {DEST_BASE}/windows/\n {DEST_BASE}/macos/") |
0 commit comments