# 🌍 Cross-Platform Development Guide

How to build and distribute Nyash applications across Windows, Linux, and macOS.

## 🎯 Philosophy: Write Once, Run Everywhere

Nyash achieves true cross-platform compatibility through:
- **Platform-agnostic configuration** (nyash.toml)
- **Automatic library resolution** (plugin loader)
- **Unified plugin system** (C ABI)

## 🔄 Cross-Platform Plugin Loading

### The Magic Behind It

ChatGPT5's `resolve_library_path` implementation in `src/runtime/plugin_loader_v2.rs`:

```rust
// Automatic extension mapping
let cur_ext: &str = if cfg!(target_os = "windows") { "dll" } 
                   else if cfg!(target_os = "macos") { "dylib" } 
                   else { "so" };

// Windows: try without 'lib' prefix
if cfg!(target_os = "windows") {
    if let Some(stripped) = stem.strip_prefix("lib") {
        // Try nyash_plugin.dll instead of libnyash_plugin.dll
    }
}
```

### Configuration That Works Everywhere

```toml
# nyash.toml - Same file works on all platforms!
[libraries."libnyash_filebox_plugin.so"]
boxes = ["FileBox"]
path = "libnyash_filebox_plugin.so"  # .so works everywhere!
```

**Runtime Resolution:**
- Linux: `libnyash_filebox_plugin.so` ✅
- Windows: `nyash_filebox_plugin.dll` ✅ (lib prefix removed)
- macOS: `libnyash_filebox_plugin.dylib` ✅

## 🏗️ Building for Multiple Platforms

### From Linux/WSL (Recommended Hub)

```bash
# For Linux (native)
cargo build --release

# For Windows
cargo xwin build --target x86_64-pc-windows-msvc --release

# For macOS (requires macOS SDK)
# cargo build --target x86_64-apple-darwin --release
```

### Build Matrix

| Host OS | Target | Tool | Command |
|---------|--------|------|---------|
| Linux/WSL | Linux | cargo | `cargo build --release` |
| Linux/WSL | Windows | cargo-xwin | `cargo xwin build --target x86_64-pc-windows-msvc` |
| Windows | Windows | cargo | `cargo build --release` |
| Windows | Linux | cross | `cross build --target x86_64-unknown-linux-gnu` |
| macOS | macOS | cargo | `cargo build --release` |
| macOS | Linux | cross | `cross build --target x86_64-unknown-linux-gnu` |

## 📦 Creating Universal Distributions

### Directory Structure
```
nyash-universal/
├── bin/
│   ├── linux/
│   │   └── nyash
│   ├── windows/
│   │   └── nyash.exe
│   └── macos/
│       └── nyash
├── plugins/
│   ├── linux/
│   │   ├── libnyash_filebox_plugin.so
│   │   └── ...
│   ├── windows/
│   │   ├── nyash_filebox_plugin.dll
│   │   └── ...
│   └── macos/
│       ├── libnyash_filebox_plugin.dylib
│       └── ...
├── nyash.toml          # Universal config
├── examples/
└── README.md
```

### Universal Launcher Script

Create `run.sh` (Linux/macOS) and `run.bat` (Windows):

**run.sh:**
```bash
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
OS="$(uname -s)"

case "$OS" in
    Linux*)  BIN="linux/nyash" ;;
    Darwin*) BIN="macos/nyash" ;;
    *)       echo "Unsupported OS: $OS"; exit 1 ;;
esac

export NYASH_PLUGIN_PATH="$SCRIPT_DIR/plugins/$(echo $OS | tr '[:upper:]' '[:lower:]')"
"$SCRIPT_DIR/bin/$BIN" "$@"
```

**run.bat:**
```batch
@echo off
set SCRIPT_DIR=%~dp0
set NYASH_PLUGIN_PATH=%SCRIPT_DIR%plugins\windows
"%SCRIPT_DIR%bin\windows\nyash.exe" %*
```

## 🔌 Plugin Compatibility

### Building Plugins for All Platforms

Automated build script (`build_all_plugins.sh`):

```bash
#!/bin/bash
PLUGINS="filebox array map string integer net"

for plugin in $PLUGINS; do
    echo "Building $plugin plugin..."
    cd "plugins/nyash-$plugin-plugin" || exit 1
    
    # Linux
    cargo build --release
    cp target/release/lib*.so ../../dist/plugins/linux/
    
    # Windows (from WSL)
    cargo xwin build --target x86_64-pc-windows-msvc --release
    cp target/x86_64-pc-windows-msvc/release/*.dll ../../dist/plugins/windows/
    
    cd ../..
done
```

### Plugin ABI Stability

The C ABI ensures plugins work across platforms:

```c
// Standard C ABI functions (same on all platforms)
extern "C" {
    fn nyash_plugin_abi_version() -> u32;
    fn nyash_plugin_init(host_fns: *const HostFunctions) -> i32;
    fn nyash_plugin_invoke(params: *const InvokeParams) -> i32;
    fn nyash_plugin_shutdown();
}
```

## 🎯 Testing Cross-Platform Builds

### Test Matrix Script

```bash
#!/bin/bash
# test_all_platforms.sh

echo "=== Testing Linux Build ==="
./target/release/nyash test/cross_platform.hako

echo "=== Testing Windows Build (Wine) ==="
wine ./target/x86_64-pc-windows-msvc/release/nyash.exe test/cross_platform.hako

echo "=== Testing WASM Build ==="
wasmtime ./target/wasm32-wasi/release/nyash.wasm test/cross_platform.hako
```

### Cross-Platform Test Program

```nyash
// test/cross_platform.hako
print("Platform Test Starting...")

// Test basic plugins
local arr = new ArrayBox()
arr.push("Cross")
arr.push("Platform")
arr.push("Success!")
print("Array test: " + arr.get(0) + "-" + arr.get(1) + " " + arr.get(2))

// Test file operations (platform-specific paths)
local file = new FileBox()
if file {
    print("FileBox available on this platform")
}

print("✅ All tests passed!")
```

## 🚀 CI/CD for Cross-Platform

### GitHub Actions Example

```yaml
name: Cross-Platform Build

on: [push, pull_request]

jobs:
  build:
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
          - os: windows-latest
            target: x86_64-pc-windows-msvc
          - os: macos-latest
            target: x86_64-apple-darwin
    
    runs-on: ${{ matrix.os }}
    
    steps:
    - uses: actions/checkout@v2
    
    - name: Install Rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable
        target: ${{ matrix.target }}
    
    - name: Build
      run: cargo build --release --target ${{ matrix.target }}
    
    - name: Test
      run: cargo test --release --target ${{ matrix.target }}
    
    - name: Upload artifacts
      uses: actions/upload-artifact@v2
      with:
        name: nyash-${{ matrix.target }}
        path: target/${{ matrix.target }}/release/nyash*
```

## 💡 Best Practices

### 1. Always Test on Target Platform
```bash
# Quick test after cross-compile
wine ./nyash.exe --version  # Windows binary on Linux
```

### 2. Use Platform-Agnostic Paths
```nyash
// Bad
local file = new FileBox()
file.open("C:\\data\\file.txt", "r")  // Windows-specific

// Good
local file = new FileBox()
file.open("./data/file.txt", "r")  // Works everywhere
```

### 3. Handle Platform Differences Gracefully
```nyash
box PlatformHelper {
    static getPlatformName() {
        // Future: return actual platform
        return "universal"
    }
    
    static getPathSeparator() {
        // Future: return platform-specific separator
        return "/"
    }
}
```

## 🔧 Troubleshooting

### "Can't find plugin" after cross-compile
- Check file naming (lib prefix on Windows)
- Verify correct architecture (x86_64 vs ARM)
- Use `--verbose` flag for detailed logs

### Different behavior across platforms
- File path separators (`/` vs `\`)
- Case sensitivity (Linux/macOS vs Windows)
- Line endings (LF vs CRLF)

### Performance variations
- Debug vs Release builds
- Native CPU optimizations
- Plugin loading overhead

## 📚 References

- [Plugin System Architecture](../../reference/plugin-system/)
- [Build Configuration](README.md)
- [Platform-Specific Notes](../../reference/platform-notes.md)