Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include/exclude resources depending on scheme

Tags:

ios

xcode4

iphone

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?

like image 468
Art Gillespie Avatar asked Apr 14 '11 18:04

Art Gillespie


3 Answers

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
like image 128
Art Gillespie Avatar answered Sep 25 '22 14:09

Art Gillespie


Targets dictate what's included in a product. Duplicate your target and create a scheme for it. Modify that target's membership.

like image 40
Joshua Nozzi Avatar answered Sep 22 '22 14:09

Joshua Nozzi


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:

enter image description here

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.

like image 41
occulus Avatar answered Sep 24 '22 14:09

occulus