Multiple Configuration Files Per Target - ios

In Xcode I am able to assign a single xcconfig file to my project and targets:
Is there any way to assign more than one xcconfig file to a target? In the dropdown it only allows a single selection.
I understand that I am able to override build settings from my project configuration file in my target configuration file, I'm up against a problem where I may need to have separate configuration for environments (dev, QA, prod) and separate configurations for different "flavours" of the app so being able to have multiple configuration files per target seems like a potential solution.

Configuration files support the #include statement so you could build your higher-level files from one-or-more lower-level files.

Related

NotificationServiceExtension with multiple targets in iOS Application

I have 3 targets in my iOS application namely Stage, Preprod and Prod. I added NotificationServiceExtension for the Stage target for the development purpose. Since the added NotificationServiceExtension is not available in other targets i.e pre-prod and prod, hence am not able to use the NotificationServiceExtension. Do i have to added 2 more NotificationServiceExtension for Preprod and prod targets? Or there is some different solution?
Thank you.
I'd recommend you to avoid using different targets for different environments. The better way is to use different build configurations, because:
.xcodeproj file will be much smaller
You will need single app extension
You will not need to add each new file to every target
You will not need to recompile the whole app for different environment
So in your case I'd create the following configs:
StageDebug
StageRelease
PreprodDebug
PreprodRelease
ProdDebug
ProdRelease
Here is a nice article about creating build configurations, have a look.

Set build variable in scheme instead of target

I am currently working on an iOS project in XCode that uses configurations to specify the different API environments my app can connect to. Additionally, I use targets to override one of my project configuration's user-defined values to specify a particular configuration file to use in the app. However, this is the only value that changes in the target. I work with multiple different configuration files (maybe 10 to 20 at a time) and creating a new target for each file to update one value seems clunky.
My question: Is there a way to pass this one value in from the scheme instead of setting it in the target?
I have seen that there is a pre-build script that can be run but I have not yet had any success exporting environment variables.
CONFIG_FILE="My Config File"
export CONFIG_FILE
I have also seen that some people have had success using PlistBuddy to write the values into the info.plist file during the pre-build phase of the scheme. This may be an option as well although it would require I redo a lot of my build process. I wanted to see if there was any other options before heading down this path.
Thanks for the help.
I was able to do this by using a .xcconfig file that is updated during my pre-build action in my scheme.
I used this tutorial to learn how to set up the project: http://www.jontolof.com/cocoa/using-xcconfig-files-for-you-xcode-project/

How do Xcode's ":configuration" conditional compilation directives work in an xcconfig file?

When copying a target's build settings and pasting them into an xcconfig file as plain text, one finds the output sectioned off by conditions for each build configuration, e.g.:
//:configuration = Debug
SETTING = value
SETTING = value
SETTING = value
//:configuration = Release
SETTING = value
SETTING = value
SETTING = value
//:completeSettings = some
SETTING
SETTING
SETTING
Some questions about how the ":configuration" directives are used:
If I specify a setting above all of them in the same file, will it apply to all build configurations?
I assume they apply to a group of settings below them, but do they apply to settings following empty lines?
Short answer:
The comments are neither conditions, nor directives. They are just comments, used to clarify what build configuration the entries that follow apply to. When you copy the complete build settings of a target, the resulting text is not meant to be used in a single xcconfig file. Rather, it can be used to extract the elements you need for different config files. The comments make it easy to find the settings you need for a particular build configuration.
So, if you assign an xcconfig file to the Debug build configuration of a target, you can copy the settings under //:configuration = Debug to that file, and then make any changes there, as needed.
Long answer:
You can assign exactly one xcconfig file per build configuration per target.
(You do this in the project's Info editor, under Configurations, where you'll find a list of configurations, where each configuration can be expanded to show a list comprising of the project and its targets. You can assign one config file to each of these by choosing from a list of config files. The listed config files consists of all the config files you added to the project.)
The settings listed in an assigned xcconfig file are used in the construction of the build settings for the target and build configuration combination it was assigned to, and they will be reflected in the Build Settings editor in Xcode. The build system uses a hierarchy of configuration settings that is used to construct the settings that will finally be applied.
*(You can see this reflected in the Xcode Build settings editor Select All and Levels at the top of the Build Settings editor to everything.) The build system starts out with defaults for the platform (e.g. iOS Default). These can be changed by settings at the project level, and then by settings at the target level. The Build Settings editor finally lists the Resolved settings, so that you can see exactly which settings will be applied.)*
Settings are applied in the following order, where each subsequent entry will override the previous setting:
Default -> Project Config File -> Project -> Target Config File -> Target.
So, if you specify, say, a Valid Architecture in a config file assigned to the project for a certain build configuration, then that setting will override the default setting. However, if, in Xcode's build settings editor you specify another value for that setting at the project level, then that value will override the value specified in the xcconfig file. Next, if there is an entry in an xcconfig file for the target for that build configuration, then that value will be applied, unless of course, it is overridden by a value for that setting at the target level in the Build Settings Editor. (Confused yet? :-)
As I wrote, only a single xcconfig file can be applied per target/build-configuration combination. Fortunately xcconfig files can import other xcconfig files so that groups of settings can be combined into logical units and then imported into the final xcconfig files, that are to be assigned to a target/build-configuration. If you want to learn more about the contents of xcconfig files take a look here:
The Unofficial Guide to xcconfig files

Xcode / iOS: Unit Tests, Schemes, and Configurations

My iOS project has five schemes: Local Development, Integration, QA, Demo, and Production. Each scheme uses a differing configuration to control things like network poll frequency, API endpoints, analytics, and so on.
Similarly, we have five corresponding targets: Local Development, Integration, QA, Demo, and Production. Each target has several User-Defined Build Settings, which contain API keys, numeric values for timing, etc.
Our application's Info.plist file uses application variables such as ${SOME_ENDPOINT_URL} to draw in the corresponding User-Defined Build Settings.
To retrieve the variables, I do something like the following:
[[[NSBundle mainBundle] infoDictionary] valueForKey:#"Some Endpoint URL"]
That would correspond to the User-Defined Build Setting, like this:
"Some Endpoint URL" = ${SOME_ENDPOINT_URL}
I am now looking at how to configure the project appropriately to perform unit and logic tests.
To build out the tests to determine if the environments are configured correctly, I'm not certain what the best practice is.
Is it correct to build out five additional Test-specific targets for each environment?
Or is it better to override the "Run action's arguments" setting for the test component for each scheme, and provide something like an argument to specify which scheme we are looking at?
Are there any existing references for configuring unit and logic tests for iOS projects with multiple environments? This project's complexity seems to exceed the scope of most documentation.
The following are what I do.
Info.plist
Create a master Info.plist file
Write a run script (Shell Script) for each scheme to generate a environment-specific Info.plist by modifying settings in the master Info.plist (Use PlistBuddy -c)
Add the run script to Build Phases (above "Compile Sources")
.h file
Define configuration settings in a .h file (e.g. config.h)
#if defined (CONFIG_FILE)
#import CONFIG_FILE
#endif
Import config.h in your code
Use pre-processor macros for each scheme to select the target .h file.
-DCONFIG_FILE=local-env-config.h

How can I save all my build settings from 1 xcode project and use them on other xcode projects?

I'm using xcode 4.5 and cordova/phonegap to build my apps. I have invested a lot of time into getting the build settings just right for my xcode project and I would like to reuse these settings on multiple apps I am building. I'm looking to see if there is a fast way to export these settings or build a template that I can use for future projects.
I've tried copying the project folder and changing the name and that does not work. I get an error when working with the cordovalib.xcodeproj file.
Any help on exporting these settings or creating a template would be appreciated.
Use an .xcconfig file.
http://developer.apple.com/library/ios/#recipes/xcode_help-project_editor/Articles/BasingBuildConfigurationsonConfigurationFiles.html
File.. New File.. Then choose the Configuration Settings File from the Other section.
You will have to copy the build settings from your xcodeproj file. Open your xcodeproj file in a text editor and copy:
buildSettings = { ... }
Into your xcconfig file. Be aware that the xcconfig file has a specific format. The above video / Apple documentation should help you.
You will then need to tell Xcode which xcconfig file to use for each build configuration.. Debug, Release, etc. You can do this by importing it under your Project's Info tab, under Configurations.
XCConfig files are certainly the way to go for sharing build settings across multiple targets or even projects.
As StuR wrote six years ago, you still add a configuration file from the New File dialog in XCode. It is just a text file with a key value format.
The easiest way to add configuration values is — in my opinion — to go to the build settings of your target, select the row of the setting you want to modify and press cmd+c to copy it. When you paste in the config file, it will be inserted in the right format.
To add the config file to your target, you need to go to the project settings. There is a Configurations section where you can set the config files for each target and configuration (Debug, Release, etc)
You find the official documentation for XCConfig files here: https://help.apple.com/xcode/mac/10.1/#/dev745c5c974
One very usefull feature of the XCConfig files is that you can import other XCConfig files and build a kind of inheritance schema.

Resources