Skip to content

feat(ios): add --catalyst to build Mac Catalyst apps - #5

Merged
farfromrefug merged 1 commit into
mainfrom
feat/mac-catalyst-builds
Aug 11, 2026
Merged

feat(ios): add --catalyst to build Mac Catalyst apps#5
farfromrefug merged 1 commit into
mainfrom
feat/mac-catalyst-builds

Conversation

@farfromrefug

Copy link
Copy Markdown
Collaborator

Summary

ns build ios --catalyst rebuilds the existing iOS target against the macOS SDK with the Mac Catalyst variant, producing a native macOS .app in platforms/ios/build/<Configuration>-maccatalyst.

Mac Catalyst is a variant of the iOS platform rather than a platform of its own, so this reuses the iOS target instead of introducing a new one. Four things it has to get right:

  • destination, and no -sdk. platform=macOS,variant=Mac Catalyst selects the variant; passing an SDK on top of it makes xcodebuild fall back to iphoneos, so the Catalyst path supplies BUILD_DIR/SHARED_PRECOMPS_DIR directly instead of going through getBuildCommonArgs. Without that the .app lands in DerivedData and the CLI reports "No .app found".
  • SUPPORTS_MACCATALYST=YES is forced, since the runtime template only sets the legacy SUPPORTS_UIKITFORMAC alias.
  • signing goes through -allowProvisioningUpdates. Catalyst needs a macOS provisioning profile, which $iOSSigningService cannot select; Xcode creates it automatically.
  • the deployment target is clamped, not validated. Catalyst starts at iOS 13.1. Failing a project that still targets iOS 12 would force it to drop iOS 12 users just to get a Mac build, so the target is raised for this build only, with a warning. MACCATALYST_DEPLOYMENT_TARGET is passed alongside because the runtime's metadata generator reads it and older runtimes crash when it is unset.

Not included: running the result. ns run <platform> goes through the LiveSync pipeline, which is built around Mobile.IDevice — a Catalyst app is a local .app you open, not a device. Wiring that up means a Mac pseudo-device implementing IDeviceApplicationManager (24 members) and IDeviceFileSystem (34 members) plus device discovery, which belongs in its own PR. For now: open platforms/ios/build/Debug-maccatalyst/<name>.app.

Testing

Built a real app (OSS Weather, iOS deployment target 12.0) from a clean platforms/ios:

$ ns build ios --catalyst
Mac Catalyst requires iOS 13.1 or higher. Building the Mac Catalyst app with IPHONEOS_DEPLOYMENT_TARGET=13.1 instead of the project's 12.0.
Project successfully built.
The build result is located at: .../platforms/ios/build/Debug-maccatalyst/ossweather.app

The .app launches on Apple Silicon as a native macOS app — menu bar, resizable window, weather data loading. All 13 CocoaPods dependencies compiled for arm64-apple-ios-macabi without changes. tsc --noEmit and npm run build are clean.

Note this also needs the runtime-side fixes in Akylas/nativescript-ios-runtime#4 — without them the metadata generator crashes or emits metadata with no UIKit.

`ns build ios --catalyst` rebuilds the existing iOS target against the macOS SDK
with the Mac Catalyst variant, producing a native macOS .app in
`platforms/ios/build/<Configuration>-maccatalyst`.

Mac Catalyst is a variant of the iOS platform rather than a platform of its own,
so this reuses the iOS target instead of introducing a new one:

- destination `platform=macOS,variant=Mac Catalyst`, and no `-sdk` — passing one
  on top of the destination makes xcodebuild fall back to iphoneos
- `SUPPORTS_MACCATALYST=YES` is forced, since the runtime template only sets the
  legacy `SUPPORTS_UIKITFORMAC` alias
- signing goes through `-allowProvisioningUpdates`: Catalyst needs a macOS
  provisioning profile, which the iOS signing service cannot select
- Catalyst starts at iOS 13.1, so the deployment target is clamped for this build
  only (with a warning) rather than failing a project that still targets iOS 12

`MACCATALYST_DEPLOYMENT_TARGET` is passed explicitly because the runtime's
metadata generator reads it and older runtimes crash when it is unset.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@farfromrefug
farfromrefug marked this pull request as ready for review August 11, 2026 08:56
@farfromrefug
farfromrefug merged commit 37e690a into main Aug 11, 2026
7 of 11 checks passed
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