使用ONLY_ACTIVE_ARCH = NO

时间:2016-03-03 12:38:39

标签: ios xcode

我有一个小问题,我不确定如何解决。

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

我们还希望将Xcode默认项目设置“仅构建活动架构”(ONLY_ACTIVE_ARCH)保留为YES以进行调试,将NO保留为版本。

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

NSUInteger bob = 12234;
NSLog(@"bob %lu", bob);

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

  

“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构建模拟器时始终遇到此警告。这可能吗?

1 个答案:

答案 0 :(得分:1)

原因是5s出现时字长的变化。换句话说,5s和更高版本的iPhone有64位处理器,而所有以前的iPhone都有32位处理器。

以下是NSUInteger

的实际typedef
#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

您可以看到,对于32位处理器,NSUInteger显式定义为unsigned int,而对于64位处理器,NSUInteger明确保护为{{1} }}。

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

unsigned long

对于4s,此NSUInteger bob = 12234; NSLog(@"bob %lu", bob); 不匹配,因为NSLog被明确定义为NSUInteger,格式说明符unsigned int%lu。这种非常明显的不匹配是32位处理器存在警告的原因。对于64位处理器,没有不匹配,因此没有警告。

警告中的建议修补程序假设您打算使用unsigned long。但是,这是另一种解决方案。

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 的定义会在您提到的特定代码中产生不匹配的体系结构,那么只会出现不匹配的情况。已经有一种标准的方法可以实现这一目标:为所有方案设置“仅构建活动架构”为“”。