Skip to content

avwohl/iospharo

Repository files navigation

iospharo

A Pharo Smalltalk VM for iOS and macOS, written as a clean C++ interpreter.

Overview

iospharo runs standard Pharo 13 and Pharo 14 images on iOS devices and Mac (via Catalyst). It is a from-scratch interpreter implementation — not a port of the Cog JIT VM — with full support for the Sista V1 bytecode set, FFI with callbacks, and the standard Pharo test suite.

Note: Pharo 12 and earlier use a different class table layout that the VM does not yet handle.

Status

VM core (solid):

  • 99.90% test pass rate on Mac Catalyst (13,040 / 13,053)
  • 99.55% test pass rate on iOS Simulator
  • FFI with callbacks (sigsetjmp/siglongjmp)
  • All standard VM plugins built-in (B2D, JPEG, DSA, SSL, etc.)
  • Third-party libraries: cairo, freetype, harfbuzz, pixman, libpng, OpenSSL, libssh2, libgit2

GUI (working):

  • Metal rendering pipeline — Pharo desktop renders correctly
  • Menu bar, world menu, and context menus all functional
  • Touch-to-mouse event translation (tap, long-press, two-finger, pinch, drag)
  • Hardware keyboard support with modifier keys
  • Image library with download, import, and catalog management

Install from the App Store

Available for iPad, iPhone, and Mac:

Download on the App Store

Requirements:

  • iPad (5th gen / 2017 or newer) or iPhone (6s / 2015 or newer) or Mac (Apple Silicon or Intel)
  • iOS / iPadOS 15.0 or later, macOS 14.0 or later
  • ~150 MB free storage (app + image + sources)

Pharo images are downloaded in-app (no separate download needed).

Beta Testing (TestFlight)

There may be a newer pre-release version available via TestFlight:

  1. Install TestFlight from the App Store (free, ~30 MB)
  2. Open this invite link on your iPad or iPhone: Join the Beta
  3. Tap "Accept" then "Install" — the app appears on your home screen

TestFlight builds expire after 90 days but auto-update when new builds are published.

Prerequisites

Install these before building:

# Xcode command-line tools (includes clang, make, etc.)
xcode-select --install

# CMake (build system)
brew install cmake

# For third-party library builds (cairo, freetype, etc.)
brew install meson ninja pkg-config autoconf automake libtool

You also need:

Building

Step 1: Build libffi and SDL2 xcframeworks

scripts/build-libffi.sh
scripts/build-sdl2.sh

This downloads, cross-compiles, and packages libffi (FFI/callbacks) and SDL2 (display driver) as xcframeworks for iOS device, simulator, Mac Catalyst, and macOS. Takes about 10 minutes. The xcframeworks are gitignored due to size.

Step 2: Build third-party libraries

Cairo, freetype, harfbuzz, pixman, libpng, OpenSSL, libssh2, and libgit2 are cross-compiled as static xcframeworks:

scripts/build-third-party.sh

This downloads source tarballs and builds for iOS device, Simulator, and Mac Catalyst. Takes about 15 minutes on first run. Use --no-crypto to skip OpenSSL and libssh2 (libgit2 is always built for local repository support).

Step 3: Build the app

open iospharo.xcodeproj

Select your target (iOS device, Simulator, or My Mac - Catalyst) and build.

Xcode has a "Check XCFramework Freshness" build phase that automatically runs scripts/build-xcframework.sh whenever VM source files (src/vm/, src/platform/) are newer than the xcframework. The first Xcode build will take several minutes while it compiles the VM; subsequent builds are fast unless you change VM sources.

To manually rebuild the VM xcframework (e.g. after a git pull):

scripts/build-xcframework.sh

This produces Frameworks/PharoVMCore.xcframework with slices for iOS device (arm64), iOS Simulator (arm64 + x86_64), and Mac Catalyst (arm64 + x86_64).

Code signing (optional): To deploy to a physical device or the App Store, copy Local.xcconfig.example to Local.xcconfig and fill in your Apple Developer Team ID. Local.xcconfig is gitignored.

Quick development build (Mac only)

For faster iteration on VM internals. This builds a headless command-line binary (not the iOS/Catalyst app). Requires Steps 1 and 2 above — the cmake build links against the xcframeworks in Frameworks/.

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

# Run headless with a Pharo image
./build/test_load_image /path/to/Pharo.image

Project Structure

iospharo/
├── src/vm/           C++ VM: Interpreter, ObjectMemory, Primitives, FFI
├── src/include/      VM headers (vmCallback.h, etc.)
├── src/platform/     Platform abstraction (EventQueue, display)
├── src/ios/          Generated interpreter reference (cointerp-cpp.c)
├── iospharo/         SwiftUI app (Metal renderer, bridge, views)
├── scripts/          Build scripts (VM xcframework, third-party libraries)
├── docs/             Technical reference (bytecode spec, architecture)
├── Frameworks/       Built xcframeworks (gitignored)
└── CMakeLists.txt    CMake build for the VM library

Architecture

┌─────────────────────────────┐
│   SwiftUI App               │
│   (ContentView, Settings)   │
├─────────────────────────────┤
│   PharoBridge.swift         │  VM lifecycle, event bridge
├─────────────────────────────┤
│   MetalRenderer.swift       │  GPU display rendering
├─────────────────────────────┤
│   C++ Interpreter           │  Sista V1 bytecodes, GC,
│   (libPharoVMCore.a)        │  FFI, primitives, plugins
└─────────────────────────────┘

The image's OSSDL2Driver calls SDL2 functions via FFI. Our SDL2 stubs bridge these to the Metal rendering pipeline. Touch gestures are mapped to Pharo mouse events (tap=left-click, long-press=right-click, two-finger tap=right-click).

Startup patches

The app applies Smalltalk patches on every launch to fix image bugs and adapt to VM differences (stubbed SDL2, missing font glyphs, etc.). Patches are version-specific — the app detects the Pharo version and loads startup-13.st or startup-14.st accordingly. Users can add custom patches by creating startup-user.st next to the image file (it is never overwritten). See docs/startup-system.md for the full details.

Configuration

VM parameters are set in PharoBridge.swift when calling vm_init():

maxOldSpaceSize 2 GB Max heap (virtual, lazy commit) edenSize 10 MB Young generation size maxCodeSize 0 JIT code space (unused)

Related

  • pharo-headless-test — Run the full Pharo SUnit test suite headless with a fake GUI (click menus, press buttons, take screenshots — no display needed). Extracted from this project but works with any Spur VM. Included here as a submodule at scripts/pharo-headless-test/.

License

MIT — see LICENSE and THIRD_PARTY_LICENSES.

Credits and Acknowledgements

This project would not exist without the decades of work by the Smalltalk community. The VM's interpreter, object memory, and primitives are a clean C++ reimplementation of the architecture defined by the Pharo and Squeak projects.

Pharo and predecessors:

  • Pharo — the Smalltalk environment this VM executes (MIT; Copyright 2008-2019 The Pharo Project, Inria)
  • OpenSmalltalk-VM — the reference VM from which VMMaker-generated plugin code and headers are taken (MIT; Copyright 2013 3D Immersive Collaboration Consulting, LLC)
  • Squeak — the original open source Smalltalk from which Pharo descends (MIT; Copyright 1996-2008 Viewpoints Research Institute, Apple Inc.)

VMMaker-generated plugins included in this repo:

  • BalloonEnginePlugin (B2DPlugin.c) — vector graphics
  • DSAPlugin (DSAPrims.c) — digital signature algorithm
  • JPEGReaderPlugin, JPEGReadWriter2Plugin — JPEG codec wrappers
  • SqueakSSLPlugin (SqueakSSL.c, sqMacSSL.c by Andreas Raab and Tobias Pape)

Bundled libraries:

Statically linked libraries (cross-compiled as xcframeworks):

  • libffi 3.5.2 — Foreign Function Interface (MIT)
  • SDL2 2.26.5 — Simple DirectMedia Layer (zlib)
  • cairo 1.18.2 — 2D graphics (LGPL-2.1 / MPL-1.1)
  • FreeType 2.13.3 — font rendering (FTL)
  • pixman 0.43.4 — pixel manipulation (MIT)
  • HarfBuzz 10.1.0 — text shaping (MIT)
  • libpng 1.6.43 — PNG support (libpng license)
  • OpenSSL 3.4.0 — cryptography (Apache-2.0)
  • libssh2 1.11.1 — SSH client (BSD-3-Clause)
  • libgit2 1.8.4 — Git library (GPL-2.0 with linking exception)

This software is based in part on the work of the Independent JPEG Group.

About

Pharo Smalltalk VM for iOS and Mac Catalyst — interpreter-only (no JIT), with low-bit oop encoding for ASLR compatibility

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors