48

我正在使用 Xcode 和 .xcconfig 文件。我试图在预处理器定义中附加一些值,但我根本无法让它工作。

我尝试了以下(以及许多变体),但到目前为止没有运气:

GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'

NEW_VALUE符号根本不会添加到预处理器定义中。

有没有人成功地将新值附加到 xcconfig 文件中的变量?

4

8 回答 8

36

由于此问题的其他答案中所述的原因,您不能轻易继承值。

我建议在级联中定义您的设置。让我们假设 APP 是您的项目前缀,并简单地定义几个 CFLAGS:

平台.xcconfig:

APP_PLATFORM_CFLAGS = -DMAS=1

项目.xcconfig:

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

目标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。

这是GTM的简化版,去那里了解更多。

于 2011-03-13T12:39:25.877 回答
19

如其他答案所述,在 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.xcconfig 作为其 Debug 配置,您将-DMY_GENERIC_FLAG -DMY_DEBUG_FLAG获得OTHER_SWIFT_FLAGS.

(而不仅仅是-DMY_DEBUG_FLAG在 Xcode 9 和更早的版本中)


新行为非常简单:$(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 )。

于 2018-06-06T23:34:35.227 回答
10

根据 Xcode 构建系统指南:

当一个配置单元包含多个特定构建设置的定义时,Xcode 使用该单元中的最后一个定义。请记住,配置文件无权访问它们包含的配置文件中的构建设置定义。也就是说,您不能修改包含的配置文件中的定义;你只能更换它。

所以,我想这意味着不可能将值附加到给定的变量。

于 2009-09-09T19:44:00.470 回答
9

这有效:

xcodebuild GCC_PREPROCESSOR_DEFINITIONS='$(value) NEW_VALUE'
于 2012-09-27T16:30:53.283 回答
4

我想我在尝试将 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)

遗憾的是,这不起作用,但将第二个声明放入仅由 Debug 配置加载的文件将正确覆盖设置。

于 2014-08-14T22:13:02.483 回答
4

还有另一个问题的答案可能有助于解决这个特定问题。它描述了一种技术,让每一层组成定义的子集,然后在叶级 xcconfig 将它们全部组合在一起。

于 2010-01-15T19:37:05.900 回答
1

这在 Xcode 2.4.1 中对我有用:

GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE"

在编辑配置文件和显示在目标的构建信息中的更改之间,您有时必须留出几秒钟的时间。

于 2009-09-09T10:11:56.140 回答
0

您想使用占位符 $(inherited) 来表示从较低级别继承的值,例如

GCC_PREPROCESSOR_DEFINITIONS = "$(inherited) NEW_VALUE"
于 2010-01-15T21:51:40.643 回答