BigZaphod / Chameleon

Chameleon is a port of Apple's UIKit for iOS (and some minimal related frameworks) to Mac OS X.
http://chameleonproject.org/
BSD 3-Clause "New" or "Revised" License
3.44k stars 568 forks source link

UIKit does not build in release mode in Xcode4 #39

Closed jamiepinkham closed 12 years ago

jamiepinkham commented 13 years ago

Haven't tried with Xcode3, but building with "release" in Xcode causes many un-resolvable issues.

jamiepinkham commented 13 years ago

actually, chameleon doesn't build for 32-bit at all.

BigZaphod commented 13 years ago

Are you targeting something earlier than 10.6? Chameleon is 10.6+. I just built it in 32 bit with no problem. We also routinely build in Release mode when we ship Twitterrific for the Mac. I think something else might be wrong?

jamiepinkham commented 13 years ago

when i build for 32 bit mode i get a ton of "incompatible type for argument 1 of initWithFrame:" for classes like UIWindow, UIImageView, etc.. very strange.

jamiepinkham commented 13 years ago

the same issue occurs in your sample projects included with the repo

jamiepinkham commented 13 years ago

Ok. I've figured it out.

The reason a 32-bit build doesn't work, but a 64-bit build does is that in 64-bit, NSRect is defined to CGRect, so it works. But in 32-bit it all falls apart.

Since, in 32-bit, NSRect != CGRect and initWithFrame returns an id, the compiler is forced to find a matching signature from your available imports. Since AppKit is include, NSView's initWithFrame is resolved. Which takes an NSRect.

The solution is to add a -(id)initWithCGRect:(CGRect) to UIView, and call that instead of UIView's initWithFrame, the implementation is simply just calling initWithRect.

I'll fork and do a pull request with the fix.

BigZaphod commented 13 years ago

It sounds like something is different when you target for 32 bit, and the error about initWithFrame: tells me that probably AppKit headers are being included (maybe in a precompiled header like your .pch or something?) when they shouldn't be. Care needs to be taken when and where AppKit headers are included because of the naming conflicts with some selectors such as initWithFrame: which takes an NSRect for AppKit, but a CGRect for Chameleon/UIKit.

That said, I don't see it happening for me when I change the UIKit project's target from 64 to 32, so I don't know why it'd be different for you unless the project files have been modified or there's some kind of local configuration either avoiding the problem on my end or causing it on yours. I do know that many people have been building and using Chameleon and this is the first I've heard of this problem (but of course others may just not have noticed it).

jamiepinkham commented 13 years ago

Well, it happens in your samples that you include in the repo, so I think it might be more common than you think.

lvandal commented 12 years ago

I have the same issues when trying to archive in either 32 or 64 bits.

UIImageView *background = [[UIImageView alloc] initWithFrame:[self frame]];

Sending 'CGRect' (aka 'struct CGRect') to parameter of incompatible type 'NSRect' (aka 'struct _NSRect')

lvandal commented 12 years ago

Moreover, the MultiApple sample will fail to compile when archiving because of the same issue:

self.view = [[[UIView alloc] initWithFrame:CGRectMake(0,0,320,460)] autorelease];

Incompatible type for argument 1 of 'initWithFrame:'

joshaber commented 12 years ago

fwiw, you can get around these errors by casting the result of +alloc:

self.view = [[(UIView *)[UIView alloc] initWithFrame:CGRectMake(0,0,320,460)] autorelease];
lvandal commented 12 years ago

I've fixed the issue by replacing:

import <Cocoa/Cocoa.h>

with:

import <Foundation/Foundation.h>

in the .pch file.

seqoy commented 12 years ago

Here are some answers: Before Leopard, NSRect and CGRect were completely different types. Apple took the opportunity provided by the transition to 64-bit to eliminate the discrepancy. But this change could break binary compatibility, so it couldn't be done across the board for 32-bit code.

NSRect is the same type as CGRect if building for iOS, for a 64-bit Mac architecture, or a 32-bit Mac architecture with the macro NS_BUILD_32_LIKE_64 defined as 1 at the command line or in a prefix header.

If you check the file NSGeometry.h you will see the conditional #if LP64 || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64.

Ok, pretty good pal, but enough of this bullshit. How do we solve the problem???

We can set our target to 64 bit, or if you prefer set the target as 32 bit and define the NS_BUILD_32_LIKE_64 as 1 in our XCode Project.

If you like the second option, edit your .pch file (find by .pch on XCode) and include this line:

#define NS_BUILD_32_LIKE_64 1