在ONLY_ACTIVE_ARCH = NO的本地计算机上编译时编译警告未遇到

Oli*_*ain 5 xcode ios

我有一个小问题,我不知道如何解决.

在我们的多个项目中,我们希望将"将警告视为错误"(GCC_TREAT_WARNINGS_AS_ERRORS)更改为YES.

我们还想将Xcode默认项目设置"Build Active Architecture Only"(ONLY_ACTIVE_ARCH)YES保留给Debug和NORelease.

然而,这有一个主要的缺点.代码如......

NSUInteger bob = 12234;
NSLog(@"bob %lu", bob);
Run Code Online (Sandbox Code Playgroud)

应该产生以下类型的警告(因此我们的错误):

"NSUInteger"类型的值不应用作格式参数; 添加显式强制转换为'unsigned long'

但是,当开发人员在本地构建和测试时,他们不会遇到此警告/错误,但是当他们提交到我们的存储库并且我们xcodebuild从命令行继续运行时,会遇到警告并且他们的构建失败.这显然是相当令人沮丧的.

我认为这与使用Xcode时和使用xcodebuild命令行时构建的架构之间的区别有关.

我在这里上传了一个示例项目......

https://github.com/OliverPearmain/ArchitectureDependantCompileWarning

我已经包含了2个方案.如果您使用"ArchitectureDependantCompileWarning"(使用Debug构建配置,因此ONLY_ACTIVE_ARCH==YES)编译iPhone 6S模拟器,您将得不到任何警告,并且编译正常.如果您使用"ArchitectureDependantCompileWarning-FAILS"方案(使用Release构建配置,那么ONLY_ACTIVE_ARCH==NO),则会遇到警告并且编译失败.

我想以某种方式确保在为模拟器构建时始终遇到此警告ONLY_ACTIVE_ARCH==NO.这可能吗?

Jef*_*ski 1

其原因是 5 出现时字长发生了变化。换句话说,5s 及更高版本的 iPhone 配备 64 位处理器,而之前的所有 iPhone 均配备 32 位处理器。

这是实际的 typedefNSUInteger

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
Run Code Online (Sandbox Code Playgroud)

您可以看到,对于 32 位处理器,NSUInteger明确定义为 a unsigned int,而对于 64 位处理器,NSUInteger明确定义为unsigned long

所以,看看这段代码......

NSUInteger bob = 12234;
NSLog(@"bob %lu", bob);
Run Code Online (Sandbox Code Playgroud)

对于 4s,这NSLog不匹配,因为NSUInteger显式定义为 aunsigned int并且格式说明符%lu为 a unsigned long。这种非常明显的不匹配是 32 位处理器存在警告的原因。对于 64 位处理器,不存在不匹配,因此不会出现警告。

警告中建议的修复假设您打算使用unsigned long. 然而,这里有一个替代解决方案。

NSUInteger bob = 12234;
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
NSLog(@"bob %lu", bob);
#else
NSLog(@"bob %u", bob);
#endif
Run Code Online (Sandbox Code Playgroud)

最重要的是,您想要做的是在没有不匹配的情况下产生不匹配警告,这是不合适也不可能的。

编辑:

这不是不匹配错误未能表现为警告/错误的情况。从字面上看,不存在不匹配。出现此错误的唯一方法是实际上存在不匹配。如果您正在构建的架构的定义会NSUInteger在您提到的特定代码中造成不匹配,则只会出现不匹配。已经有一个标准方法可以实现这一点:将所有方案的“仅构建活动架构”设置为“否”