问题描述
第一个问题。
我在XCode Build System方面遇到了一些麻烦,特别是在预处理器定义方面。
我正在尝试为Objective-C运行时定义一个宏,以避免强制将分派函数强制转换为适当的函数指针类型。通常的做法是使用#define OBJC_OLD_disPATCH_PROTOTYPES
,然后在下一行包含标题。一旦包含标头,就已经定义了宏,并相应地配置了标头。
但这就是开始变得怪异的地方了!
根本无法识别宏,并且好像没有#define
语句一样包含了标头,因此它无法#define OBJC_OLD_disPATCH_PROTOTYPES
并且被(重新定义)为0。
main.c
#include <stdio.h>
#define OBJC_OLD_disPATCH_PROTOTYPES 1
#include <objc/objc-runtime.h>
int main(int argc,const char * argv[]) {
// From there:
// - Build System: OBJC_OLD_disPATCH_PROTOTYPES is always 0,except if defined in build settings
// - Clang (only): OBJC_OLD_disPATCH_PROTOTYPES is 1
printf("%d\n",OBJC_OLD_disPATCH_PROTOTYPES);
}
在项目构建设置的“ Apple Clang-预处理”部分下定义预处理器宏时,构建系统将按预期方式运行。它使用-D
的{{1}}参数定义全局宏,从而使该宏可用于项目使用的任何文件。
但是,当我在使用clang
的终端上使用clang时,源代码可以正确编译。
有人可以告诉我我需要配置什么才能使构建系统正常运行吗?
解决方法
使用Xcode IDE进行构建时会发出警告:
Ambiguous expansion of macro 'OBJC_OLD_DISPATCH_PROTOTYPES'
,直接使用Xcode的输出确实为0,而使用clang main.c
的输出为1。区别在于Xcode默认情况下对启用了模块的模块使用clang:如果在此处启用模块,则会在命令行上收到相同的警告:
clang -fmodules main.c
解决方案
在Xcode中,选择目标,转到“构建设置”选项卡,然后在“ Apple Clang-语言-模块”部分中,将“启用模块(C和Objective-C)”条目切换为“否”:
然后,无论在命令行上使用Xcode还是Clang,在两种情况下您都可以得到预期的结果。
说明:
如果您使用模块,则会发生以下情况:
- 代替模块的预处理器和文本,而是使用模块的二进制表示形式
- 模块是(独立地)预编译的,也就是说,它们使用模块预编译后的定义
- 因此,include / import语句之前的代码中的预处理定义对模块没有影响(对其他导入的模块也不起作用)。
- 如果启用了模块,不仅会影响@imports,而且还会将#includes转换为在后台导入的模块
因此,您对OBJC_OLD_DISPATCH_PROTOTYPES有一个矛盾的定义。 预编译模块对OBJC_OLD_DISPATCH_PROTOTYPES使用0,然后将其重新定义为1。
顺便说一句:如果您使用
#define OBJC_OLD_DISPATCH_PROTOTYPES 0
然后,您使用与预编译模块相同的定义,因此即使启用了模块,也没有关于宏的模棱两可扩展的警告。
在没有启用模块的情况下,预处理器会包含文本,编译结果并返回预期结果,即在objc.h中使用所需的typedef。