[TIMOB-26807] iOS: Missing files when running from Xcode project
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | None |
Status | Open |
Resolution | Unresolved |
Affected Version/s | Release 8.0.0 |
Fix Version/s | n/a |
Components | n/a |
Labels | cb-tooling, engSchedule |
Reporter | Jan Vennemann |
Assignee | Christopher Williams |
Created | 2019-02-07T23:18:22.000+0000 |
Updated | 2021-08-21T20:34:44.000+0000 |
Description
Until SDK 7.5.X one could open the Xcode project from a device build (
-T device
) and simply run it via Xcode. This was very useful for easy native debugging of both the SDK core and natives modules.
Since SDK 8.0.0 this is now failing due to the core-js polyfills which are added to the app outside of our usual JS processing and thus are not part of the encrypted JS assets.
Apart from the issue mentioned in this tickets this may also have a negative performance impact since i would assume loading the polyfills from the encrypted assets is probably faster then loading them all from file.
*EDIT:* With latest master the issues with polyfills were resolved. Only the __index__.json
used to resolve require paths is still required.
As a workaround the following build phase can be added to the Xcode project which copies the required files into the app bundle:
cp ${SRCROOT}/build/Products/Debug-iphoneos/${CONTENTS_FOLDER_PATH}/_index_.json ${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/_index_.json
Building an app directly from the generated Xcode project has NEVER been supported. It can work, but you can't clean the project. I plan to address this with the rewrite of the iOS build for the new build pipeline. Also note that there are other tickets out there that are related to building projects from Xcode. This ticket should likely be a dupe.
This topic pops up every few months - since years. If Titanium could just inject the above build script, devs are FINE. No rewrite or larger changes required; the benefits for real word developers struggling with this would be huge.
I'm fine with adding the 4 lines in the description to the existing "Pre-Compile" build phase. I would prefer we not add a new build phase as that would require a change in the iOS build script.
Sounds like a plan! [~jvennemann] I am getting "directory not found" errors when using this in latest 8.1.0 master, but it works without it as well.
[~hknoechel], only the last line is required with the latest master builds. The other issues with the polyfills seem to have been resolved in the meantime. [~cbarber], what existing "Pre-Compile" build phase do you mean? AFAIK, the Xcode project does not contain any existing "Run Script" build phase we could use for this.
Why not just add the file to the usual build copy-phase? We copy a LOT to the built product, so this one file won't make a huge difference I assume.
Is this really still an issue? The _index_.json file appears to already be in the build/Products/Debug-iphonesimulator directory, so when I hacked our iOS CLI build to re-use the Pre-Compile build phase and then copy the file as suggested above, it's failing simply because the file already exists (and both the src/dest paths in the command resolve to the same file path!)
I just did a test. I built an Alloy app with Titanium SDK 9 (master). I open the Xcode project and try to run it and it blows up with "Could not find the file ti.main.js". After doing some testing, I determined Xcode uses a system DerivedData directory to build the app. This directory is outside the Titanium project and thus does not have any of the Titanium resources. To fix the Derived Data directory issue, you must open Xcode Preferences, go to the "Locations" tab, then set the "Derived Data" path to be "Relative" and a value of "DerivedData". This will put all intermediate files in the "build/iphone/DerivedData" directory. Next you need to click the "Advanced..." button under the Derived Data field to open the build location window. Select the "Custom" option with "Relative to Workspace". Set the "Products" path to "Build/Products" and the "Intermediates" path to "Build/Intermediates.noindex". Click the "Done" button and close the preferences. Now you can build your iOS app and will will run. BUT, don't clean the project! That will wipe all files in the "build/iphone/build/Products/Debug-iphonesimulator/appname.app" directory and then you're back at the "Could not find the file ti.main.js" error. I recommend we research changing the iOS build so that it copies/processes files from the Resources directory into a "build/iphone/Resources" directory instead of "build/iphone/build/Products/Debug-iphonesimulator/appname.app". Then add each of those Resources files to the Xcode project as static files that are copied to the final app output directory. This will allow you to clean, re-build, distribute, and natively debug an app without issue.
[~cwilliams], yes this is still an issue, precisely because of what [~cbarber] wrote. When you open the project in Xcode it will use a different derived data directory. The command above copies the _index_.json from the derived data directory our command line build uses to the one when you build directly from within Xcode. As you already noted, that's also the reason it fails when you try to hack our iOS CLI because both dest/src are the same in our command line build. [~cbarber], your proposed solution is exactly what i had in mind too. We probably "just" have to refactor [copyResources](https://github.com/appcelerator/titanium_mobile/blob/f63e597adfc21c4aac6894234b2c92bee4c5a593/iphone/cli/commands/_build.js#L4895) so that it copies all resources to this new destination and then add this as a folder reference to the Xcode project. That way we don't have to manage each and every file reference in the project. Xcode should then just copy it during the "Copy Bundle Resources" phase. As an intermediate solution we could start with the
_index_.json
and, instead of writing it directly into the Xcode directory, write it into a temp folder and then let Xcode copy it. That way users should be able to run a device build directly from Xcode (since JS resources are encrypted and don't need to be copied).Or just add the index.json to the Xcode project. :)
Unfortunately that did not work. I included the run script phase from Jan in the main target build phases, but it still complained about the ti.main.js not being found. Has anyone actually tried these steps? I'm running from Alloy, but that should just be a bunch more sources after all.
[~hknoechel] I didn't think that one-liner would have completely fixed it. You would need to do a device build or a sim build with deploy type of "test" so that the .js files get encrypted and embedded in the obj-c code, however you'd still be missing any other assets (images, json, html, etc). I really think the correct solution here is to add each file (code, images, everything) to the Xcode project when copying files and then write the Xcode project after copying files.
Ok, so little update here: I found a way to make this working again. We can generate a "WorkspaceSettings.xcsettings" with the following contents:
which is copied to
<project>/build/iphone/MyApp.xcodeproj/project.xcworkspace/xcuserdata/<username>.xcuserdatad/WorkspaceSettings.xcsettings
. It can likely even be underxcshareddata
to have less trouble with generating OS-username-depending folders. This will likely cause issues for normal builds, so the build path can/should either be updated to play well with the current one or be injected in a special build mode, e.g.ti build -p ios --open-xcode-project
PR: https://github.com/appcelerator/titanium_mobile/pull/13032