Skip to content

macOS and iOS

macOS and iOS come from one plugin, with the same sources and the same Metal backend, so one setup covers both. It’s also the most travelled route: CI draws a frame on macOS on every change to the engine.

A Mac with Apple silicon Not an Intel one
Xcode With its command line tools. For iOS, also the iOS platform and a simulator, both installed from Xcode
CocoaPods Only if your project uses it rather than Swift Package Manager. See below

The oldest systems your app can target are macOS 10.15 and iOS 13. They’re Flutter’s own defaults, so a new project needs no change.

Flutter 3.47 builds Apple plugins with Swift Package Manager by default, and a Swift package can’t run a script that downloads anything, because package plugins run sandboxed with no network. So on a Mac, the setup is the one step Flutter doesn’t do for you. Run it once, after flutter pub get:

Terminal window
flutter pub get
for setup in "${PUB_CACHE:-$HOME/.pub-cache}"/git/orblit-*/packages/orblit_filament/darwin/setup.sh; do
bash "$setup"
done

Pub keeps a git dependency in a cache directory named after the commit, such as ~/.pub-cache/git/orblit-45f41842…/, which is why the loop goes looking for it rather than naming it. The script downloads Filament’s Mac and iOS releases (44 MB and 30 MB), compiles the materials, and packages the lot as one Filament.xcframework with slices for macOS, iOS devices and the iOS simulator. It took 24 seconds here, on a fast connection, and leaves about 290 MB on disk.

If you skip it, the build fails with an error that doesn’t mention setup at all:

error: When building for macOS, the expected library
…/orblit_filament/third_party/Filament.xcframework/macos-arm64/macos.a
was not found

That means the setup hasn’t run for the engine commit your app is on. Run the loop and build again.

If your project uses CocoaPods instead (flutter config --no-enable-swift-package-manager), the podspec runs the same script itself, as a prepare_command, when CocoaPods installs the pod. That covers the first build.

The trap is when it doesn’t run again. Flutter only runs pod install when it thinks your pods have changed, and new materials in the same copy of the engine don’t count. That’s what you get from a path dependency on a clone after a git pull. The build then fails with 'generated/<name>_material.h' file not found. Run packages/orblit_filament/darwin/setup.sh in that clone and it builds.

Switching a project between Swift Package Manager and CocoaPods needs a flutter clean in between.

Terminal window
flutter run -d macos

For iOS, open a simulator and run on it by its id:

Terminal window
open -a Simulator
flutter devices # copy the simulator's id from here
flutter run -d <id>

The iOS simulator draws with a slimmer lit surface than macOS does. Its virtual GPU reports Filament feature level 2, and the standard surface needs level 3, so the renderer picks one with nine samplers instead of twelve. It keeps every map, ground blending and decals, and gives up rectangular lights’ shadows and the irradiance field.

A device with an A13 or newer, which is an iPhone 11 or later, reports level 3 and gets the standard surface. That hasn’t been run, because it needs a signing identity. CI builds for the simulator only. To run on a phone, set your team under Signing & Capabilities in ios/Runner.xcworkspace first, as for any Flutter app, and please say on the Discord how it went.

Filament’s Mac release is built for arm64 only, and that includes matc, the material compiler, which has to run on the machine doing the build. So an Intel Mac can’t run the setup for macOS or iOS, and nor can it build for Android, which borrows the Mac’s matc. The plugin also leaves x86_64 out of its macOS build, so an app that uses it is an Apple silicon app.

The web build uses a matc you compile yourself, so it might work on an Intel Mac. Nobody has tried. The Linux container described under Linux is another way round it, and that hasn’t been tried on an Intel Mac either.