A compilation warning was not detected when compiling on the local computer with ONLY_ACTIVE_ARCH = NO

I have a small problem that I'm not sure how to solve it.

In our several projects, we would like to change the "Process warnings as errors" ( GCC_TREAT_WARNINGS_AS_ERRORS ) to YES .

We would also like to leave the default project setting for Xcode "Build Active Architecture Only" ( ONLY_ACTIVE_ARCH ) to YES for Debug and NO for release.

However, this has one major drawback. Code, for example ...

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

It should produce the following type of warning (and, therefore, an error in our case):

Values โ€‹โ€‹of type "NSUInteger" should not be used as format arguments; add an explicit cast to "unsigned long" instead

HOWEVER, when developers build and test locally, they DO NOT meet this warning / error, but when they commit our repository and our continuous integration launches xcodebuild from the command line, the warning occurs and their assembly fails. This is clearly disappointing.

I assume this has something to do with the difference between the architecture that is built using Xcode and when using xcodebuild from the command line.

I downloaded a sample project here ...

https://github.com/OliverPearmain/ArchitectureDependantCompileWarning

I have included 2 circuits. If you compile for the iPhone 6S simulator using "ArchitectureDependantCompileWarning" (which uses the Debug assembly configuration and therefore ONLY_ACTIVE_ARCH==YES ), you will not receive any warnings and will not compile anything. If you use the "ArchitectureDependantCompileWarning-FAILS" scheme (which uses the release assembly configuration and therefore ONLY_ACTIVE_ARCH==NO ), then a warning occurs and compilation fails.

I would like to make sure somehow that this warning ALWAYS occurs when creating for the simulator with ONLY_ACTIVE_ARCH==NO . Is it possible?

+5
source share
1 answer

The reason for this is the change in word length when 5s came out. In other words, 5 or more iPhones have a 64-bit processor, and all previous iPhones have a 32-bit processor.

Here are actually typedefs for NSUInteger

 #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 

You can see that for a 32-bit processor, NSUInteger explicitly defined as unsigned int , while for a 64-bit processor, NSUInteger explicitly protected as unsigned long .

So, looking at this code ...

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

For 4s, this NSLog has a mismatch, since NSUInteger explicitly defined as unsigned int , and the %lu format specifier is unsigned long . This very apparent mismatch is the reason that a warning exists for 32-bit processors. There is no mismatch for a 64-bit processor and therefore no warnings.

The proposed fix in the warning suggests that you intended to use an unsigned long . However, this is an alternative solution.

 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 

The bottom line is that you are trying to warn of a non-compliance when there is no non-compliance, which is neither suitable nor possible.

EDIT:

This is not a case of a mismatch error that does not appear as a warning / error. There is literally no discrepancy. The only way to show this error is actually a mismatch. There will only be a mismatch if you build against architectures for which the NSUInteger definition will create a mismatch in the specific code you specify. There is a standard way to do this: set only "Build Active Architecture Only" to NO for all your circuits .

+1
source

Source: https://habr.com/ru/post/1244355/


All Articles