Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to append values in xcconfig variables?

Tags:

xcode

xcconfig

I'm using Xcode and .xcconfig files. I'm trying to append some values in the preprocessor definitions, but I simply can't make it work.

I tried the following (as well as many variations of this), but no luck so far:

GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'

The NEW_VALUE symbol is simply never added to the preprocessor definitions.

Does anyone had success appending new values to variables in xcconfig files?

like image 656
Martin Cote Avatar asked Sep 08 '09 13:09

Martin Cote


People also ask

How do I add files to Xcconfig?

To create an xcconfig file, choose File -> New -> File... in your project. In the new file dialog, scroll down until you see the Configuration Settings File in the Other section. You can add configurations for pretty much anything you want.

What is an Xcconfig?

Xcode build configuration files, more commonly known by their xcconfig file extension, allow build settings for your app to be declared and managed without Xcode. They're plain text, which means they're much friendlier to source control systems and can be modified with any editor.


2 Answers

For reasons stated in other answers to this question, you can't inherit values easily.

I recommend defining your settings in cascade. Let's assume APP is your project prefix and make this simple defining only a few CFLAGS:

platform.xcconfig:

APP_PLATFORM_CFLAGS = -DMAS=1 

project.xcconfig:

#include "platform.xcconfig" APP_PROJECT_CFLAGS = -DBETA=1 

target-one.xcconfig:

#include "project.xcconfig" APP_TARGET_CFLAGS = -DSUPER_COOL=1 #include "merge.xcconfig" 

target-two.xcconfig:

#include "project.xcconfig" APP_TARGET_CFLAGS = -DULTRA_COOL=1 #include "merge.xcconfig" 

merge.xcconfig:

OTHER_CFLAGS = $(inherited) $(APP_PLATFORM_CFLAGS) $(APP_PROJECT_CFLAGS) $(APP_TARGET_CFLAGS) 

Then, you'll base each of your targets build configurations on target-xxx.xcconfig. A real project will use more complex setups, using a configuration file for the project and a different one for the target, but you get the idea.

Also, remember that $(inherited) refers to higher level in the hierarchy, not earlier. For instance, it inherits from Project level at Target level. Not sure if this apply to Xcode 4 too.

This is a simplification of GTM, go there to learn more.

like image 136
djromero Avatar answered Oct 01 '22 06:10

djromero


As stated in other answers, prior to Xcode 10, xcconfig files could not simply inherit and extend each other's values. But,

Since Xcode 10, xcconfig now work as one might expect them to : $(inherited) actually expand to the previously defined value of the variable.

When an .xcconfig file contains multiple assignments of the same build setting, later assignments using $(inherited) or $(<setting_name>) will inherit from earlier assignments in the .xcconfig. The legacy build system caused every use of $(inherited) or $(<setting_name>) to skip any other values defined within the .xcconfig. To detect whether your .xcconfig is affected by this improvement, running defaults write com.apple.dt.XCBuild EnableCompatibilityWarningsForXCBuildTransition -bool YES in Terminal will cause Xcode to generate a warning about this situation.

(Xcode 10 beta 1 release notes)

So for example, given two simple .xcconfig files:

// Generic.xcconfig OTHER_SWIFT_FLAGS = $(inherited) -DMY_GENERIC_FLAG 
// Debug.xcconfig #include "Generic.xcconfig" OTHER_SWIFT_FLAGS = $(inherited) -DMY_DEBUG_FLAG 

Assuming your project uses Debug.xcconfig for its Debug configuration, you'll get the expected value -DMY_GENERIC_FLAG -DMY_DEBUG_FLAG for OTHER_SWIFT_FLAGS.

(instead of just -DMY_DEBUG_FLAG in Xcode 9 and earlier releases)


The new behavior is pretty straightforward: $(inherited) is simply replaced by the previously defined value of the variable, if any.

So in the previous example, if we expand the #include statement, we'll get the following xcconfig file:

// Merged xcconfig files after resolving #include OTHER_SWIFT_FLAGS = -DMY_GENERIC_FLAG OTHER_SWIFT_FLAGS = $(inherited) -DMY_DEBUG_FLAG 
  • On the first line OTHER_SWIFT_FLAGS value is -DMY_GENERIC_FLAG ( $(inherited) expands to nothing, because this is the first definition of OTHER_SWIFT_FLAGS we encounter1).
  • On the second line OTHER_SWIFT_FLAGS if overwritten, and its value is now -DMY_GENERIC_FLAG -DMY_DEBUG_FLAG (its previous value + the newly added flag).

On a more complex xcconfig setup, things could look like this:

// First.xcconfig OTHER_SWIFT_FLAGS = $(inherited) -DMY_FIRST_FLAG 
// Second.xcconfig OTHER_SWIFT_FLAGS = $(inherited) -DMY_SECOND_FLAG 
// Last.xcconfig #include "Generic.xcconfig" OTHER_SWIFT_FLAGS = $(inherited) -DMY_LAST_FLAG 
// Merge.xcconfig #include "First.xcconfig" #include "Second.xcconfig" OTHER_SWIFT_FLAGS = $(inherited) -DMY_INTERMEDIATE_FLAG #include "Last.xcconfig" 

We'll assume this time we're using the Merge.xcconfig in our configuration.

The resolved value for OTHER_SWIFT_FLAGS will then be -DMY_FIRST_FLAG -DMY_SECOND_FLAG -DMY_INTERMEDIATE_FLAG -DMY_GENERIC_FLAG -DMY_LAST_FLAG.

This might be surprising at first, but it actually makes sense: once the #include are resolved, we end up with this xcconfig:

OTHER_SWIFT_FLAGS = $(inherited) -DMY_FIRST_FLAG OTHER_SWIFT_FLAGS = $(inherited) -DMY_SECOND_FLAG OTHER_SWIFT_FLAGS = $(inherited) -DMY_INTERMEDIATE_FLAG OTHER_SWIFT_FLAGS = $(inherited) -DMY_GENERIC_FLAG OTHER_SWIFT_FLAGS = $(inherited) -DMY_LAST_FLAG 

The final resolved value is then the one defined on the last line, which is -DMY_LAST_FLAG plus the value it inherited from the previous line -DDMY_GENERIC_FLAG (which comes from Generic.xcconfig, included in Last.xcconfig) etc etc.

Note that naturally, if you forget $(inherited) in one of the definitions, you'll break the inheritance chain and only get the values from the bottom definitions, up to the definition without $(inherited).


1 One may expect the xcconfig file to inherit previous values defined at the Project level, but it doesn't seem to be the case


📡 As of Xcode 10 beta 1, it seems the build settings editor GUI doesn't properly resolve the correct value for variables defined in the xcconfig files, and displays the values as if resolved with the old pre-Xcode 10 behavior. I filed rdar://40873121 regarding this (https://openradar.appspot.com/radar?id=4925869923500032).

like image 28
Guillaume Algis Avatar answered Oct 01 '22 07:10

Guillaume Algis