我正在使用Xcode和.xcconfig文件。我想要在预处理器定义中添加一些值,但我无法使其起作用。
我尝试了以下方法(以及许多变化),但目前还没有成功:
GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'
符号NEW_VALUE
从未被添加到预处理器定义中。
是否有人成功地将新值追加到xcconfig文件中的变量中?
由于其他答案中提到的原因,您不能轻松地继承值。
我建议采用级联定义设置。假设APP是您的项目前缀,让我们简单地定义一些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"
目标-two.xcconfig:
#include "project.xcconfig"
APP_TARGET_CFLAGS = -DULTRA_COOL=1
#include "merge.xcconfig"
合并.xcconfig:
OTHER_CFLAGS = $(inherited) $(APP_PLATFORM_CFLAGS) $(APP_PROJECT_CFLAGS) $(APP_TARGET_CFLAGS)
然后,你将基于 target-xxx.xcconfig
为每个目标构建配置创建。一个真实的项目将使用更复杂的设置,使用一个项目配置文件和一个不同的目标配置文件,但是这个想法很清楚了。$(inherited)
是指在层次结构中 更高级别的,而不是 更早的。例如,在目标层面它从项目层面继承。不确定这是否也适用于 Xcode 4。如其他答案所述,在 Xcode 10 之前,xcconfig 文件不能简单地继承和扩展彼此的值。但是,
自从 Xcode 10 起,xcconfig 现在可以按照人们的期望工作:$(inherited)
实际上会扩展为变量的先前定义值。
当一个 .xcconfig 文件包含同一构建设置的多个赋值时,使用
$(inherited)
或$(<setting_name>)
进行的后续赋值将继承 .xcconfig 中较早的赋值。传统的构建系统导致每个使用$(inherited)
或$(<setting_name>)
的情况都跳过 .xcconfig 中定义的任何其他值。要检测您的 .xcconfig 是否受到此改进的影响,请在终端中运行defaults write com.apple.dt.XCBuild EnableCompatibilityWarningsForXCBuildTransition -bool YES
,这将导致 Xcode 生成有关此情况的警告。
(Xcode 10 beta 1 发布说明)
例如,给定两个简单的 .xcconfig 文件:
// Generic.xcconfig
OTHER_SWIFT_FLAGS = $(inherited) -DMY_GENERIC_FLAG
// Debug.xcconfig
#include "Generic.xcconfig"
OTHER_SWIFT_FLAGS = $(inherited) -DMY_DEBUG_FLAG
假设您的项目在Debug配置中使用Debug.xcconfig,您将会在OTHER_SWIFT_FLAGS
中得到预期的值-DMY_GENERIC_FLAG -DMY_DEBUG_FLAG
,而不是在Xcode 9及之前的版本中仅得到-DMY_DEBUG_FLAG
。
新行为非常简单:如果有的话,$(inherited)
将被先前定义的变量值替换。
因此,在上面的示例中,如果我们展开#include
语句,我们将得到以下xcconfig文件:
// Merged xcconfig files after resolving #include
OTHER_SWIFT_FLAGS = -DMY_GENERIC_FLAG
OTHER_SWIFT_FLAGS = $(inherited) -DMY_DEBUG_FLAG
OTHER_SWIFT_FLAGS
值为-DMY_GENERIC_FLAG
($(inherited)
不会被展开,因为这是我们遇到的第一个OTHER_SWIFT_FLAGS
的定义1)。OTHER_SWIFT_FLAGS
被覆盖,并且它的值现在为-DMY_GENERIC_FLAG -DMY_DEBUG_FLAG
(它之前的值加上新添加的标志)。在更复杂的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"
我们假设这一次我们在配置中使用Merge.xcconfig。
OTHER_SWIFT_FLAGS
的解析值将是-DMY_FIRST_FLAG -DMY_SECOND_FLAG -DMY_INTERMEDIATE_FLAG -DMY_GENERIC_FLAG -DMY_LAST_FLAG
。
起初可能会感到惊讶,但实际上这是有道理的:一旦#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_GENERIC_FLAG
OTHER_SWIFT_FLAGS = $(inherited) -DMY_LAST_FLAG
最终解析的值是最后一行定义的值,即 -DMY_LAST_FLAG
加上它从上一行继承的值 -DDMY_GENERIC_FLAG
(这个值来自于 Generic.xcconfig,包含在 Last.xcconfig 中)等等。
请注意,如果您在其中一个定义中忘记了 $(inherited)
,则会破坏继承链,只会获得从底部定义开始的值,直到没有 $(inherited)
的定义。
1 人们可能期望 xcconfig 文件继承在项目级别定义的先前值,但似乎并不是这种情况。
截至 Xcode 10 beta 1,构建设置编辑器 GUI 似乎无法正确解析在 xcconfig 文件中定义的变量的正确值,并显示值,就像使用旧的 Xcode 10 之前的行为解析的值一样。我在此方面提交了 rdar://40873121 的问题报告 (https://openradar.appspot.com/radar?id=4925869923500032)。
这个有效:
xcodebuild GCC_PREPROCESSOR_DEFINITIONS='$(value) NEW_VALUE'
GCC_PREPROCESSOR_DEFINITIONS=$(value) NEW_VALUE
(不带引号)。 - mkeiser我认为在尝试将Cocoapods的xcconfig文件集成到我的项目中时,我意外发现了一个更好的方法。我喜欢在我的项目中设置以下内容:
GCC_PREPROCESSOR_DEFINITIONS = CONFIGURATION_$(CONFIGURATION)
不幸的是,这与Pods.xcconfig附带的定义发生了冲突。正如其他地方所述,$(inherited)不能按预期工作。下面的内容可以正常工作:
GCC_PREPROCESSOR_DEFINITIONS[config=*] = CONFIGURATION_$(CONFIGURATION) $(inherited)
更新:
如果您需要覆盖特定配置的设置,则可能会尝试编写类似以下内容的代码:
GCC_PREPROCESSOR_DEFINITIONS[config=*] = CONFIGURATION_$(CONFIGURATION) $(inherited)
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG=1 CONFIGURATION_$(CONFIGURATION) $(inherited)
GCC_PREPROCESSOR_DEFINITIONS[config=*] = ...
语法在 Xcode 5 中有效。我在特定目标的 .xcconfig
文件中使用它来将中心定义的项目范围构建设置附加到特定目标设置中:BLA[config=*] = $(BLA_TARGET_SPECIFIC) $(BLA_PROJECT_WIDE)
。 - bassimGCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE"有时你需要允许几秒钟的时间,在编辑配置文件和更改出现在目标的“构建信息”之间。
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited) NEW_VALUE"
$(inherited)
在xcconfig
文件内部不起作用;特别是,你不能使用它来扩展从一个已包含的文件中继承的定义。 - Jens Ayton
PRODUCT_NAME
中使用$(inherited)
确实存在问题。我认为这与我在答案末尾提到的错误有关。在某些地方,Xcode可以理解新的继承系统(我有一个使用完整继承名称创建的 .app),而在其他一些地方则不行,这会导致问题。我在一个示例项目中重现了这个问题: https://github.com/guillaumealgis/SO-1393987-ProductNameInheritanceXcconfig - Guillaume Algis