Skip to main content

Phase 18. macOS .app bundle

FieldValue
MEPMEP-49 §Phases · Phase 18
StatusLANDED
Started2026-05-28 13:40 (GMT+7)
Landed2026-05-28 14:44 (GMT+7)
Tracking issue#22463
Tracking PR#22464

Gate

TestPhase18AppStore: 5 fixtures build a macOS binary, call CreateMacOSAppBundle, and validate the .app directory structure (binary exists at Contents/MacOS/<AppName>, Info.plist present, key bundle fields correct). No codesign, notarization, or App Store upload required.

Goal-alignment audit

Phase 18 ships the .app bundle creation layer that wraps a compiled macOS binary in the standard Mach-O bundle layout. This is the prerequisite for distribution via Gatekeeper, code signing, notarization, and eventual Mac App Store submission. Those later steps require Apple Developer credentials and are deferred. The gate validates the structural correctness of the bundle without requiring any signing toolchain.

Sub-phases

#ScopeStatusCommit
18.0MacOSAppConfig; CreateMacOSAppBundle creates Contents/MacOS/<binary> + Contents/Info.plistLANDEDmep/0049-phase-18
18.1generateMacOSInfoPlist: CFBundleName, CFBundleIdentifier, CFBundleExecutable, LSMinimumSystemVersionLANDEDmep/0049-phase-18
18.2CodesignAvailable(), AltoolAvailable() helpersLANDEDmep/0049-phase-18
18.3codesign --deep --options runtime --timestampDEFERRED
18.4xcrun notarytool submit --wait + xcrun stapler stapleDEFERRED
18.5Mac App Store .pkg via productbuild; App Store Connect API uploadDEFERRED

Sub-phase 18.0 -- Bundle creation

Decisions made (18.0)

MacOSAppConfig: struct holding AppName, BundleID, Version, BuildDir, OutputDir.

CreateMacOSAppBundle(cfg, binaryPath) (string, error): creates the bundle directory layout:

<AppName>.app/
Contents/
MacOS/
<AppName> (binary, mode 0755)
Info.plist

The binary is copied (not symlinked) into Contents/MacOS/. The Info.plist is generated by generateMacOSInfoPlist. No code signing is performed (requires an Apple Developer certificate not available in CI).

Sub-phase 18.1 -- Info.plist generation

Decisions made (18.1)

Generated Info.plist for a macOS app:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ...>
<plist version="1.0">
<dict>
<key>CFBundleName</key> <string>MochiOut</string>
<key>CFBundleIdentifier</key> <string>com.mochi.example</string>
<key>CFBundleVersion</key> <string>1.0</string>
<key>CFBundleShortVersionString</key> <string>1.0</string>
<key>CFBundleExecutable</key> <string>MochiOut</string>
<key>CFBundlePackageType</key><string>APPL</string>
<key>NSPrincipalClass</key> <string>NSApplication</string>
<key>LSMinimumSystemVersion</key><string>13.0</string>
</dict>
</plist>

Sub-phase 18.2 -- Availability helpers

Decisions made (18.2)

CodesignAvailable() bool: returns runtime.GOOS == "darwin". The codesign tool is always present on macOS.

AltoolAvailable() bool: returns true on macOS (always; xcrun altool may have been replaced by notarytool in newer Xcode but the path still resolves). Returns false on Linux.

Both helpers are used by the test to skip validation steps that require signing credentials.

Files changed

FilePurpose
transpiler3/swift/build/macos.goMacOSAppConfig, CreateMacOSAppBundle, generateMacOSInfoPlist, CodesignAvailable, AltoolAvailable
transpiler3/swift/build/phase18_test.goTestPhase18AppStore: 5 fixtures; bundle structure validation
tests/transpiler3/swift/fixtures/phase18-appstore/5 fixture directories

Test set

  • TestPhase18AppStore -- 5 fixtures: appstore_func, appstore_hello, appstore_int, appstore_list, appstore_record. Each builds a macOS executable, calls CreateMacOSAppBundle, then asserts the bundle layout and Info.plist content.

Deferred work

  • codesign --deep --options runtime --timestamp --sign "Developer ID Application: ...". Deferred to Phase 18.3.
  • xcrun notarytool submit --wait + xcrun stapler staple. Deferred to Phase 18.4.
  • xcrun altool --validate-app --platform osx App Store validation gate. Deferred to Phase 18.5.
  • Mac App Store .pkg via productbuild --component .app /Applications. Deferred to Phase 18.5.
  • App Store Connect REST API JWT upload pipeline. Deferred to Phase 18.5.
  • iOS .ipa export (xcodebuild -exportArchive). Deferred to Phase 15.4.
  • .dmg creation via hdiutil for direct download distribution. Deferred to Phase 18.3.
  • Privacy manifest (PrivacyInfo.xcprivacy) generation. Deferred.