【问题标题】:How to append values in xcconfig variables?如何在 xcconfig 变量中附加值?
【发布时间】:2009-09-08 13:19:34
【问题描述】:

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

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

GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'

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

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

【问题讨论】:

    标签: xcode xcconfig


    【解决方案1】:

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

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

    平台.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)
    

    然后,您将每个目标构建配置基于target-xxx.xcconfig。一个真正的项目将使用更复杂的设置,为项目使用一个配置文件,为目标使用一个不同的配置文件,但你明白了。

    另外,请记住,$(inherited) 指的是层次结构中的更高级别,而不是早期。例如,它从目标级别的项目级别继承。不确定这是否也适用于 Xcode 4。

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

    【讨论】:

      【解决方案2】:

      如其他答案所述,在 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 进行其调试配置,您将获得 -DMY_GENERIC_FLAG -DMY_DEBUG_FLAG 的预期值 OTHER_SWIFT_FLAGS

      (而不仅仅是 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 -showBuildSettings 也有这个错误。然而,宏定义似乎在预处理时起作用。
      • 从 Xcode 12.5(我测试的唯一 Xcode 版本)开始,此答案中描述的行为似乎不再是这种情况。其他人也是这样吗?
      • @RogerOba 我刚刚验证过,Xcode 12.5 中似乎没有任何变化
      • @GuillaumeAlgis 我的测试场景与答案顶部的“通用+调试”完全相同。我观察到的是,当我使用 $(inherited) 时,变量(在我的例子中是 PRODUCT_NAME)是空的(是的,我在顶部#include'ing generic.xcconfig 引用),但是如果我定义了一个自定义变量( MY_VARIABLE) 在 generic.xcconfig 中,$(inherited) 确实正确地返回了它的值。你看到了什么不同的东西吗?你能这么好心地尝试一下 PRODUCT_NAME 吗?
      • @RogerOba 在PRODUCT_NAME 中使用$(inherited) 似乎确实有问题。我认为它与我在答案末尾提到的错误有关。在某些地方 Xcode 理解新的继承系统(我有一个使用完整继承名称创建的 .app),而在其他一些地方它不理解,这会导致问题。我在一个示例项目中转载:github.com/guillaumealgis/…
      【解决方案3】:

      根据 Xcode 构建系统指南:

      当一个配置单元包含 一个以上的定义 特定的构建设置,Xcode 使用 单元中的最后一个定义。保持 请记住,配置文件确实 无权访问构建设置 配置中的定义 他们包括的文件。那是你 不能修改中的定义 包含的配置文件;你 只能换了。

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

      【讨论】:

        【解决方案4】:

        这行得通:

        xcodebuild GCC_PREPROCESSOR_DEFINITIONS='$(value) NEW_VALUE'
        

        【讨论】:

        • 谢谢,不过我只是使用GCC_PREPROCESSOR_DEFINITIONS=$(value) NEW_VALUE(没有引号)。
        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          我想我在尝试将 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 配置加载的文件将正确覆盖设置。

          【讨论】:

          • GCC_PREPROCESSOR_DEFINITIONS[config=*] = ... 语法适用于 Xcode 5。我在特定于目标的 .xcconfig 文件中使用它来将集中定义的项目范围的构建设置附加到特定于目标的设置:BLA[config=*] = $(BLA_TARGET_SPECIFIC) $(BLA_PROJECT_WIDE)。跨度>
          【解决方案7】:

          这在 Xcode 2.4.1 中适用于我:

          GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE"

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

          【讨论】:

          • XCode 3.2 运气不佳 :(
          【解决方案8】:

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

          GCC_PREPROCESSOR_DEFINITIONS = "$(inherited) NEW_VALUE"
          

          【讨论】:

          • 这看起来是一个完美的答案,但它是错误的。 $(inherited) xcconfig 文件中不起作用;特别是,您不能使用它来扩展包含文件的定义。
          • 那你怎么扩展?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-08
          • 1970-01-01
          • 2020-10-17
          • 2013-11-09
          • 2021-10-11
          • 1970-01-01
          相关资源
          最近更新 更多