Compile program for older versions of Mac - objective-c

I have an objective c script that takes a Mac's system information and outputs it as an XML with specific tags. It works on Mountain Lion and Lion, but doesn't work with any versions besides those. Up to 10.5 would be ideal. When I run it on 10.6.8, I get a Bad CPU error. Any suggestions?

Xcode 4.5.1 comes with OS X 10.7 and 10.8 SDKs. To compile programs that run on earlier OS X versions, you have to set the "OS X Deployment Target" in the Info tab of the program settings.
"Automatic Reference Counting" is only supported on OS X 10.6 and later (see Objective-C Feature Availability Index). If you want to deploy to 10.5, you have to compile without ARC. So either
you create a new project and uncheck the "Use Automatic Reference Counting", or
you set "Objective-C Automatic Reference Counting" to "No" in the Build Settings.
To build executables that run on 32-bit processors, you have to set "Architectures" to "32-bit Intel" in the Build settings. By default, Xcode 4.5.1 will compile for the architecture of the compile machine (which most probably is 64-bit). But in this case you can not use ARC, because ARC requires the so-called "modern runtime", which is available only on 64-bit systems.

Related

Will Mac application developed in latest XCode work in old OS-X?

I have MacOS-X - 10.7 and Xcode - 4.6.2 and made a Mac application. The client side machine is also MacOS-X - 10.7. But in my mac application there was a small error with NSNumberFormatter which when I was changing, Xcode was crashing. So I edited the code in latest Xcode and OSX. And then I made the binary of it and run in MacOS-x - 10.7, its working fine. But the source code is no more opening in Xcode - 4.6.2. Its asking for the latest version of Xcode. My question is will the binary will work fine in older version of OS-X even if it is developed in latest Xcode?
The version of OS X which your application will run on is dictated by the OS X Deployment Target in the project settings. If that is set to support 10.7, then it doesn't matter which version of OS X you built it on: the built application will work on 10.7 and later.
This setting will also set the minimum allowed OS in the Info.plist, so people trying to run the build on earlier OSes will see an alert instead of the app just crashing.
More information on setting the deployment target and building for different OS versions with SDKs is available in the Apple documentation:
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html

Miscellaneous confusion about Xcode build settings (64/32 bits, SDK version, etc)

When I create a new OS X application project, I noticed many target options those confuse me quite a lot:
(1) The top-left setting of Xcode window:
(2) The "Base SDK":
(3) "Deployment Target":
(4) Architectures:
Here comes my questions:
For (2) and (3), I think it was clearer to understand. These are what I comprehend:
(2) This identifies what I develop with.
(3) This identifies what OS version my application will be used on.
Please tell me whether I am right...
But I could not understand (1). I just know that if I select 32-bit here, I could not use ARC.
Neither with (4), what are they? Are they represent the bit-width of the CPU? What was the difference between (1) and (4)?
I'll explain your items out of order.
The Base SDK
This defines the largest set of APIs you can use. You can use anything that existed as of the version number identified here. For example, if you use the 10.8 SDK, you can use -[NSColor CGColor] (introduced in 10.8), but not -[NSData base64EncodedDataWithOptions:] (first public in 10.9).
(Of course, you can also use anything older than that version.)
Accordingly, the SDK version is also known as the “max[imum] allowed” version in the Availability macros.
The SDK version also sometimes becomes important when Apple changes the behavior of an API. When they do that, they sometimes keep the old behavior around for applications linked with older SDKs. This is called an “on-or-after check”, as in “checks whether you're on 10.8 [SDK] or later”. (The concept and term pre-date Xcode having SDKs for each OS version. It used to just go by whatever OS you were running Xcode and building on.)
The Deployment Target
This is the minimum OS version you require. If something was removed in a prior version (rare, but it happens), you can't use it.
This tends to affect link-time and run-time things more than compile-time things. For example, ARC won't work if your deployment target is 10.5 or earlier.
Accordingly, the Deployment Target is also known as the “min[imum] required” version in the Availability macros.
The Info.plist can also specify a minimum OS version. Nowadays, this is set by default and it's set by macro expansion to the Deployment Target.
The Architectures build setting
Different CPUs have different architectures. Essentially, they fit into broad categories, such as:
PowerPC 32-bit (ppc)
PowerPC 64-bit (ppc64)
Intel 32-bit (i386)
Intel 64-bit (x86_64)
ARM 32-bit
ARM 64-bit
(PowerPC architectures aren't supported anymore. You can add them to the Architectures list, as ppc and ppc64, but Xcode will just ignore them.)
Macs nowadays have Intel processors. Almost all Intel Macs have 64-bit processors. You only need to worry about 32-bit Intel if you want to support Macs all the way back to 2006. That's probably more hassle than it's worth.
iOS devices run ARM processors, and most are still 32-bit. The A7 (iPhone 5S, iPad Air, iPad Mini with Retina Display) is 64-bit. But, if you run on an iOS Simulator, it's running on your Mac (it's a Simulator, not an emulator), so it'll target an Intel architecture (formerly always i386, but probably can now be x86_64 if needed).
The “top-left setting of Xcode window”
This is the build scheme and run destination. (Yes, it's two separate things in one pop-up menu. Actually, it's two separate pop-up menus in one control. Try it.)
“My Mac 64-bit” is the run destination. You'll be running the 64-bit version of your app on your Mac, not in an iOS Simulator or on an iOS device. Your choice for a Mac app is merely which architecture you want to run, and they should behave the same (this is, obviously, something you sometimes need to test).
iOS apps have more choices here. Some apps are iPhone-only, some are iPad-only, some are universal, and some may be set to build for both 32-bit and 64-bit architectures. You'll have a Simulator offered for each combination of form factor and architecture (e.g., iPhone Simulator 64-bit) you can run on. You'll also have the option to run your app on any iOS device that's connected and enabled for development (you get this prompt when you plug in the device in Xcode's sight).
TL;DR
Deployment Target is the lowest OS version your app will run on.
Base SDK is the highest OS version you can use stuff from. If it didn't exist yet, it doesn't exist at all for you.
Architectures are the set of hardware your app will run on.
Run Destination is the hardware you're going to run it on from within Xcode.
Just like with most OSes these days you can develop either a 32bit or a 64bit application. The "bitness" refers mostly to how memory addresses are structured (either using 32bit allowing so at most 4GB to address or 64bit (computation left as an exercise to the reader)). However the choosen architecture usually has more implications (like the missing ARC support for 32bit apps) but also how wide CPU registers are, how much memory a structure uses in RAM etc.
OS X also supports socalled fat binaryies that is, a bundle containing both 32bit and 64bit variants of your application. This is however only needed if you normally prefer to run 64bit code, but want your app also to run on OS versions that only support 32bit.
In XCode you can define for what architecture to build your project, either 32bit only, 64bit only or a fat bundle. In the project settings you can set what is allowed and in the top bar in XCode you can quickly switch between the allowed architectures (your questions 1 and 4).
The base SDK determines what you want to use to compile your application. If you select for instance 10.7 you cannot use new APIs that were introduced in 10.8 or 10.9 (which might perfectly be ok if you want your application to run on earlier OS versions only). However if you want to dynamically use new features if they are availble you'd select the latest OS as base SDK and check in code what OS you are running on and only use new features if they are available. It is totally ok to compile an application with access to new features and run it on older systems if you don't use the new APIs there (they are late-bound and hence only crash when you access them the first time and they are not available).
The deployment target determines the minimum OS version your application needs to run properly. This is a runtime check done when the application is started. The OS will refuse to start an application that is made for a later version.

iMac - missing x86 version of GameKit

If I run this command:
file /System/Library/Frameworks/GameKit.framework/GameKit
I get:
/System/Library/Frameworks/GameKit.framework/GameKit: Mach-O 64-bit
dynamically linked shared library x86_64
Which equates to my iMac (a brand new one) is missing the x86 version of GameKit. So my x86 Mac application (it is a C# Xamarin.Mac app) crashes when referencing GameKit.
Does anyone know if this is going to be an ongoing issue for future Macs? Or is it an Apple bug that this is missing on my machine?
Everything points to Apple deprecating 32-bit (architecture i386) code at some point. This is because they took advantage of switch from 32-bit to 64-bit code to add features to the Objective-C runtime, making 64-bit runtime more featureful.
I have no confirmation for this, but judging from how PowerPC transition was handled, and how 64-bit code deprecates loads of ancient technologies, this is probably not far off.
Although I do have 32-bit GameKit on my machine, it would not surprise me at all if a future release of OS X might contain no 32-bit code. And since all Macs that contain GameKit must be able to run 64-bit code (a requirement for Mountain Lion), the best advice I can give is to add a 64-bit version of the app. I have no idea if MonoMac supports 64-bit code, but that's the direction you should go to.
I suspect an OS update (such as the upcoming 10.8.3) might install a version of GameKit that happens to contain 32-bit code. Or it might remove 32-bit code for the rest of us. But I would absolutely not count on Apple maintaining or adding new features to 32-bit code, precisely because many features that they like (such as ARC or synthesizing ivars) can't be supported by the so-called 32-bit Objective-C runtime without breaking binary compatibility.

Create Universal Automator Action

I'm trying to create a universal Automator action for Mac OS X 10.5 & above. Under architectures I have set "i386 ppc" and when compiled, Finder sees the binary as "Universal". Automator however says that the action is not universal and won't run it. (when hitting "Build & Go" in Xcode it works)
Am I missing something here?
If your Mac is an Intel Mac, check if Automator is running as 64 bit process (Activity Monitor can tell you that). If it is, it may not be able to load a binary that contains 32 bit only. In that case your binary must have been compiled for three architectures, i386, ppc and x86_64. Note, however, that in SDK 10.5, Cocoa was not available for x86_64, so you will have to use SDK 10.6 for the x86_64 variant, while keeping SDK 10.5 for the i386 and ppc variants. That is easily possible, though, you can create a custom build setting, named SDKROOT_x86_64, which will override the default SDK setting (named SDKROOT), but only when building for the architecture x86_64. The value should be the absolute path to the SDK (I'm not sure if the shortcuts Apple usually uses for this setting will also work for a custom override).

Cocoa/Xcode - OSX retrocompatibility

I wrote a Cocoa app on my Mac which is 10.6.6. I sent it to a friend who has 10.5.7 and they got this error:
Cannot open this app with this version of OSX
How can I make my app retrocompatible with minimum 10.4 Tiger ?
Set the Mac OS X Deployment Target in your Target build settings to OS X 10.4. And make sure to not use any 10.5 or 10.6-only APIs without checking for their availability first.
For 10.5 you can set the deployment target to 10.5 and make sure you only use APIs available in 10.5 (you should get warnings for 10.6 only APIs).
For 10.4, you'll probably need to install the 10.4 SDK from the Xcode install and use that SDK. If you have any properties declared, you'll also have to change them to getter/setter pairs and manually implement the getter/setters for synthesized properties.
If at all possible, you should avoid having to support 10.4 because the runtime predates Objective-C 2.0.