I have some large resources that I only need for my simulator runs—I'd like to have them automatically excluded from all device builds. Is there any way to do this with Xcode 4 short of custom build scripts that copy the resources?
I went with a Run Script phase with the following:
if [ ${PLATFORM_NAME} != "iphonesimulator" ]; then
echo "device build -- removing resources..."
rm "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/test_a.mp3"
rm "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/test_b.mp3"
# reveal the binary in the Finder
/usr/bin/open --reveal "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
else
echo "simulator build..."
fi
Targets dictate what's included in a product. Duplicate your target and create a scheme for it. Modify that target's membership.
Art's answer works well.
I'm adding this alternative answer because I have certain requirements and I found a solution that addresses those.
In my case, I need some large resources to be only in some test builds, but I don't want them to be included in the project or checked in with project. I also want to avoid Xcode pointlessly copying a large file from one folder to another during the build.
My solution is as follows:
Create a new folder on disk under your Resources/ folder, titled FolderLinkedResources.
Add a folder reference to this folder in the Xcode project.
This is a link to an actual folder on hard disk, rather than a project folder group. You do it via an option in the Add Files dialog:
Then at build time I have a custom build phase script (placed earlier than compilation) that hard-links the required resource file into the referenced folder on disk:
# COPY_SPECIAL_RESOURCES is only defined in schemas where I require the special resource(s).
# SpecialResources folder is a sibling folder alongside my entire Xcode project folder
if [ ${COPY_SPECIAL_RESOURCES} == "1" ]; then
ln ../SpecialResources/mySpecialResourceFile.bin Resources/FolderLinkedResources/
fi
Now the build will include your special resource.
Note that since the resource file is inside a folder reference in the project, the built app will actually contain the resource file in a folder, rather than at the top level. This means that the usual call to retrieve your resource will not work:
NSString *resourcePath = [[NSBundle mainBundle]
pathForResource:#"mySpecialResourceFile"
ofType:#"bin"];
To fix this, you need to also provide the folder name containing the resource:
NSString *resourcePath = [[NSBundle mainBundle]
pathForResource:#"mySpecialResourceFile"
ofType:#"bin"
inDirectory:#"FolderLinkedResources"];
Note: this technique also works well for when you don't actually know what the resources are until build time! As long as your script step hard-links in the files, they will make it into the build.
In the interests of tidyness and sanity, I include a run script build phase that happens after the compilation, which clears out the hard link:
if [ ${COPY_SPECIAL_RESOURCES} == "1" ]; then
rm -rf Resources/FolderLinkedResources/*.*
fi
Finally, in case anyone is interested in my actual use case for this: I have pre-recorded HTTP communications data for certain offline test builds of my app. This data is in no way a part of the core app, so I don't want it checked in with app itself, or part of the project by default.
Custom build scripts is your best friend in Xcode. Have the script delete the resource after the build and before the code sign.
Related
Is there anyway I can just call into a define such as LIBFOO_DIRCLEAN, and just do what was implemented in the define?
Inside HOST_LIBFOO_INSTALL_CMDS, I copy files to the target directory, and would like the 'make package-dirclean' to delete what was copied into the target directory. 'make clean', would obviously do this(any many more), but that is much more than I want to do.
I see the following buildroot variables. LIBFOO_EXTRACT_CMDS, LIBFOO_CONFIGURE_CMDS, LIBFOO_BUILD_CMDS, HOST_LIBFOO_INSTALL_CMDS, LIBFOO_INSTALL_TARGET_CMDS, etc.
make foo-dirclean is a simple tool that just deletes the package build directory. In most cases, when the list of files installed by a package does not change over time (only files content changes) you can simply rebuild the package and the target directory will be rebuilt correctly.
If you want you can implement your own foo-myclean step that implements your own logic. However you must understand deleting files in the target directory is not supported by Buildroot and thus you are on your own.
Xcode can't find my Storyboards and my Info.plist in my Copy Bundle Resources, So my App doesn't run. I tried to add the Existing files again but they always appear red highlighted. I'm pretty sure it must be a local problem because when i clone the latest update from my repository on my other mac its runs without any problems. I already tried to re-install Xcode, delete files from Xcode/DerivedData and i also deleted the com.apple.Xcode.plist.
Anyone any ideas?
Try to reset your Simulator and then clean your App Build Folder
My experience is that the proposed solution works, but cleaning and re-compiling the entire app whenever a resource has changed is very tedious, especially for larger projects.
Therefore I came up with this solution that forces fresh resources in the app on a per-directory basis, without having to clean or recompile:
Add a 'Run Script Build Phase' (Editor > Add Build Phase > Add Run Script Build Phase)
Copy/paste the following script into the build phase (don't forget to set the actual paths on line 1):
dirsToCopy=("path1/directory1","path2/directory2")
for INPATTERN in "${dirsToCopy[#]}"; do
INDIR=$PROJECT_DIR/$INPATTERN/*
OUTDIR=$TARGET_BUILD_DIR/$CONTENTS_FOLDER_PATH/$INPATTERN
cp -R $INDIR $OUTDIR
done
For those not used to working with shell scripts:
paths on line 1 of the script are relative to the project directory (where the .xcodeproj file resides)
you can add more (or less) paths to the array dirsToCopy if you want
you can change the pattern of files to copy where variable INDIR is defined
you can change how the copying is done (currently, recursive due to -R) by changing the flags to cp in the last line of script within the for block.
May I use a settings bundle in xcode which is not called Settings.bundle?
If I have multiple settings bundles (for multiple build targets), must I define these additional names anywhere? My application seems to always look for one called Settings.bundle.
For those of you who aren't good at shell scripts, here's a template version of what I used. In addition to a Debug and Release build, we also had a Debug-Special build with its own Info.plist in the build settings, and a different Settings.bundle/Root.plist file. I created copies of the Setting.bundle/ folder to Settings(original).bundle and Settings(special).bundle and added this script to the pre-build:
subdir="original" ; [[ $CONFIGURATION = "Debug-Special" ]] && subdir="special" ; cp "$SRCROOT/Settings($subdir).bundle/Root.plist" "$SRCROOT/Settings.bundle/"
Be sure to select your project to add the environment variables to the shell that runs the script.
I realize the thread is pretty old in code years but it is still relevant, and hopefully this will save the next person who finds it some time.
Solved this by adding a script in pre-build where the alternative bundle is renamed to Settings.bundle
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?