ios - XCode 构建系统:弄乱预处理器定义和包含的头文件?
问题描述
这里的第一个问题。
我在使用 XCode 构建系统时遇到了一些问题,特别是在预处理器定义方面。
我正在尝试为 Objective-C 运行时定义一个宏,以避免强制将调度函数强制转换为适当的函数指针类型。通常的方法是使用#define OBJC_OLD_DISPATCH_PROTOTYPES
然后在下一行包含标题。一旦包含了标头,就已经定义了宏并且相应地配置了标头。
但这就是它开始变得奇怪的地方!
该宏根本无法识别,并且标头被包含,就好像该#define
语句不存在一样,因此它失败#define OBJC_OLD_DISPATCH_PROTOTYPES
并且它被(重新?)定义为 0。
主程序
#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 - Preprocessing”部分下的项目构建设置中定义预处理器宏时,构建系统会按预期运行。-D
它使用参数定义全局宏,clang
使其可用于项目使用的任何文件。
但是,当我从终端使用 clang 时,源代码可以正确编译clang main.c
。
有人可以告诉我需要为构建系统配置什么才能正常运行吗?
解决方案
使用 Xcode IDE 构建时会发出警告:
Ambiguous expansion of macro 'OBJC_OLD_DISPATCH_PROTOTYPES'
并且输出确实是 0 直接使用 Xcode,但 1 和clang main.c
. 不同之处在于 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。
推荐阅读
- powershell - powershell:替换TXT文件中某个位置的字符
- powershell - Powershell 新手:如何使用嵌套的 foreach 或数组(或任何其他解决方案)将 2 个或更多变量放入同一个文件中?
- r - 滚动时如何保持titlePanel(或shinyWidgets::panel)固定?
- cygwin - Windows server 2016 上的 Cygwin 安装问题 - 退出 256
- php - 填充表单字段 php wordpress
- python - Python 中的 PayPal 自适应付款转换货币请求(已弃用的 API)
- mysql - Symfony 4.3 两个实体之间的唯一实体不起作用
- regex - 为什么使用 find 时这个正则表达式在 shell 上不起作用
- reactjs - 从 React 中导入的文件调用函数时出错
- google-cloud-platform - 如何限制 G Suite 中的服务帐户访问权限?