-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix(ios): Resolve Mac Catalyst build failures and App Store distribution issues #14370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This commit fixes 4 critical bugs that prevented Mac Catalyst builds from succeeding and being distributed via Mac App Store: Bug tidev#1: SWIFT_ACTIVE_COMPILATION_CONDITIONS (already fixed in template) - Template already uses $(SWIFT_CONDITIONS) instead of $(GCC_DEFINITIONS) - No changes needed Bug tidev#2: Invalid FRAMEWORK_SEARCH_PATHS - Changed relative path 'Frameworks' to absolute '$(PROJECT_DIR)/Frameworks' - Fixes 'Unable to find module dependency: TitaniumKit' error - Location: Line 3524 Bug tidev#3: Missing build-time symlinks in TitaniumKit.framework - Created createTitaniumKitSymlinks() function to ensure proper macOS framework structure - Creates required symlinks: Versions/Current, TitaniumKit, Headers, Resources, Modules - Called before xcodebuild to fix build directory frameworks - Locations: Lines 7114-7207, 7101, 7104 Bug tidev#4: Missing distribution symlinks in final app bundle - Same createTitaniumKitSymlinks() function handles app bundle - Called after xcodebuild completes to fix frameworks in .app/Contents/Frameworks - Prevents App Store rejection due to missing/malformed TitaniumKit - Location: Line 7433 Impact: - Enables successful Mac Catalyst compilation (ti build -p ios -T macos) - Enables App Store distribution (ti build -p ios -T macos --deploy-type production) - Eliminates need for 'ti clean' before each build - Restores fast incremental builds for Mac Catalyst Tested with: TiDesigner app (iPad app with modules: ti.compression, dk.napp.social) Related documentation: MAC_CATALYST_BUILD_FIXES.md in TiDesigner project
Document all Mac Catalyst build fixes in CHANGELOG: - FRAMEWORK_SEARCH_PATHS absolute path fix - TitaniumKit.framework symlink creation - Clearly note Mac Catalyst-only impact (no effect on iOS/Android) Related to commit 3e403c6 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
…ilds Improve createTitaniumKitSymlinks() to handle incremental builds: - Detect and remove directories created by previous SDK versions - Detect and verify existing symlinks point to correct targets - Remove incorrect symlinks/directories/files before creating new ones - Enables builds without `ti clean` for projects with existing builds This fixes: - "Couldn't resolve framework symlink" error (readlink on directory) - "EEXIST: file already exists" on incremental rebuilds - Allows seamless migration from SDK 13.0.1.GA to 13.1.0 Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Improve ensureSymlink() to handle broken symlinks correctly: - Use lstatSync() instead of existsSync() to detect broken symlinks - existsSync() follows symlinks and returns false for broken ones - lstatSync() doesn't follow symlinks and detects them even if broken - Verify symlink target exists before considering it valid - Remove and recreate broken symlinks automatically This fixes EEXIST errors in incremental builds when symlinks point to targets that no longer exist. Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
hansemannn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these changes look quite verbose, so I'm wondering if only parts of these changes are actually relevant for this precise fix.
iphone/cli/commands/_build.js
Outdated
| // Bug #3: Build-time symlinks in build/Frameworks directory | ||
| // Bug #4: Distribution symlinks in final app bundle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove these comments, it's looks odd as part of an overall build script. If necessary, add it to the comments
…back - Remove verbose "Bug #X" comments, use descriptive explanations instead - Simplify ensureSymlink function from 44 to 23 lines - Remove redundant fs.existsSync check as suggested by reviewer - Remove unused logger parameter from ensureSymlink Co-Authored-By: Claude Opus 4.5 <[email protected]>
|
@hansemannn Thanks for the detailed feedback! I've addressed your concerns in the latest commit: Changes made:
Testing performed:
Ready for your review when you have a chance! |
hansemannn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent work, we can approve it now! :)
…ion issues (#14370) * fix(ios): Fix Mac Catalyst build failures and App Store distribution This commit fixes 4 critical bugs that prevented Mac Catalyst builds from succeeding and being distributed via Mac App Store: Bug #1: SWIFT_ACTIVE_COMPILATION_CONDITIONS (already fixed in template) - Template already uses $(SWIFT_CONDITIONS) instead of $(GCC_DEFINITIONS) - No changes needed Bug #2: Invalid FRAMEWORK_SEARCH_PATHS - Changed relative path 'Frameworks' to absolute '$(PROJECT_DIR)/Frameworks' - Fixes 'Unable to find module dependency: TitaniumKit' error - Location: Line 3524 Bug #3: Missing build-time symlinks in TitaniumKit.framework - Created createTitaniumKitSymlinks() function to ensure proper macOS framework structure - Creates required symlinks: Versions/Current, TitaniumKit, Headers, Resources, Modules - Called before xcodebuild to fix build directory frameworks - Locations: Lines 7114-7207, 7101, 7104 Bug #4: Missing distribution symlinks in final app bundle - Same createTitaniumKitSymlinks() function handles app bundle - Called after xcodebuild completes to fix frameworks in .app/Contents/Frameworks - Prevents App Store rejection due to missing/malformed TitaniumKit - Location: Line 7433 Impact: - Enables successful Mac Catalyst compilation (ti build -p ios -T macos) - Enables App Store distribution (ti build -p ios -T macos --deploy-type production) - Eliminates need for 'ti clean' before each build - Restores fast incremental builds for Mac Catalyst Tested with: TiDesigner app (iPad app with modules: ti.compression, dk.napp.social) Related documentation: MAC_CATALYST_BUILD_FIXES.md in TiDesigner project * docs: Add Mac Catalyst fixes to CHANGELOG.md for v13.1.0 Document all Mac Catalyst build fixes in CHANGELOG: - FRAMEWORK_SEARCH_PATHS absolute path fix - TitaniumKit.framework symlink creation - Clearly note Mac Catalyst-only impact (no effect on iOS/Android) Related to commit 3e403c6 Co-Authored-By: Claude Sonnet 4.5 <[email protected]> * chore: remove changelog updates (generated during release) * fix: address eslint for titanium kit symlinks * fix(ios): Handle existing directories and symlinks in Mac Catalyst builds Improve createTitaniumKitSymlinks() to handle incremental builds: - Detect and remove directories created by previous SDK versions - Detect and verify existing symlinks point to correct targets - Remove incorrect symlinks/directories/files before creating new ones - Enables builds without `ti clean` for projects with existing builds This fixes: - "Couldn't resolve framework symlink" error (readlink on directory) - "EEXIST: file already exists" on incremental rebuilds - Allows seamless migration from SDK 13.0.1.GA to 13.1.0 Co-Authored-By: Claude Sonnet 4.5 <[email protected]> * fix(ios): Detect and fix broken symlinks in Mac Catalyst builds Improve ensureSymlink() to handle broken symlinks correctly: - Use lstatSync() instead of existsSync() to detect broken symlinks - existsSync() follows symlinks and returns false for broken ones - lstatSync() doesn't follow symlinks and detects them even if broken - Verify symlink target exists before considering it valid - Remove and recreate broken symlinks automatically This fixes EEXIST errors in incremental builds when symlinks point to targets that no longer exist. Co-Authored-By: Claude Sonnet 4.5 <[email protected]> * refactor(ios): simplify Mac Catalyst symlink handling per review feedback - Remove verbose "Bug #X" comments, use descriptive explanations instead - Simplify ensureSymlink function from 44 to 23 lines - Remove redundant fs.existsSync check as suggested by reviewer - Remove unused logger parameter from ensureSymlink Co-Authored-By: Claude Opus 4.5 <[email protected]> --------- Co-authored-by: Claude Sonnet 4.5 <[email protected]>
|
@macCesar After merging all changes for 13.1.1 (incl. yours) to 13_1_X, the build fails due to a Mac Catalyst error: https://github.com/tidev/titanium-sdk/actions/runs/21472015632/job/61846652200 Can you please review the issue? Note: The build was triggered by the tab-bar fixes, but only because that was the last cherry-picked commit before pushing it to the branch where the CI starts. |
|
@hansemannn I don't think it was a Mac Catalyst error. Therefore Now with your update to Xcode 26.2, it seems to be working 👍 Edit: Ah, I saw your discussion on Slack too late (I only use it in the browser, not the app). |
|
@hansemannn @hbugdoll Thanks for clarifying! So the failure was NOT caused by my PR, is that correct? Sorry, I'm not very familiar with this type of CI/workflows! Still learning 🙂 Glad to hear everything is working now with Xcode 26.2! |
Yep. |
|
For the sake of completeness: GitHub's macOS 15 runner was changed... |
Summary
This PR fixes critical build failures that prevented Mac Catalyst apps from compiling and being distributed through the App Store. These issues have affected developers since at least SDK 12.x, requiring workarounds that disrupted normal development workflows.
Problems Addressed
1. Framework Search Path Issue
Symptom: Intermittent build failures with framework linking errors
Root cause: Relative framework search path
"Frameworks"failed to resolve correctly in certain build scenariosSolution: Use absolute path
"$(PROJECT_DIR)/Frameworks"for reliable framework location2. Missing TitaniumKit.framework Symlinks
Symptom: Compilation errors and App Store rejections
Build-time error:
App Store rejection:
Root cause: Mac Catalyst requires macOS framework structure with proper symlink hierarchy (
Versions/Current -> Aand root-level symlinks), but builds were producing iOS framework structureSolution: Automatically create required symlinks at two critical points:
3. Incremental Build Issues
Symptom:
EEXIST: file already existserrors when rebuilding withoutti cleanRoot cause: Previous SDK versions created directories instead of symlinks, or symlinks became broken during incremental builds
Solution: Detect and remove directories, files, and broken symlinks before creating new ones
Changes
Modified Files
iphone/cli/commands/_build.jsSpecific Changes
Line 3524: Updated
FRAMEWORK_SEARCH_PATHSfrom"Frameworks"to"$(PROJECT_DIR)/Frameworks"Lines 7116-7242: Added
createTitaniumKitSymlinks()functionmacos,dist-macappstore)lstatSync()instead ofexistsSync()to detect broken symlinksLines 7101, 7104, 7433: Integrated symlink creation into build pipeline
Impact
What This Fixes
ti cleanrequiredWhat This Doesn't Affect
Testing
Verified across multiple scenarios with different Titanium projects:
ti cleanAdditional Context
The issues fixed by this PR affected any Titanium application attempting to:
macos)dist-macappstore)These were fundamental build system issues, not app-specific problems.
Mac Catalyst builds require native modules to include an
ios-arm64_x86_64-maccatalystslice in their xcframework.What this means:
Example error when a module lacks Mac Catalyst support:
For module developers:
To enable Mac Catalyst support in your module:
mac: trueto your module'smanifestfileNote: Some modules may have legitimate reasons to not support Mac Catalyst (iOS-only APIs, hardware dependencies, etc.).
Backward Compatibility
This change is fully backward compatible:
Note: This fix enables Mac Catalyst as a viable deployment target for all Titanium developers, opening the Mac App Store distribution channel that was previously blocked by these issues.