Skip to Content
Technical Articles

SAP Cloud Platform Mobile Services connection URLs per Xcode Build Settings

A customer asked me a question this week, about how best to manage multiple iOS client builds with the SAP Cloud Platform SDK for iOS which are targeting different SAP Cloud Platform Mobile Service tenants (TEST, QUAL, PROD).  The tenant-specific builds will then be made available to targeted user groups via an internal App Store.

There are a couple ways to handle this, but they all relate to using the Xcode Project Build Settings.  We’ll start there, modifying a project generated from the Assistant macOS application with SAPFioriFlows framework.

To start from the same point as the project below, using the Assistant, ensure that if you are using a Neo SAP Cloud Platform instance, the ‘Use Discovery Service’ feature is un-checked in the application.  If using a CF instance, this option should be hidden; if not (on an older version of Assistant) make sure it is also unchecked.  This will cause us to generate the connection settings into a file named ‘ConfigurationProvider.plist’.

First, select the Xcodeproj file in the Xcode Project Navigator.  This brings up the window containing your Targets, and the Project. Your current Target will typically be selected by default.  Switch to the Project.

Here, you can manage a number of configuration-related setups, including assigning xcconfig files, adding localization to the project, etc.  What we want to do, is create Configurations to match our TEST, QUAL, and PROD landscapes.  Click the “+” button, under the ‘Configurations’ section.  You’ll be prompted to duplicate either your Debug or Release configurations.  I would probably recommend picking ‘Debug’ for TEST; then ‘Release’ for QUAL and PROD.  But, you could go with Release for all three as well.  Name them for their respective tenant.

Now, let’s create the per-landscape configurations.  In the generated app, locate the file ConfigurationProvider.plist, in the Onboarding group.  Explore the contents a bit:  it contains the connection url for the SAP Cloud Platform tenant, and any authentication-related configurations.  This is the file in which we will provide our Build Settings-specific configurations.

Right-click on the file in the Project Navigator, and select ‘Show in Finder’.  Here, create 3 copies of the file, and add suffixes for each of the Build Settings Names.  E.g.:  ConfigurationProvider_PROD.plist.

Double-click on the ConfigurationProvider_TEST.plist to open it.  Let’s modify it slightly, to simulate having custom connection settings.  Click the ‘+’ button next to ‘Root’ to add a new String type key-value entry.  Name the key ‘MODE’, and the value ‘TEST’.

Do the same for QUAL and PROD.

Last, switch back to Xcode, right click on ConfigurationProvider.plist in the Project Navigator again, and select ‘Delete’.  When prompted to ‘Remove Reference’, or ‘Move to Trash’, choose ‘Remove Reference’.

We still want the file in the source directory with the per-tenant copies, but instead of including it in the default copied resources, we’re going to add a script which picks the correct file from our current build settings.

Go back to the Xcodeproj file in the Project Navigator, and switch back to your App Target.  Scan across the menu items to locate Build Phases.

Click the “+” button above the listed build phases, and select “New Run Script Phase”.

This will add a new phase to the end of the list, named ‘Run Script’.  Double-click on the name to edit, and rename the phase to ‘Pick ConfigurationProvider’.  Then, click on the arrow to expand the phase.

Copy/paste the following script, to the shell canvas:

CONFIGURATION_PROVIDER_FILE="ConfigurationProvider.plist"

if [ $CONFIGURATION == "TEST" ] || [ $CONFIGURATION == "QUAL" ] || [ $CONFIGURATION == "PROD"]; then

    CONFIGURATION_PROVIDER_FILE="ConfigurationProvider_${CONFIGURATION}.plist"

fi

echo "Copying ${SRCROOT}/${PRODUCT_NAME}/Onboarding/${CONFIGURATION_PROVIDER_FILE}"

cp -R ${SRCROOT}/${PRODUCT_NAME}/Onboarding/${CONFIGURATION_PROVIDER_FILE} ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/ConfigurationProvider.plist

echo "Custom configuration provider plist has been copied."

Summarizing the script:  if our current build configuration is TEST, QUAL, or PROD, then we will copy that respective ConfigurationProvider_* file, to the app build.  (If Debug or Release are used, then we’ll just grab the original unmodified ConfigurationProvider.plist).  You might end up deleting these Build Setting options entirely, but they tend to live on in most projects, so we’ll just leave them in and work around them in the script.

To test:  we need to pick which Build Setting we want to use, in the Scheme.  Schemes are combinations of targets and configurations, for each of the Xcode build commands (build, run, test, profile, analyze, archive).  Click on the Active Scheme button next to the Run and Stop buttons in the upper left of the screen, and select ‘Edit Scheme’.

For this example, choose the ‘Run’ command to configure, and pick ‘TEST’ from the ‘Build Configuration’ drop-down under the ‘Info’ tab.

Click ‘Close’, then execute ‘Build and Run’.  You should see the application launch, with a ‘Start’ button on the home screen.  This means that it successfully read the ConfigurationProvider.plist settings in the SAPFioriFlows on boarding component.  Success!

To confirm that we do indeed have the correct properties:

  1. Review the Build log in the Report Navigator.  Hit ‘Command+9’ to switch to the Report Navigator, and select the most recent successful (or unsuccessful, if you have a failure) Build.You should have a section entitled ‘Run custom shell script ‘Copy ConfigurationProvider’, with the statements:
    Copying /<my path>/ResourcePerBuildSetting/Onboarding/ConfigurationProvider_TEST.plist
    Custom configuration provider plist has been copied.

  2.  Switch back to the Project Navigator by hitting ‘Command+1’, expand the ‘Products’ group, and select your *.app product.  Right-click, and pick ‘Show in Finder’.

    In Finder, again right-click on the app product, and now select ‘Show Package Contents’.

    Here’s the contents of your application.  Double-click on the ConfigurationProvider.plist file to open it.  You should see your MODE=TEST entry.  If so, success!

So now, we’ve proven that we can supply custom configurations to the compiled application, based on the selected build settings, that are compatible with the SAPFioriFlows on boarding implementation in the generated app from the Assistant.  Before you go, let me share a few techniques for using this productively.

  1. Edit the scheme.  You’ve already seen, that you can edit the default scheme’s settings for the Run command to pick from particular settings.  This is convenient for individual testers, but not practical for a CI system.
  2. Create a custom scheme for each Build Settings.   This approach is feasible, since -scheme is an optional parameter in the xcodebuild command line tools.
  3. Pass the -configuration flag to xcodebuild command line tools.For this simple case, this is the least amount of duplication required.  To validate, switch back to your App Target settings, and make sure that you have a Developer Team selected, under the ‘Signing’ section.  (easiest is to check the ‘Automatically manage signing’ box).


    Then run the xcodebuild command:

    xcodebuild -project ResourcePerBuildSetting.xcodeproj/ -configuration QUAL

    You should see:  **BUILD SUCCEEDED** in the terminal.

There you have it.  Xcode Build Settings configurations are powerful tools for modifying or parameterizing your build environment.  Since we had a discrete plist file to manage, we were able to combine them with a simple Run Script build phase, to copy the correct resource to connect our users to the respective tenant.

For more complex configurations, or for runtime-level environmental parameters in Swift, you should also investigate xcconfig files.  This was unnecessary in this case since the SAPFioriFlows.FileConfigurationProvider instance is looking for a file named ConfigurationProvider.plist.  But, for runtime parameters, such as Developer Keys, etc., they are an additional powerful tool for your CI toolkit.  Check out some 3rd-party resources:

  • https://www.appcoda.com/xcconfig-guide/
  • https://nshipster.com/xcconfig/

Happy Compiling!

1 Comment
You must be Logged on to comment or reply to a post.
  • thanks Stan I was actually looking at this, it will saved me some time.

    Sometimes I have customers that like to be able to select the system (DEV, QA, Production) from the app settings (inside Settings.bundle)

    in that case I duplicate the configuration provider file like you did and inside the

    OnboardingFlowProvider class, method configuredWelcomeScreenStep, I can read the settings.bundle and supplied the correct file path to the initializer of the FileConfigurationProvider

     

    Appart from the ConfigurationFileProvider file, there is a URL hardcode that is generated by the assistant … (I used SAML when I generated my code using the assistant)

    inside the class ODataOnboardingStep, method configureData, the URL of the tenant with the destination is hardcode, it should be retrieve instead from the configuration file provider like this

     

            let settingsParameters = context.info[.sapcpmsSettingsParameters] as! SAPcpmsSettingsParameters
            
            let destinationName = settingsParameters.destinations!.first!.value
       
            let configurationURL = URL(string: destinationName, relativeTo: settingsParameters.backendURL)!

     

    here is the Gist from my Github

     

    thanks

     

    Alex