I'm writing an iPhone app in Objective-C with Xcode and I have some Lua scripts that run on the device.
I'm having an issue where if I edit a Lua script, save, flick over to Xcode and Build and Run (⌘Y) the latest version of that Lua script is copied into the app bundle but not copied to the device.
The scripts aren't in the Xcode project, I edit them in Textmate. I have a build step which copies the scripts into the app bundle and touches the files, this is being run fine and the latest script version is in the app bundle when I run the app. The files have all been touched, but for some reason when copying the bundle to the device Xcode decides not to copy the latest.
If I stop the app and then Build and Run (⌘Y) again, the latest version is copied across.
My workaround is to save the Lua file, then in Xcode do a Build (⌘B) and then Build and Run (⌘Y), so build the app twice. This always seems to copy the latest version to the device.
Update:
As many have noted, one solution is to clean the targets and rebuild. You can do this, you could also build twice as I have noted above. This problem is easily reproducible (in my setup it happens every time, regardless of how recently the targets were cleaned). I'm hoping for a more reliable/permanent solution
You should definitely add those files to your Xcode project. You can still edit them in your other editor, but Xcode will include them in your bundle automatically if you add it to the project. If they aren't getting copied when you build, this is how I resolve it:
Right click on the file in Xcode and choose "Touch" which updates the timedate stamp on the file, so it looks "new".
On the simulator, choose Reset Content and Settings from the File Menu.
In Xcode, do a Build Clean
When you build and run after that it should install the file just fine.
EDIT:
To add external folders to your project that will get included in your bundle and preserve the folder structure intact, all you need to do is:
Click on the project icon at the top of the file list on the left.
Click the Project menu and Add to Project.
Select the folder you want to include and click Add.
Unchecked the Copy checkbox and change "Recursively create groups for any added folders" to "Create Folder References for any added folders".
When the target is built, open up the bundle and your directory structure will exist inside fully intact.
First of all: I feel your pain. I haven't found any good documentation on rolling up your sleeves and digging into the iOS build pipeline if you want to do some interesting (or even just simple) data pipelining using custom scripts.
Second of all: I don't agree that you need to, or even should put all your assets in your Xcode project. That's really a matter of personal preference, and if you've got a complicated enough project, Xcode becomes a beast to navigate your code alone as it is, let alone with all your art assets and data files.
Third: Cleaning is a work-around, as is touching an individual source-code file (Xcode will pick up on this and do the signing/touching of the master directory for you without the need to do a clean build -- a clean build is extremely time consuming if you have a large project or significant assets), but these are really just hacks to get the thing to work without fixing the underlying problem: you need to hit the right dependency to get the copy step to kick in.
I had the same issues you're describing here with the following differences:
I'm using a gnu make script to process art resources (audio, data files, images) by doing some basic manipulations (compression, stripping out un-needed things, building fonts, etc). I'm using gnu make because 1.) I know it 2.) I find it easier to put all my rules into one script 3.) I like to keep my data folder nice and hierarchical and 4.) Xcode isn't always the way you want to interface/organize/manage all your data! (though I think it does a great job for code and even small amounts of data in a less complex project)
Anyhow, what I found is that I really had 2 problems: 1.) Code signing and 2.) Copying. The copying is easy, all you need to do is touch the build products folder. In my case I added the following to my make file: "touch $(DIR_CONTENTS)" where I defined "$(DIR_CONTENTS)" using the existing env parms provided by Xcode to the shell when my Xcode is executed: "DIR_CONTENTS = $(BUILT_PRODUCTS_DIR)/$(CONTENTS_FOLDER_PATH)" (you can see the full list of env parms if you click on the 3 horizontal lines in the output log). In your case you'd need to do the equivalent in your lua script. Not sure what that entails, I've been purposely dodging lua for years, but I can't imagine it's too crazy.
The next bit is trickier, 'cuz what I found was that just because you've updated, doesn't mean that the code signing stuff works nicely. In my case I needed to add a ResourceRules.plist file and add my art directory (art/.*) as a dictionary, with a line to omit and a weight. I couldn't find docs on this anywhere, so I copied the ResourceRules.plist file from the generated folder into my source folder, added it to the project, and then pointed the code signing stuff at it. (This would be in the build rules under Code Signing: it'll be your "Code Signing Resource Rules Path")
This isn't really my ideal solution, by the way. I would rather be able to trigger the code-signing step via my script if my data changes, but as I stated earlier I haven't found any useful docs in apple's developer library on how to really dig into the custom builds. You can do the code signing by hand, but I didn't like it.
Hope that helps.
UPDATE:
I figured I'd add some example code.... here are some relevant excerpts from my makefile:
# Near the beginning, where I do my variables n' such, I define the
# directory in a variable. Note that BUILD_PRODUCTS_DIR and CONTENTS_FOLDER_PATH
# are environment variables set by XCode and will be filled with the corresponding
# paths
DIR_CONTENTS = $(BUILT_PRODUCTS_DIR)/$(CONTENTS_FOLDER_PATH)
DIR_DEST_ART = $(DIR_CONTENTS)/art
DIR_DEST_FONTS = $(DIR_DEST_ART)/fonts
# ... more folders defined here...
DIR_SRC_FONTS = $(SRCROOT)/source-art/fonts
# ... more folders defined here...
# ... do some useful build stuff ...
# This is an example of my rule that takes the .png's built by my font script
# and compresses them to .pvrs (note: this isn't final, so YMMV). The thing to
# note here is that if this rule kicks off, the last thing that will happen is
# that I will touch my DIR_CONTENTS folder, which will kick off the copy to the
# device. I find having to touch the folder really annoying, I prefer the way xcopy
# and similar copy methods recursively travel & update if required.
$(DIR_DEST_FONTS)/%.pvr : $(DIR_SRC_FONTS)/%.png
#echo == Compress $(subst $(SRCROOT),src,$<) to $(subst $(DIR_DEST_ART),dest,$#) ===
#mkdir -p $(dir $#)
#xcrun -sdk iphoneos texturetool -e PVRTC -o $# -f PVR $<
#touch $(DIR_CONTENTS)
Then, in order to deal with the code signing problem, I edited my ResourceRules.plist to look like the below. The area to pay attention to is the key that starts with "art/.*"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>rules</key>
<dict>
<key>.*</key>
<true/>
<key>art/.*</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<integer>0</integer>
</dict>
<key>Info.plist</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>ResourceRules.plist</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>100</real>
</dict>
</dict>
</dict>
</plist>
For reasons I am yet to understand, sometimes the build process seems to get forgetful or simply unreliable.
Usual troubleshooting for this type of scenario is to clean all in Xcode, and at the same time delete the app from the phone.
Why are the scripts not in the Xcode project? They can still be in the project while you use Textmate to edit them. Perhaps including them in the Xcode project will make it more likely that they get transferred to the device?
Sounds like you have an "one-off" kind of a problem, in which your updated scripts make it "too late" to the bundle. Have you tried changing the order of the build phases, in particular moving the copy phase not to be at the end but before the compile and link phases?
I work on this in device build when resource updated:
In Xcode, Right Click your .app file in Products Group
Choose 'Show in Finder'
Clean the files that where .app file located
Run again
this works fine for me on device building that won’t cost much time.
Clean all targets in Xcode
Restart Xcode
Try to install on the device
I see this problem once in a while with a sqlite database that I have included in my project. Sometimes it just doesn't get the updated version.
Typically my fix for this is to go into the Application Support/iPhone Simulator folder and delete the app inside the Application folder and also delete the Caches folder.
This will force the Simulator to reconstruct all of this and get fresh files.
I had a similar problem auto-copying a script file, when changed. Had set its Type to "C" to allow for auto syntax highlighting. Had added the file to "Build Phases / Copy Bundle Resources". But no luck; changes to the file would not update the bundle.
The fix, in this case, was to change the Type from "C" to "JSON". Now, it updates the bundle automatically on the device. Makes sense, since source files are rarely needed for a binary. Originally, Apple didn't allow any scripting.
I had the same problem today using Xcode 11.1. I tried deleting the app from my device, cleaning the project and rebuilding, deleting the resources and re-adding them to the project, none of which worked.
What eventually worked was this: I opened the project window, then went to 'Build Phases', then opened 'Copy Bundle Resources' and simply moved some of the resources up and down in the list. I suppose that told Xcode that something had changed.
Use Trouble Shooting
Clean the Xcode Projects
Build and Run
Related
I'm working on a multi-platform iOS and Mac app. When I try and Archive and Distribute to the App Store I run into this issue:
ERROR ITMS-90259: "Bad Bundle Executable. You must include a valid CFBundleExecutable key in your bundle's information property list file."
Verified that the Info.plist for the Mac target has a CFBundleExecutable
Tried Xcode 12 & 13
Tried using App Transporter
Used Xcode 13 RC and let that auto-generate the Info.plist
I've tried everything I could find online - there's not much - and I can't get the upload to succeed.
However, I was able to replicate the issue with an entirely empty project. No dependencies, no code, nothing. The project archives successfully, but the upload fails.
Any help would be appreciated. I've spent two days on this already.
An example project that fails: https://drive.google.com/file/d/1qUN5lHEWNyNHQV54fYPXMeRsuO-cpHqW/view?usp=sharing
We had two issues causing this, making it fail when uploading a Mac build to iTunes. The first issue, we had included a package (from Steam), that had its own plist and post build script.
com.rlabrecque.steamworks.net/Editor/RedistCopy.cs - build script
com.rlabrecque.steamworks.net/Plugins/steam_api.bundle.meta - folder with plugin and plist
We renamed the post build script and removed the plugin folder, not 100% sure if the renaming was needed.
Then, we had this in our own post build script that was causing issues, so we removed it too.
rootDict.SetString("CFBundleExecutable", "${EXECUTABLE_NAME}");
Then it worked! Also worth noting that we believe the CFBundleExecutable didnt actually end up matching the file name e.g. the file produced was a.pkg and the plist says:
<key>CFBundleExecutable</key>
<string>b</string>
But seems iTunes was ok with that. We use Unity and it seems in the pList the string was set to the "Product Name" (Edit > Project Settings > Player, at the top, "Product Name").
We also didnt need to use Transporter to upload.
I am almost ready to release my iphone app. I use restkit for consuming my webservice. When I archive, it fails with this error:
cp: /Users/myusername/Library/Developer/Xcode/DerivedData/project-name-/ArchiveIntermediates/project-name/IntermediateBuildFilesPath/UninstalledProducts/include/RestKit: No such file or directory
I dragged & dropped restkit into the project. It builds and works fine in debug mode. I am guessing it is unable to locate restkit dir while archiving. But I am not sure why. Any thoughts?
I've had trouble linking with my own framework in the past, but I have a procedure that works. Even though I don't understand it, it works so I follow it like voodoo, and I don't risk angering the gods by asking too many questions.
Here's what I'd try on your project (again, partly voodoo here):
Navigate to the Frameworks folder in the project nav, select the RestKit and delete it with the delete key. Just delete references.
Using Finder, option-drag (copy) the framework from wherever you first got it
(~/Downloads, or another project or wherever) into your project directory, replacing files if prompted.
Back in your project, select the project, then the target, then build phases.
Open the link binary section, hit "+", then the "Add Other.." button on the bottom of the dialog
Browse to the framework you copied in in step 2.
See if you can clean, build, archive. Easy enough to try, and no livestock are harmed. Hope it works for you.
In our environment, we share resources across multiple projects and platforms. When building for iPhone, only a subset of those resources are needed. Since that subset is still considerable, we have a manifest file listing what goes in, which limits the copy. We have our own Python script which does the copy, refreshing only the files which have changed.
I have made a Run Script Phase in Xcode to call that script, but I am having a few issues related to the Code Signing phase.
Since we use a separate manifest file, my Run Script Phase cannot specify any input/output file in the Xcode GUI: it varies depending on what is contained in directories at the time. The side effect of this is that Xcode doesn't strictly know what files will get copied (things happen "under the cover", so to speak).
The problem I have is that if I only modify resource files between builds, rebuilding my app will properly call my script, which copies the appropriate files, only Xcode won't rerun the Code Signing step, and won't re-copy my app to my device.
I found that odd, considering that my resource files are indeed listed in the <app_bundle>/_CodeSignature/CodeResources file, but it looks like Xcode determines rebuilds requirements independent of that (likely only files listed in the project file), which is understandable.
I tried playing tricks by touching my app bundle's directory, or the app's binary itself, but it doesn't quite work. Touching the app's bundle directory doesn't seem to do anything, while touching the binary will work, but NOT FOR THE CURRENT BUILD, only the subsequent one (since no input file requires recompilation, Xcode infers no new binary gets generated, but the next time, it will indeed detect that the binary has been touched, and redo both Code Signing and on).
Still, this is quite an imperfect workaround, because:
Having to build twice is error prone
My dSYM file will needlessly get regenerated
Does anyone know of any way to force the Code Signing step in Xcode (from a Run Script, or elsewhere)?
You can call codesign directly from the command line or a shell script, e.g.
codesign -f -s "iPhone Distribution" --entitlements Entitlements.xcent -vv location/MyApp.app/MyApp
Run man codesign to find out the usage.
You can discover all the internal commands run by viewing the detailed build output in Xcode. Select the Build tab, then click the little icon at the bottom left of that window pane - the one that looks like text (it is next to the warning icon). This will show the full build output in a new pane in Xcode.
I created a shell script calling codesign directly so I could re-sign an existing binary using a new certificate and provisioning profile (e.g. after updating some graphics in the binary).
This turned out to be really complicated as Xcode does some subtle stuff as part of its internal build processes (one example: Xcode embeds the provisioning profile in the resulting app binary, but in the process changes some of its values, e.g. the get-task-allow setting). That meant I had to write a tool to generate an appropriate .xcent file from the provisioning profile, depending on whether a Development/Distribution/App Store build is being done. Hopefully none of that will affect you...
I always use one folder on my filesystem for an Xcode project. It contains all project files. When I zip it and send it to a friend, she can't just ipen the xcodeproj file. It opens, but all paths are broken and build fails because all the classes don't find the #include'd files. But when I download i.e. some example projects from apple, these work perfectly. What am I doing wrong?
UPDATE:
I'm doing it like this:
1) I create a project and specify an directory on my desktop
2) In that directory I create an "images" directory and add images to it
3) I pull this images directory out and drag it into the Resources Groups&Files. Xcode asks if I want to copy it to destination folder, I click no. Because it's already there. All other things are set to default.
4) all other things are just created within xcode, and xcode just puts all classes in the Classes directory of my project.
5) when I want to add images, I first put them in the directory of the project, and from there drag them into the Images group in xcode. That's to make sure xcode doesn't mess them up with everything else. Otherwise it would just copy them to the root of my project directory rather than inside the Images directory, which doesn't make sense. In fact, the whole Groups&Files filesystem doesn't make sense at all, it's one big mess. Apple's biggest mistake in Xcode so far. That's why I have to do such stupid things.
We don't really know exactly what you're doing so it's hard to see what you're doing wrong.
Perhaps inspect the xcode project files directly, see if you have hardcoded paths. That's a sure fire problem. Make sure you copy resources into the project instead of referencing them externally, etc.
I expect that you have "search path" build setting set to an absolute path on your machine, rather than a path relative to the project. Best way to tell is to post a portion of the build transcript from the failed build and look at the -I directives. If those paths don't exist on your friend's machine, then they should be changed from absolute paths to paths that start with ${SRCROOT}.
Are you just trying to build on the second machine or are you trying to deploy to a device on the second machine? If you are trying to deploy to a device (iPhone or iPod Touch) then it probably has something to do with Code Signing and Certificates.
I have a bunch of content files for my iPhone app that I generate via shell script. It takes way too long to be a part of the Xcode build process, so I run it periodically.
I don't want to have to continually add these files to my Xcode project in order to get them included my app resources folder. Is there a way to get Xcode to copy the contents of a folder into the app resources at build time? (It'd be a bonus if I could specify other locations, such as the approot documents folder.)
I tried adding a new 'Copy Files Build Phase' to my target, but that didn't seem to work. This seems like a common problem, but I couldn't find anything about it here.
-- Edit (What I did)
Per Jasarien and cdespinosa's suggestions, I did the following in a build script. I decided not to copy to the destination, because that would only work when using the simulator, I don't think that'll work when deploying to a device.
cp -rf "$PROJECT_DIR/mystuff" "$CONFIGURATION_BUILD_DIR/$CONTENTS_FOLDER_PATH/"
-- Edit 2
This doesn't appear to get files onto my iPhone. Any ideas?
You can setup a Run Script build phase in your app's target. Write the script so that it copies the resources into the app bundle.
This is the path i use for output:
${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
Just copy your files in that directory, it's the bundle (simulator or device).
You can also take a look at my answer here : how to set up a Xcode build rule with a variable output file list?