简而言之
是否可以从父项目继承自定义配置?不,不是在询问如何继承某些目标设置。
配置和预处理器宏/标志
Xcode中的每个项目都初始化了两个名为Debug
和Release
的标准配置。使用目标(在.pbxproj
中称为GCC_PREPROCESSOR_DEFINITIONS
)下的显示名称为Preprocessor Macros
的设置来设置一个DEBUG
标志是一种常见的模式,这可以从Objective-C代码中读取,如下所示。
#ifdef DEBUG
print("DEBUG flag set")
#else
print("No debug flag!")
#endif
这也适用于Swift,但是我们必须使用
OTHER_SWIFT_FLAGS
并像这样声明:-D DEBUG
并且读取变量值的方式与上面的Objective C代码相同。
许多项目 => xcconfig文件
我的应用程序由一个包含主要项目和几个依赖项项目的xcworkspace组成。让我们称我所依赖的项目为框架。由于我有几个框架,我不想多次设置构建设置。
因此,我使用
xcconfig
文件。我有一个主配置文件,即主项目的配置文件,让我们称其为Main.xcconfig
。我还有另一个名为Framework.xcconfig
的配置文件,它以#include "Main.xcconfig"
开头,从而继承了Main
的设置。当然,我设置每个框架以利用该Framework.xcconfig
文件。有这些配置文件时声明
DEBUG
标志非常方便,在Main.xcconfig
中添加:OTHER_SWIFT_FLAGS[config=Debug] = -D DEBUG
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG
因此,在主项目和框架项目中为配置Debug
标志声明DEBUG
标志(因为Framework.xcconfig
继承自Main.xcconfig
...)。
自定义配置
如果我们想要能够使用设置了DEBUG
标志的应用程序进行分析,那该怎么办呢?分析应该使用与Release
相同的优化标志。但是我们绝不希望为Release
构建设置DEBUG
标志。
为什么不创建一个新的配置,让我们称其为Profiling
。问题来了!当然,我们应该将这个新的配置添加到主项目中。然后我们编辑我们的方案,在Profile下选择Build Configuration中的新配置Profiling
。
现在,我们可以在Main.xcconfig
文件中为Profiling
设置DEBUG
标志。
OTHER_SWIFT_FLAGS[config=Debug] = -D DEBUG // we keep this
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG // we keep this
OTHER_SWIFT_FLAGS[config=Profiling] = -D DEBUG
GCC_PREPROCESSOR_DEFINITIONS[config=Profiling] = DEBUG
我们尝试运行模拟器,然后看到了"No debug flag!"的提示,这是预期的,因为我们正在使用Debug
配置来运行,因此没有声明DEBUG
标志。
所以我们尝试进行分析,并启动一些Instruments测量和打开控制台。在那里,我们看到了消息"DEBUG flag set"
它有效了,太棒了!
配置不会从父项目继承
我们刚刚针对主项目检查了DEBUG
标志。如果我们想在某个框架中检查自己的标志会发生什么情况。因此,我们在某个框架中尝试使用#ifdef DEBUG
。 这可以工作,因为所有框架都具有配置Debug
,因为它是所有项目的默认配置(与Release
一起)。
然后我们在一个框架项目中尝试#ifdef DEBUG
,并再次使用Instruments进行分析。现在我们看到了消息"No debug flag!"
哦不!它不工作了!为什么?我不知道,但唯一合理的结论就是我们添加为依赖项的项目 - 我们的框架 - 没有从主项目继承 Profiling
配置。
对我来说,这太不可思议了...感觉像是Xcode中的一个缺陷。
糟糕的解决方案
我不知道除了将相同的配置 Profiling
添加到所有框架项目(至少对于我想要检查该标志的框架)之外还有其他解决方案。但这感觉像是一个丑陋的解决方案!我至少有10个框架,必须将某个配置添加到每个框架中,感觉非常丑陋。
替代(可怕的!)解决方案
是的,当然还有另一种解决方案,那就是使用Release
配置进行分析,并在Main.xcconfig
中声明DEBUG
标志,如下所示:
OTHER_SWIFT_FLAGS[config=Release] = -D DEBUG
GCC_PREPROCESSOR_DEFINITIONS[config=Release] = DEBUG
但是由于我们想要在框架中检查 DEBUG
标志,我们需要将上述两行声明标志的代码添加到 Frameworks.xcconfig
中。
当然,我们需要将 构建配置 设为 Release
用于性能分析的方案。
然后,我们可以在主项目中添加一个名为 AppStore
的新的 配置,并仅在主项目中使用该配置来归档应用程序。到目前为止还好吗?
这是个陷阱!
不,这不是一个好主意!因为我刚才说过,项目和父项目之间不会继承配置。因此,我们的框架将不会继承这个新的AppStore
配置,所以当框架被构建/归档时,我看到它们会“回退”到Release
配置(不确定是否可以在某个地方选择“默认”/“回退”配置?也许它会回退到您用作新配置基础的那个配置?)。但是,由于我们刚刚为主项目和所有框架添加了
Release
配置的DEBUG
标志声明,并且在归档应用程序时使用的是Release
配置,而所有框架都使用Release
配置,因此我们的生产应用程序将包含调试代码!这是非常不希望的,潜在风险很大。
好的解决方案?
我不知道...你知道吗?如果配置可以从父项目继承,那不是很好吗?苹果...拜托了。
$(inherited)
从父级继承配置。你试过了吗? - clemensGCC_PREPROCESSOR_DEFINITIONS = $(inherited) DEBUG
。我没有直接使用目标设置。我使用的是xcconfig
文件,因此这将转换为GCC_PREPROCESSOR_DEFINITIONS[Profiling] = $(inherited) DEBUG
。问题在于我们的框架中没有可用的 配置Profiling
。这是一个进退两难的局面。我追求的是配置的继承!而不是某个目标构建设置(如GCC_PREPROCESSOR_DEFINITIONS
)的继承。 - Sajjon.xcconfig
文件中,如果针对所述目标(项目)不存在MY_CONFIGURATION
,则无法使用<SOME_SETTING>[config=<MY_CONFIGURATION>] = <SOME_VALUE>
或等效的Target Settings
行中的<SOME_SETTING>= <SOME_VALUE>
。对于Target Settings
情况(即不使用.xcconfig
文件时),这是自我解释的,因为没有MY_CONFIGURATION
行!而在.xcconfig
文件中,[config=<MY_CONFIGURATION>]会失败,因为它不存在。再次强调,如何确保从父项目继承MY_CONFIGURATION
? - Sajjon