This chapter describes how cross-development works. For information on how to configure your Xcode projects or makefiles to use cross-development, see “Configuring Your Project for Cross Development.”
To develop software that can be deployed on, and take advantage of features from, different versions of Mac OS X, you specify which version (or SDK) of Mac OS X headers and libraries to build with. You can also specify the earliest Mac OS X system version on which the software will run.
Cross-development depends on the following features of the development environment:
Weak linking, which was introduced in Mac OS X version 10.2 (Jaguar) and supported by the December 2002 Development Tools. Weak linking allows your software to run on versions of Mac OS X whose libraries may not export all the entry points your software requires.
You can find additional information on weak linking inTechnote 2064, “Ensuring Backwards Binary Compatibility—Weak Linking and Availability Macros on Mac OS X”.
Important: See “Limitations” for possible issues with weak linking.
Mac OS SDKs, introduced in Mac OS X version 10.3, which are complete sets of header files and stub libraries as shipped in previous versions of Mac OS X, so you can compile and link against specific headers and libraries.
Cross-Development support, first available in the Xcode Tools distributed with Mac OS X version 10.3. This support allows you to specify the earliest version of Mac OS X your software is intended to run on and the latest version your software uses features from.
When you first install the Developer Tools, you can choose which cross-development SDKs are installed by using the Customize option in the installer. The cross-development SDKs are not installed by default; therefore you must do a custom installation to add them to your system. If you already installed the developer tools on your system, you can reinstall the SDKs from the Xcode Tools CD. Install the CrossDevelopment.mpkg
package or run the general installer and install the Cross-Development components.
When you install the cross-development SDKs, the installer creates a /Developer/SDKs
directory. This directory contains several subdirectories, each of which provides the complete set of header files and stub libraries that shipped for a particular version of Mac OS X. Typically, the latest minor revision of every major revision is represented—for example, 10.2.8 is the latest version of Mac OS X version 10.2. This gives you access to features introduced in System Updates without too much redundancy.
Note: Using SDKs allows you to use new APIs introduced in a System Update. When new functionality is added as part of a System Update, the System Update itself does not typically contain updated header files reflecting the change. The SDKs, however, do contain updated header files.
Each SDK resembles the directory hierarchy of the operating system release it represents: it has usr
, System
, Library
, and Developer
directories at its top level. Each of these directories is in turn populated with directories containing the headers and libraries that would be present in that version of the operating system with Apple Developer Tools installed.
The libraries in an SDK are stub libraries; that is, they do not contain executable code but just the exported symbols for the purpose of linking. This allows SDKs to take up far less disk space and reduces the possibility that an SDK library will be loaded at runtime.
To use cross-development for a target in an Xcode project, you make two selections (described in more detail in “Configuring Your Project for Cross Development”:
In the General pane of the project inspector, you select a target SDK. This is the OS version you want to develop for, such as Mac OS X 10.3.9. This is shown in Figure 2-1.
Your software is built as though you were building in that version of the operating system.
In the Build pane of the inspector window for the target or project, you choose a Mac OS X deployment version, such as 10.2. This is shown in Figure 2-2.
This specifies the earliest Mac OS X system version on which your software will run.
Xcode uses information from these settings during building and linking of your software. Together, these settings define the range of OS versions from which you can use features. You can unconditionally use features from OS versions up to and including the system version that you have specified as your deployment OS. You can use features from system versions later than the deployment OS—up to and including the system version you've selected as your target SDK—but you must check for the availability of the feature, as described in “Check for Undefined Function Calls.”
Figure 1-1 shows the "timeline" for a project targeting the Mac OS X 10.4 (Universal) SDK, with a deployment target set to Mac OS X 10.2.
In this example, the software can freely use any features from Mac OS X versions 10.0 through 10.2. It can also take advantage of features from Mac OS X versions 10.3 and 10.4, but it must first check that the feature is available.
Of course, you should also check to see if you are using deprecated API; while still available, these APIs are not guaranteed to be supported in the future. Using cross-development, the compiler can warn you about the presence of deprecated API.
To use cross-development in a makefile-based project, you add special options to your compiler and linker options to build against the target SDK. For more information, see “Using Cross-Development.”
In Xcode, the SDK settings in the project inspector control the value of a build setting called SDKROOT
. This build setting points to the root directory in which to find headers and libraries to build against. If SDKROOT
is not set, a project is compiled against the headers and linked against the runtime libraries in the current system (/usr/include
, /usr/lib
, and /System/Library/Frameworks
).
In makefile-based projects, the SDK settings are controlled by the options you pass to the compiler and linker.
When you build a target, GCC compiles your source files using the headers and frameworks from the SDK you selected. This means that your source can refer to functions, classes, methods, and constants that are defined for use with that version of the operating system. Functions and methods that exist in that version but not earlier ones are defined as “weak” imports; that is, they will not cause an error at runtime if they are not found in the system libraries.
Your target is linked using “stub libraries” that represent the frameworks and other shared libraries in the system specified in the SDK you selected. Your software will be optimized for that version of Mac OS X (that is, it will be “prebound” to the standard locations of the frameworks in that version).
Note: Prebinding is the process of computing at build time the addresses for the symbols imported by libraries and applications, so that less work needs to be performed by the dynamic linker at runtime. In Mac OS X v10.3.3 and earlier, prebinding can improve the user experience by providing a faster launch. In later versions of Mac OS X, prebinding is not necessary.
You can read more about prebinding in “Prebinding Your Application” in “Launch Time Performance” in the Performance Documentation area.Only system dynamic libraries and frameworks are provided in stub-library form. Static libraries (such as those required by GCC) are provided in the SDK and included in your code as if they have been drawn from the /usr/lib
directory of the operating system being targeted.
When the object code for the target is loaded on a Mac OS X system, the dynamic loader (dyld
) attempts to resolve its imports with the libraries that exist on the running system. If it is loaded on a system earlier than the one defined by the deployment OS version, then it may fail to load (if, for example, it uses function calls not supported in that version of the operating system, or it is loaded in Mac OS 10.1, which does not support weak linking).
However, if the system supports weak linking and the deployment OS was set for that system version or later, then your object code loads, but certain function calls may be undefined. Your code should avoid calling those functions in system versions that do not support them (either by checking the system version globally, or checking each function pointer for a null value before calling it). For an example see “Check for Undefined Function Calls.”
In Xcode, when you select an SDK for a project Xcode sets SDKROOT
to the path of the chosen SDK, and implicitly adds that path to the search paths for frameworks, headers, and libraries. In makefile-based projects, the options you pass to the compiler and linker do this for you.
One of the files in the new search path is $(SDKROOT)/usr/include/AvailabilityMacros.h
, which is the principal header for driving weak linking support. This header file sets the preprocessor macro MAC_OS_X_VERSION_MAX_ALLOWED
to a constant that is equivalent to the version represented by that SDK (for example, 1028 for Mac OS X v10.2.8).
When you choose a Mac OS X deployment OS, as described in “Configuring Your Project for Cross Development,” you assign a constant value to the MACOSX_DEPLOYMENT_TARGET
build setting that corresponds to the chosen major system version (such as 10.1, 10.2, 10.3, or 10.4). The compiler uses this build setting to enable weak linking. The compiler also uses this value to set the preprocessor symbol MAC_OS_X_VERSION_MIN_REQUIRED
, which is used by the header AvailabilityMacros.h
to determine which functions are weak linked.
Important: When you select an SDK for a project in Xcode (see “Configuring Your Project for Cross Development”), the SDK you choose applies to all targets in the project (all are built with headers and libraries from the specified SDK). Although it is possible to specify an SDK on a per-target basis, doing so may interfere with the operation of other Xcode features that rely on a projectwide SDK setting, as described in “How SDK Settings Affect Other Features of Xcode.” You can select a deployment OS (described in “Configuring Your Project for Cross Development”), for an individual target or for all targets in the project. The target or targets can be deployed on systems back to the specified OS version. To learn more about build settings and their precedence, see Xcode 2.2 User Guide.
The MAC_OS_X_VERSION_MIN_REQUIRED
and MAC_OS_X_VERSION_MAX_ALLOWED
preprocessor symbols are used by the AvailabilityMacros.h
header file to define a number of other preprocessor symbols using the GCC compiler directives __attribute__((weak_import))
and __attribute__((deprecated))
. Those symbols are used extensively in Carbon header files (and in many, but not all, Cocoa headers) to define which function or method calls are available in different versions of the operating system.
The combination of these actions makes the following things happen:
If your code uses a symbol that is not defined in the selected SDK, you get a compile-time error.
If your code uses a symbol that is defined but is marked as deprecated, you get a compile-time warning.
If your code uses a symbol that is defined in the selected SDK and in the selected deployment OS, your code builds and links normally. At run time:
on systems earlier than the deployment version, your code may fail to load if you use symbols unavailable in that version
on systems equal to or later than the deployment version, you may get weak references (that is, null function pointers) for symbols not supported in that version; it is up to your code to be prepared for this—for an example see “Check for Undefined Function Calls.”
Note: The Carbon and Cocoa framework headers in Mac OS X version 10.2 and later automatically include AvailabilityMacros.h
, but those in version 10.1 (which pre-dates the introduction of AvailabilityMacros.h
) do not.
AvailabilityMacros.h
. Code that uses the 10.1.5 SDK and the availability macros can compile successfully by specifically including that header, with a statement like the following (which you can place in your prefix header file):#include <AvailabilityMacros.h>
For an example, see “Conditionally Compile for Different SDKs.”As you would expect, changing SDK settings in Xcode can have an effect on other Xcode features. Here are some of the changes you may observe:
When you change the selected SDK:
Xcode rebuilds the index for the project.
Rebuilding results in the equivalent of a clean rebuild.
Double-clicking a symbol in the Project Symbols smart group should take you to its definition in the chosen SDK. You can Command-click in the title bar of the header file to see the path, which starts with /Developer/SDKs/MacOSX…
rather than /System/Library/Frameworks…
.
Code completion is based on the SDK in use. For example, if you are targeting Mac OS X version 10.3.9, typing “HIAboutB…” should complete to HIAboutBox
. However, if you are targeting version 10.2.8, HIAboutBox
is not defined, and does not appear in the code completion interface.
When you select a #include<header>
directive in a source file, typing Command-D opens the header from the currently selected SDK, rather than from /System/Library/Frameworks
.
When debugging your code, symbolic information from headers (such as inline function body definitions) will come from the currently selected SDK, not from the root system on which you are running.
Cross-development is most strongly supported by the Carbon APIs and to a lesser degree by Cocoa. However, given the dynamic nature of Objective-C (for example, it doesn’t produce link errors, it just raises a runtime exception if you call a method that doesn’t exist), cross-development support is less important for Cocoa applications.
Some OS X frameworks, most notably those derived from Open Source projects, such as OpenGL and the BSD and Kernel frameworks, do not use Apple's availability macros to support cross-development. However, code that makes kernel-specific calls is likely to be closely bound to the OS that supports those calls, and is less likely to benefit from cross-development. Code that works with OpenGL can use the mechanisms described in Technical Q&A QA1188: OpenGL Entry Points and GetProcAddress.
QuickTime has a separately distributed SDK that can be installed on any variant of Mac OS X v10.2 or later. As a result, certain QuickTime APIs are not bound to a particular version of the OS. In addition, when you install a QuickTime SDK, it’s installed into your current operating system, not into any of your developer SDKs. Because a developer SDK does not necessarily include the headers from the latest software update of QuickTime, you can’t currently use SDK support and the QuickTime SDK simultaneously.
Note: QuickTime and some related components, such as Core Audio, provide extensions to the availability macros that tell you which features are available in particular QuickTime software updates.
The following are some additional limitations of cross-development support:
Weak linking is not available prior to Mac OS X v10.2. As a result, software developed with a deployment OS set for Mac OS X v10.1 will not load in v10.1 if it uses features from later system versions.
If you want to deploy the same code in Mac OS X version 10.1.5 as in version 10.2 and later, you have to build the 10.1.5 code as a separate project with a separate executable. Set the selected SDK to 10.1.5 and the Mac OS X deployment OS to 10.1. This code will not be able to use features from the more recent OS versions.
The compiler calling conventions for C++ code changed in Mac OS X version 10.2 with GCC 3.1, so to compile C++ code targeting Mac OS X v10.1, you must use the GCC 2.95.2 compiler.
Note: The Mac OS X v10.1.5 SDK and GCC 2.95.2 are no longer included with the Xcode Tools. If you want to build for Mac OS X v10.1 you must install the SDK and the compiler from Xcode 1.5 or earlier.
For additional information on weak linking in this document, see “Building,” “Loading,” “How SDK Settings Affect The Build,” and “Check for Undefined Function Calls.”
Xcode uses a native build system that performs its own dependency analysis and directly invokes the necessary build commands. Cross-development SDK support works with targets that use the native build system, but it does not work with Project Builder targets that have not been upgraded to native targets.
In Xcode, you can’t use the SDK setting in the General pane of the project inspector to alter the SDK selection based on the current build configuration.
Cross-development support works primarily with release, not debug, builds of your software. You cannot use the ZeroLink or Fix and Continue features in Xcode if you have selected the 10.2.8 or earlier SDK, because those features require development-time frameworks that are only available in Mac OS X v10.3. However, to use ZeroLink but deploy on Jaguar, you can set the deployment OS to 10.2 in your release build configuration but not in your debug build configuration.
Code built with GCC 4.0 does not run on versions of Mac OS X prior to Mac OS X v10.3 (10.3.9 for C++ or Objective-C++). To target these versions of Mac OS X, you must build using GCC 3.3.
© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-11-07)