xcode 如何在 xcconfig 变量中附加值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1393987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to append values in xcconfig variables?
提问by Martin Cote
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.
我正在使用 Xcode 和 .xcconfig 文件。我试图在预处理器定义中附加一些值,但我根本无法让它工作。
I tried the following (as well as many variations of this), but no luck so far:
我尝试了以下(以及它的许多变体),但到目前为止没有运气:
GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'
GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'
The NEW_VALUE
symbol is simply never added to the preprocessor definitions.
该NEW_VALUE
符号永远不会添加到预处理器定义中。
Does anyone had success appending new values to variables in xcconfig files?
有没有人成功地将新值附加到 xcconfig 文件中的变量?
回答by djromero
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:
我建议在级联中定义您的设置。让我们假设 APP 是您的项目前缀,并使这个简单的定义仅几个 CFLAGS:
platform.xcconfig:
平台.xcconfig:
APP_PLATFORM_CFLAGS = -DMAS=1
project.xcconfig:
项目.xcconfig:
#include "platform.xcconfig"
APP_PROJECT_CFLAGS = -DBETA=1
target-one.xcconfig:
目标one.xcconfig:
#include "project.xcconfig"
APP_TARGET_CFLAGS = -DSUPER_COOL=1
#include "merge.xcconfig"
target-two.xcconfig:
目标二.xcconfig:
#include "project.xcconfig"
APP_TARGET_CFLAGS = -DULTRA_COOL=1
#include "merge.xcconfig"
merge.xcconfig:
合并.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.
然后,您将基于target-xxx.xcconfig
. 一个真正的项目将使用更复杂的设置,为项目使用一个配置文件,为目标使用一个不同的配置文件,但你明白了。
Also, remember that $(inherited)
refers to higherlevel in the hierarchy, not earlier. For instance, it inherits from Project level at Target level. Not sure if this apply to Xcode 4 too.
另外,请记住,$(inherited)
指的是层次结构中的更高级别,而不是更早的。例如,它在目标级别从项目级别继承。不确定这是否也适用于 Xcode 4。
This is a simplification of GTM, go there to learn more.
这是GTM的简化,去那里了解更多。
回答by Martin Cote
According to the Xcode Build System Guide:
根据 Xcode 构建系统指南:
When a configuration unit contains more than one definition for a particular build setting, Xcode uses the last definition in the unit. Keep in mind that configuration files do not have access to build setting definitions made in configuration files they include. That is, you cannot modify the definition made in an included configuration file; you can only replace it.
当配置单元包含多个特定构建设置的定义时,Xcode 使用单元中的最后一个定义。请记住,配置文件无权访问它们包含的配置文件中的构建设置定义。也就是说,您不能修改包含在配置文件中的定义;你只能更换它。
So, I guess this mean that it is not possible to append values to a given variable.
所以,我想这意味着不可能将值附加到给定的变量。
回答by Laxman Battini
This works:
这有效:
xcodebuild GCC_PREPROCESSOR_DEFINITIONS='$(value) NEW_VALUE'
回答by Guillaume Algis
As stated in other answers, prior to Xcode 10, xcconfig files could not simply inherit and extend each other's values. But,
正如其他答案中所述,在 Xcode 10 之前,xcconfig 文件不能简单地继承和扩展彼此的值。但,
Since Xcode 10, xcconfig now work as one might expect them to : $(inherited)
actually expand to the previously defined value of the variable.
从 Xcode 10 开始,xcconfig 现在像人们期望的那样工作:$(inherited)
实际上扩展到先前定义的变量值。
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, runningdefaults write com.apple.dt.XCBuild EnableCompatibilityWarningsForXCBuildTransition -bool YES
in Terminal will cause Xcode to generate a warning about this situation.
当 .xcconfig 文件包含同一构建设置的多个分配时,以后的分配使用
$(inherited)
或$(<setting_name>)
将从 .xcconfig 中的早期分配继承。遗留构建系统导致每次使用$(inherited)
或$(<setting_name>)
跳过 .xcconfig 中定义的任何其他值。要检测您的 .xcconfig 是否受到此改进的影响,defaults write com.apple.dt.XCBuild EnableCompatibilityWarningsForXCBuildTransition -bool YES
在终端中运行将导致 Xcode 生成有关这种情况的警告。
(Xcode 10 beta 1 release notes)
(Xcode 10 beta 1 发行说明)
So for example, given two simple .xcconfig files:
例如,给定两个简单的 .xcconfig 文件:
// 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
.
假设你的项目使用Debug.xcconfig其调试配置,你会得到的预期值-DMY_GENERIC_FLAG -DMY_DEBUG_FLAG
的OTHER_SWIFT_FLAGS
。
(instead of just -DMY_DEBUG_FLAG
in Xcode 9 and earlier releases)
(而不仅仅是-DMY_DEBUG_FLAG
在 Xcode 9 和更早版本中)
The new behavior is pretty straightforward: $(inherited)
is simply replaced by the previously defined value of the variable, if any.
新行为非常简单:$(inherited)
只需替换为变量的先前定义的值(如果有)。
So in the previous example, if we expand the #include
statement, we'll get the following xcconfig file:
所以在前面的例子中,如果我们展开#include
语句,我们将得到以下 xcconfig 文件:
// 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 ofOTHER_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).
- 第一行的
OTHER_SWIFT_FLAGS
值是-DMY_GENERIC_FLAG
($(inherited)
扩展为空,因为这是OTHER_SWIFT_FLAGS
我们遇到1的第一个定义)。 - 在第二行
OTHER_SWIFT_FLAGS
如果被覆盖,它的值现在是-DMY_GENERIC_FLAG -DMY_DEBUG_FLAG
(它的前一个值 + 新添加的标志)。
On a more complex xcconfig setup, things could look like this:
在更复杂的 xcconfig 设置中,事情可能如下所示:
// 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.
我们假设这次我们在配置中使用 Merge.xcconfig。
The resolved value for OTHER_SWIFT_FLAGS
will then be -DMY_FIRST_FLAG -DMY_SECOND_FLAG -DMY_INTERMEDIATE_FLAG -DMY_LAST_FLAG
.
为解决价值OTHER_SWIFT_FLAGS
将被-DMY_FIRST_FLAG -DMY_SECOND_FLAG -DMY_INTERMEDIATE_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:
起初这可能令人惊讶,但实际上是有道理的:一旦#include
解决,我们最终会得到这个 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_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 -DMY_INTERMEDIATE_FLAG
etc etc.
最终解析的值是在最后一行定义-DMY_LAST_FLAG
的值,加上它从前一行继承的值-DMY_INTERMEDIATE_FLAG
等等。
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 the definition without $(inherited)
.
请注意,自然而然地,如果您忘记$(inherited)
了其中一个定义,您将破坏继承链,并且只能从底部定义中获取值,向上没有$(inherited)
.
1One may expect the xcconfig file to inherit previous values defined at the Project level, but it doesn't seem to be the case
1人们可能期望 xcconfig 文件继承在项目级别定义的先前值,但情况似乎并非如此
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).
从 Xcode 10 beta 1 开始,构建设置编辑器 GUI 似乎无法正确解析 xcconfig 文件中定义的变量的正确值,并显示这些值就像使用旧的 Xcode 10 之前的行为解析一样。我就此提交了 rdar://40873121(https://openradar.appspot.com/radar?id=4925869923500032)。
回答by James Moore
I think I've stumbled on a slightly better approach while trying to integrate the Cocoapods xcconfig files into my own. I like to set the following in my projects
我想我在尝试将 Cocoapods xcconfig 文件集成到我自己的文件中时偶然发现了一个稍微更好的方法。我喜欢在我的项目中设置以下内容
GCC_PREPROCESSOR_DEFINITIONS = CONFIGURATION_$(CONFIGURATION)
Unfortunately this conflicts with the definitions that comes with the Pods.xcconfig. As is stated elsewhere $(inherited) doesn't work as expected. What does work is the following
不幸的是,这与 Pods.xcconfig 附带的定义冲突。正如其他地方所说, $(inherited) 不能按预期工作。什么工作是以下
GCC_PREPROCESSOR_DEFINITIONS[config=*] = CONFIGURATION_$(CONFIGURATION) $(inherited)
UPDATE:
更新:
If you need to override a setting for a particular configuration then you'd be tempted to write something like
如果您需要覆盖特定配置的设置,那么您可能会想写一些类似的东西
GCC_PREPROCESSOR_DEFINITIONS[config=*] = CONFIGURATION_$(CONFIGURATION) $(inherited)
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG=1 CONFIGURATION_$(CONFIGURATION) $(inherited)
Sadly this won't work BUT putting the second declaration into a file that only get's loaded by the Debug configuration will properly override setting.
遗憾的是,这行不通,但将第二个声明放入仅由调试配置加载的文件将正确覆盖设置。
回答by fbrereto
There is another questionwith an answer that might help with this particular problem. It describes a technique that has each layer compose a subset of the definitions, then bring them all together at the leaf-level xcconfig.
还有另一个问题的答案可能有助于解决这个特定问题。它描述了一种技术,让每一层组成定义的一个子集,然后在叶级 xcconfig 将它们组合在一起。
回答by Charles Anderson
This works for me in Xcode 2.4.1:
这在 Xcode 2.4.1 中对我有用:
GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE"
You do have to sometimes allow a few seconds between editing a config file and the change showing up in a target's Build Info.
您有时必须在编辑配置文件和目标构建信息中显示的更改之间留出几秒钟的时间。
回答by cdespinosa
You want to use the placeholder $(inherited) to represent the value inherited from lower levels, e.g.
您想使用占位符 $(inherited) 来表示从较低级别继承的值,例如
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited) NEW_VALUE"