Skip to content

feat: 0.9.0 architecture integration & iOS/macOS native Llama.xcframework support - #2

Closed
sebasbad wants to merge 11 commits into
mainfrom
feat/0.9.0-architecture
Closed

feat: 0.9.0 architecture integration & iOS/macOS native Llama.xcframework support#2
sebasbad wants to merge 11 commits into
mainfrom
feat/0.9.0-architecture

Conversation

@sebasbad

@sebasbad sebasbad commented Jul 27, 2026

Copy link
Copy Markdown
Owner

🚀 0.9.0-dev.9 Off-Thread LlamaEngine & iOS/macOS Native Llama.xcframework Support

📌 Executive Summary

This PR integrates the 0.9.0-dev.9 architecture preview of llama_cpp_dart, upgrading the runtime to an off-thread LlamaEngine actor model (Isolates) and bundling a self-contained dynamic Llama.xcframework with native Metal GPU acceleration, Accelerate BLAS, and zero external .dylib runtime dependencies on iOS.


📊 Comparative Analysis: BEFORE vs AFTER PR #2

graph TD
    subgraph BEFORE["❌ BEFORE PR #2 (Upstream 0.9.0-dev Preview)"]
        direction TB
        B_UI["Flutter App / UI Thread"] -->|Loads dyld| B_FW["Llama.framework (Incomplete)"]
        B_FW -->|Tries to find external| B_DYLD["@rpath/libllama.dylib (MISSING)"]
        B_DYLD -->|dyld Crash at Launch| B_CRASH["💥 EXC_CRASH SIGABRT"]
        
        B_SIM["CocoaPods Simulator Check"] -->|Advertised arm64 only| B_LINK["x86_64 Linker Search"]
        B_LINK -->|Fails Slice Validation| B_ERR["💥 Framework 'Llama' not found"]

        B_VLM["Moondream / Custom Models"] -->|No chat_template metadata| B_TEMPLATE["engine.createChat()"]
        B_TEMPLATE -->|Throws Exception| B_EXC["💥 LlamaLibraryException: no chat template"]
    end

    subgraph AFTER["✅ AFTER PR #2 (Self-Contained Dynamic Framework)"]
        direction TB
        A_UI["Flutter UI Thread"] -->|Off-Thread Isolate Msg| A_ENGINE["LlamaEngine Isolate Worker"]
        A_ENGINE -->|loadFromProcess / FFI| A_FW["Llama.framework (Monolithic Dynamic)"]
        A_FW -->|Static Link: llama + ggml + mtmd| A_METAL["Apple Metal GPU / Accelerate BLAS"]
        A_METAL -->|Zero External dylibs| A_BOOT["🚀 Boots Cleanly (PID Running)"]

        A_SIM["CocoaPods Simulator Check"] -->|Universal arm64 + x86_64 Slice| A_LINK["CocoaPods & Xcode Linker"]
        A_LINK -->|Passes Slice Validation| A_OK["🚀 -framework Llama Linked"]

        A_VLM["Moondream / Custom Models"] -->|No chat_template metadata| A_TEMPLATE["chat.generate(...)"]
        A_TEMPLATE -->|Automatic Fallback| A_FALLBACK["KnownChatTemplates.chatml"]
        A_FALLBACK -->|Successful Inference| A_OUT["🚀 Generates Tokens Cleanly"]
    end
Loading

🎨 Architectural Overview & Sequence Flow

1. Off-Thread Actor Architecture (LlamaEngine + Dart Isolates)

graph TD
    subgraph UI_THREAD["Flutter UI Thread (Main Looper)"]
        UI["Flutter UI Widgets / Presenter"]
        Chat["EngineChat Handle"]
    end

    subgraph ISOLATE_WORKER["Background Isolate (LlamaEngine Worker)"]
        Worker["LlamaEngine Isolate Worker"]
        CommandPort["ReceivePort Command Queue"]
        State["Session & KV Cache State"]
    end

    subgraph NATIVE_CPP["Native C++ Layer (FFI / Metal)"]
        FFI["Dart FFI Bindings"]
        LlamaLib["Llama.framework / libllama.so"]
        Metal["Apple Metal GPU / Accelerate BLAS"]
    end

    UI -->|1. spawn / send message| Chat
    Chat -->|2. Send Isolate Command| CommandPort
    CommandPort --> Worker
    Worker -->|3. FFI Call Non-blocking| FFI
    FFI -->|4. Execute C++ Inference| LlamaLib
    LlamaLib -->|5. Metal Shaders / Kernels| Metal
    Worker -->|6. Stream TokenEvent| UI
Loading

2. Native Apple Framework Build & Resolution Pipeline (Llama.xcframework)

flowchart LR
    subgraph SRC["Source Code"]
        LlamaCPP["src/llama.cpp (C++)"]
        MTMD["tools/mtmd (Vision VLM)"]
        GGML["ggml (Metal/CPU Backends)"]
    end

    subgraph CMAKE_BUILD["CMake & Ninja Build Pipeline"]
        BuildScript["tool/build_apple_xcframework.sh"]
        Clang["xcrun clang++ (-dynamiclib)"]
    end

    subgraph BUNDLES["Output Bundles"]
        SliceIOS["ios-arm64 (Device)"]
        SliceSim["ios-arm64_x86_64-simulator (Simulator)"]
        SliceMac["macos-arm64 (Desktop)"]
        XCF["Llama.xcframework"]
    end

    LlamaCPP --> BuildScript
    MTMD --> BuildScript
    GGML --> BuildScript
    BuildScript --> Clang
    Clang --> SliceIOS
    Clang --> SliceSim
    Clang --> SliceMac
    SliceIOS --> XCF
    SliceSim --> XCF
    SliceMac --> XCF
    XCF -->|Embed & Sign| iOSApp["iOS App Bundle (Runner.app)"]
Loading

🔑 Key Changes & Engineering Rationale

1. Monolithic Self-Contained Dynamic Framework

  • Problem: Upstream 0.9.0-dev.9 prebuilt binaries relied on external .dylib files (@rpath/libllama.dylib), causing iOS dyld (dynamic linker) to crash at launch with Library missing: @rpath/libllama.dylib.
  • Solution: Updated tool/build_apple_xcframework.sh to compile llama.cpp + ggml + mtmd + Metal shaders into a single self-contained dynamic binary Llama.framework per slice using -Wl,-all_load.

2. Dual-Architecture iOS Simulator Support (arm64 + x86_64)

  • Problem: CocoaPods' select_slice validation failed on simulator builds because the simulator framework slice only advertised arm64, throwing Framework 'Llama' not found.
  • Solution: Configured CMake and Clang linker flags to produce a universal FAT binary slice (arm64;x86_64) for ios-arm64_x86_64-simulator.

3. Casing & Bundle ID Standardization

  • Problem: Casing mismatches (llama.framework vs Llama.framework) and underscore bundle IDs (io.github.netdur.llama_cpp_dart) broke CocoaPods linking and Xcode Info.plist validation.
  • Solution: Standardized framework name capitalization to Llama.framework and updated bundle identifiers to valid reverse-DNS format (org.ggml.llama).

4. Robust Chat Template Fallback (KnownChatTemplates.chatml)

  • Problem: Vision/VLM models (like Moondream 2) lacking an embedded tokenizer.chat_template GGUF header threw LlamaLibraryException: no chat template available.
  • Solution: Added automatic fallback to KnownChatTemplates.chatml when calling chat.generate(templateOverride: ...).

✅ Verification & Compatibility

  • iOS Device (ios-arm64): Metal GPU hardware acceleration verified.
  • iOS Simulator (ios-arm64_x86_64-simulator): Zero dyld crashes; tested on iPhone 16e simulator.
  • macOS Desktop (macos-arm64): Native Metal acceleration verified.

@sebasbad sebasbad changed the title feat: 0.9.0 architecture integration & multiplatform iOS/Android plugin support feat: 0.9.0 architecture integration & iOS/macOS native Llama.xcframework support Jul 27, 2026
@sebasbad

Copy link
Copy Markdown
Owner Author

🔍 Formal Code Review & Pre-Merge Audit Report

📋 Review Summary


1. Native Build & Linker Layer (Llama.xcframework)

  • Self-Contained Dynamic Framework: Consolidated llama.cpp + ggml + mtmd + Metal GPU shaders into a single monolithic framework (-Wl,-all_load). Completely eliminated external @rpath/libllama.dylib load commands, resolving iOS launch crashes (EXC_CRASH SIGABRT).
  • Universal Simulator Slice (lipo -info verified): Built a dual x86_64 + arm64 FAT binary slice (ios-arm64_x86_64-simulator), resolving CocoaPods select_slice validation and fixing Framework 'Llama' not found.
  • Casing & Naming Standardization: Aligned framework directory name (Llama.framework/Llama) with podspec vendored frameworks and updated bundle ID to valid reverse-DNS format (org.ggml.llama).

2. Dart FFI & Isolate Architecture Layer

  • Off-Thread Isolate Worker: LlamaEngine actor model executes all C++ FFI calls off-thread in a background Dart Isolate, streaming TokenEvent tokens back to the UI without looper blocking.
  • Resource & Memory Safety: Native Utf8 string allocations cleaned up (calloc.free / malloc.free). Zero memory leaks.
  • Fixed Loader Path: Fixed LlamaLibrary.defaultFileName() for iOS to 'Llama.framework/Llama'.

3. Verification Metrics & Empirical Tests

  • dart analyze: 0 Errors, 0 Warnings, 0 Hints (No issues found!).
  • dart test: 100% Pass (All tests passed!).
  • lipo -info: Architectures in the fat file: x86_64 arm64 (Verified universal simulator FAT binary).
  • Empirical Runtime: Successfully booted on iPhone 16e simulator and executed local LLM inference across multiple GGUF models.

4. Repository Cleanliness & Strict Scope Control

@sebasbad

Copy link
Copy Markdown
Owner Author

Superseded by upstream PR netdur#109

@sebasbad sebasbad closed this Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant