Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable iCloud on a Xcode project via script

i am trying to setup a build server for a continuous building on a iOS project. Since that i need to recreate the Xcode project very often (it is a build from unity), the iCloud will be reset to OFF.

I can copy the entitlement file (with the iCloud key) via script but i still need to click on the actual checkbox to turn iCloud ON.

I managed to change the XC project manually but it is not very safe, due to possible changes on XC project structure.

Do you know a better way to do this? Cheers!

like image 980
Chiodo Avatar asked Jul 29 '14 09:07

Chiodo


1 Answers

Apparently the TO solved the problem but since there seem to be more people interested in this, here a possible solution.

You can make a script to edit the project.pbxproj which is inside your xcodeproj file (can be viewed e.g. with "show package contents" options in finder).

In this file there's a section for project settings called PBXProject section. There you can add the capabilities for the targets. You probably need to write custom parsing logic, since this file is written in XCode config format, no anything popular like XML or JSON.

The part which you want to update looks like this:

/* Begin PBXProject section */
        EB1DDE9C1A3334EC00D778DE /* Project object */ = {
            isa = PBXProject;
            attributes = {
                LastSwiftUpdateCheck = 0700;
                LastUpgradeCheck = 0610;
                /* ...more settings */                        
                TargetAttributes = {
                    EB1DDEA31A3334EC00D778DE = {/* this is one target */
                        CreatedOnToolsVersion = 6.1.1;
                        DevelopmentTeam = 37QAPDY2PR;
                        /* ...more settings */                        
                    };
                    EB9F6CE11A8812550038355B = {/* another possible target */
                        CreatedOnToolsVersion = 6.2;
                        DevelopmentTeam = 37QAPDY2PR;
                        /* ...more settings */                        
                     };

                };
            };
            /* ...more settings */                        

        };
/* End PBXProject section */

You want to add the iCloud capabilities to the targets. This looks like this:

SystemCapabilities = {
    com.apple.iCloud = {
    enabled = 1;
    };
};

So let's say you want to add iCloud capability to the target EB1DDEA31A3334EC00D778DE, then the TargetAttributes entries will look like this:

TargetAttributes = {
    EB1DDEA31A3334EC00D778DE = {/* this is one target */
        CreatedOnToolsVersion = 6.1.1;
        DevelopmentTeam = 37QAPDY2PR;
        SystemCapabilities = {
            com.apple.iCloud = {
                enabled = 1;
            };
        };
    };
    EB9F6CE11A8812550038355B = {/* another possible target */
        CreatedOnToolsVersion = 6.2;
        DevelopmentTeam = 37QAPDY2PR;
        /* ...more settings */
    };
};

Now there are some things you need to determine in order to do this:

1. Identify the section

I'd make the script look for the string "Begin PBXProject section" and then for "TargetAttributes" both of which are unique in the file. Theoretically "TargetAttributes" should be enough but better to be safe... and remember to add proper logging to the script and verify the results, because these strings could easily change in future XCode versions (I have seen them unchanged, though, a while already).

2. Identify the target

There are multiple parts in this file where you can see the id of the target associated with the name. I would just look this up myself and hardcode it in the script, as this id will not change unless you re-create the target. If you really need it you can also automate this... by looking for your target's name and the format where it appears associated with the id. There should be also other config files where this association appears (in this file the name just appears as a comment).

3. Handle situation that there is already a SystemCapabilities entry for the target, and also that there is already iCloud entry.

If your target has other capabilities this entry may already exist. Also if you already have iCloud enabled or if you had once iCloud enabled and disabled it, the entry will also exist (with a 0 value). This has to be handled in the script (latest should not be a problem if the project file is new though).

Besides of that, you also probably have to add a reference to the entitlements file. You have to add this to the build configurations of the respective targets. For this:

4. Find the build configuration id(s)

Your target has probably multiple build configurations, e.g. debug and release. You have to find the id of the build configuration(s) for which you want to add a reference to the entitlements file. To do this there's a section called XCConfigurationList (look for /* Begin XCConfigurationList section */). There look for the target id we got in 1., Then find the configuration id(s) for the configurations you need.

5. Look for build configuration id in XCBuildConfiguration section

Go to /* Begin XCBuildConfiguration section */ and look for id(s) found in 5., then add path to entitlements to it's buildSettings. E.g:

E.g. you have sth like

EB9F6CF33A861055BB38355B /* Debug */ = {
    isa = XCBuildConfiguration;
    baseConfigurationReference = B82B36921BDRI3622B0EC99 /* Pods-mytargetname.debug.xcconfig */;
    buildSettings = {
        /* build settings... */
        CODE_SIGN_ENTITLEMENTS = mytargetname/myentitlements.entitlements; /* <-- add this */
    };
    name = Debug;
};

Note that XCode should "know" the entitlements file (just like the rest of your project files).

like image 163
User Avatar answered Oct 08 '22 10:10

User