I have updated my Xcode to version 5.1 recently. After update, it runs fine with all simulators except iOS 7.1, in which it gives a mach-O link error. Moreover, there is only a 64-bit architecture option in 'Build setting' tab. According to me, it is the cause of all the problems & errors. Does anybody know reason for this & how to solve it?
Here are some warnings & errors I've got:
Warning :
Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
Error:
Symbol(s) not found for architecture x86_64
Thanks.
Xcode 5.1 changed the standard project settings. Among others it now includes the arm64 architecture for the project - but a lot of 3rd party projects don't support that yet, so I recommend to remove it from the architectures settings again (leaving you with armv7 and armv7s). Keep it in the valid architectures setting, though - this specifies on which architectures it may run.
It also introduced the default activation of some extra warnings, like the typecast to long warning - same counts here, when you use quite some other libraries (as source code) you might get lots of warnings you can't (or don't want to) do much about. You can disable the warnings again for those projects, or choose not to update your project settings right away.
Got to Build Settings -> Architectures
You probably have Standard Architectures set, right?
As of Xcode 5.1 Standard Architectures includes arm64, which you are not ready to support.
Select Other..
doubleclick $(ARCHS_STANDARD) and change it to $(ARCHS_STANDARD_32_BIT)
Note: This is a temporary fix. You are probably using some static library that didn't come with a 64-bit slice. See if there is one available and then switch Architecture back to Standard Architectures.
Indeed XCode now includes the arm64 architecture.
NSInteger is something completely different now as it is define in NSObjCRuntime.h :
#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
To deal with it you should improve your codebase. First of all, you have to be really consistent. Assign NSInteger only to NSInteger and not to int. Avoid all kind of :
int i = [aString integerValue] ( as it returns a NSInteger)
but
NSInteger i = [aString integerValue] (and if it's a long type then you won't have any trouble.)
Moreover, another issue you might have is when you want to create a string from a value.
What you could do is something like:
#define cL(v) (long)(v)
#define cUL(v) (unsigned long)(v)
NSLog(#"array.count: %ld", cUL(anArray.count));
array.count returns an unsigned int under armv7(s) and an unsigned long under arm64. By always casting into an unsigned long you will not face any warning anymore and, more important, do not get any bug.
This "logic" have been introduced by Apple itself on some tech-talks videos there:
https://developer.apple.com/tech-talks/videos/ (video "Architecting Modern iOS Games". Play the video around 10m00s)
Related
For quite a while I've been using linker sections for registering elements that are used at runtime. I find that it's a simple way to make generic and extensible interface. A particularly useful use-case is something like unit tests or a multitool (e.g. busybox) so one can do something like:
$ ./tool <handler>
Where handler is a simple string that is "looked up" at runtime by walking the linker section. In this way, your parser doesn't have to "know" what commands are supported. It just finds their handlers in the linker section dedicated for them or it doesn't.
With GCC I've been doing something like (you can do this with Clang as well):
#define __tool __attribute__((__section__("tools")))
Then each handler I want to register gets a simple structure (with more or less information as needed)
struct tool {
const char *name;
const char *help;
int (*handler)(int argc, char **argv);
}
Then, for each tool you just do something like (often conveniently wrapped in a macro):
int example_tool0(int argc, char **argv)
{
return -1;
}
static const struct tool example_tool0 = {
.name = "exmaple_tool0",
.help = "usage: ...",
.handler = example_tool0
};
__tool static const struct tool *ptr = &example_tool0;
And used a such:
$ ./tool example_tool0
And because of __tool, each pointer registered in this way is packed into a linker section that can be walked.
Now, on GCC the linker creates two magic variables for each section: __start_SECTION and __stop_SECTION. So, to "walk" all of our registered handlers you just take the size of this section, divide by the size of a pointer, and then strncmp against the name (in this example) in the struct.
All of the above just to say, how can this be done using the OSX/iOS Clang-based toolchain? I would rather not use a custom linker script to achieve this seemingly simple operation.
Is there a way do this on OSX? I have worked around the issue by registering an empty entry at the beginning of the section and at the end. But doing so requires forcing the link order of the object files.
While OSX/iOS uses Clang as their platform compiler, they do not use the LLVM linker. Rather, they implement their own ld64 (which is open source) for whatever reason. So, it may just not be supported. I didn't readily see anything in man ld on OSX, but it's a bit info-dense.
For reference with ELF and GCC
And so this has been answered by others already. I did search, but I must have missed this answer. I've actually looked for an answer to this question many times before but must've never used the right words.
https://stackoverflow.com/a/22366882/2446071
In summary, apparently the linker supports syntax to define these desired symbols yourself:
extern char __start_SECTION __asm("section$start$SEGMENT$SECTION");
extern char __stop_SECTION __asm("section$end$SEGMENT$SECTION");
I have this code from a library I am using.
#ifdef __IPHONE_8_0
if (&SKStoreProductParameterAffiliateToken) {
if (self.affiliateToken) {
[appParameters setObject:self.affiliateToken forKey:SKStoreProductParameterAffiliateToken];
if (self.campaignToken) {
[appParameters setObject:self.campaignToken forKey:SKStoreProductParameterCampaignToken];
}
}
}
#endif
Xcode is saying that the first line will always evaluate to be true but what is this line doing exactly? I never saw a if with & and a constant in that way.
SKStoreProductParameterAffiliateToken is defined as
SK_EXTERN NSString * const SKStoreProductParameterAffiliateToken NS_AVAILABLE_IOS(8_0);
What is the developer trying to check, the address of a constant? Is he trying to check if the version of iOS has this constant defined and by doing that, he is trying to check the instruction inside the if should run? But he already has ifdef __IPHONE_8_0... (??!!)
I don't get it.
Anyway I am compiling for iOS 9.3, so I can delete the if and the ifdef, right?
It is a check to see if a weak-linked symbol is available. If the library/framework containing the symbol has been weakly linked and is not available its address will evaluate to NULL and the if condition will be false.
See Using Weakly Linked Methods, Functions, and Symbols in Apple's Using SDK-Based Development for full details.
#ifdef __IPHONE_8_0 checks if Xcode should compile code inside. Ohterwise older version of Xcode will show an error about unknown variable SKStoreProductParameterAffiliateToken.
But when using newer Xcode version (with iOS SDK 8+), we may still can set a lower minimum target for our project. In this case to avoid crash on devices with lower than iOS 8 version we should check first if variable, class, method or function exists.
In your case, we are checking if pointer to SKStoreProductParameterAffiliateToken is not NULL, which means app is currently running at least on iOS 8.
I've opened an old game project in Xcode 6.1.1 (made with Xcode 5.x) started it in the simulator with the iPad Air simulator and discovered after compiling it lots of strange warnings in the SoundOAL.m in many lines of this file. They mostly say something like this:
"Incompatible pointer types passing 'NSUInteger *' (aka 'unsigned long *') to parameter of type 'ALuint *' (aka 'unsigned int *')"
I think I know what it means (ps: app works without problems), but I was wondering if anything has changed and needs to be changed by me. I tried to find something in the iOS 8 docs but I could not read anything. Maybe someone knows it better?
They're warnings due to their now being 64 bit support. You can ignore them, but if you see any unexpected results you should look there.
Since iOS devices support 64-bit, NSUInteger is 64-bit. Your code is passing a pointer to an NSUInteger to a method that takes an ALuint, which is defined in al.h as being 32-bit:
/** unsigned 32-bit integer */
typedef unsigned int ALuint;
To remove the compiler warnings, change your NSUInteger variable types to ALuint or cast them where appropriate, eg:
alSourceStop((ALuint)sourceID);
I just upgraded Xcode + iOS SDK to the latest versions (5.1/7.1) and am now getting a bunch of errors about implicit conversions losing precision (NSInteger to int etc).
Does anybody know if there is a compiler flag or something that allows me to tell the compiler to treat those as warnings rather than errors again? I couldn't find anything so far. I really don't want to go through the code and add explicit casts everywhere as this would be in a lot of places.
This is an error for good reason. NSInteger throughout your codebase will make sure that when you compile the code for 32 and 64 bit iOS devices they are handled consistently. In the 32 bit world NSInteger and int were the same, but with the advent of the iPhone 5S and the iPad Air, iOS is no longer 32 bit only.
As others have said, there really is no way around this if you don't want trouble with modern devices.
If you just want to get back to work and deal with this problem later, then you need to remove arm64 from the 'Valid Architectures' and 'Architectures' items in your project's Build Settings.
As others have said, you really should fix the warnings, but this was a nasty little surprise by Apple (that is, adding the arm64 architecture to Build Settings on Xcode 5.1) so I can totally understand wanting to put these warnings away for a while and work on what ever you were working on before you decided to upgrade.
Indeed XCode now includes the arm64 architecture.
NSInteger is something completely different now as it is define in NSObjCRuntime.h :
#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
To deal with it you should improve your codebase. First of all, you have to be really consistent. Assign NSInteger only to NSInteger and not to int. Avoid all kind of :
int i = [aString integerValue] ( as it returns a NSInteger)
but
NSInteger i = [aString integerValue] (and if it's a long type then you won't have any trouble.)
Moreover, another issue you might have is when you want to create a string from a value.
What you could do is something like:
#define cL(v) (long)(v)
#define cUL(v) (unsigned long)(v)
NSLog(#"array.count: %ld", cUL(anArray.count));
array.count returns an unsigned int under armv7(s) and an unsigned long under arm64. By always casting into an unsigned long you will not face any warning anymore and, more important, do not get any bug.
This "logic" have been introduced by Apple itself on some tech-talks videos there:
https://developer.apple.com/tech-talks/videos/ (video "Architecting Modern iOS Games". Play the video around 10m00s)
You should go and cast them the way they ought to be. Apple isn't complaining for no reason - it also ensures that you don't get any weird unexpected behaviour later down the line. I suggest you go and cast them all. It's extreme but well, it's clean.
I am using zxing and OpenCV lib in my project. I updated my XCode from 4.5 to 4.6 today and I am getting this error.
externalLibs/boost/include/boost/gil/channel_algorithm.hpp:54:85: Non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned long long'
And this error is on this line of code in one of the class of OpenCV Library:-
struct unsigned_integral_max_value : public mpl::
integral_c< UnsignedIntegralChannel,-1> {};
On Earlier version of Xcode its working fine.
Thanks in advance.
It seems boost doesn't like c++ 11 support added with the new clang compiler
so.. it say disable c++ 11 support in build settings
= src: see https://svn.boost.org/trac/boost/ticket/7270
The max value of an unsigned long long variable is in hex 0xFFFFFFFF FFFFFFFF, i.e. all bits are 1's. If interpreted as a signed number, this corresponds to a -1. So often programmers use -1 instead, hoping that the compiler will not complain. Apparently, this did not happen in XCode 4.5, but 4.6 does more rigorous checking...
I'm running into the same error when compiling on macOS Sierra with Apple LLVM version 8.1.0 (clang-802.0.42) and -std=c++11. To solve the problem I included the following compiler flag: -Wno-error=c++11-narrowing