Q: Upgrading to QuickTime 6.4 seems to have broken the ability to build our application. In one case we are using CodeWarrior 8.3 on Mac OS X 10.2.6 to build a Mach-O target and are now getting parse errors referring to AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER . How do we fix this?
We also rely on MAC_OS_X_VERSION_10_3 being defined to determine if were building with the Mac OS X 10.3 headers or not. QuickTime 6.4 seems to have updated AvailabilityMacros.h on MacOS X 10.2.x systems and now defines it. What is the correct approach when conditionalizing our code to build on multiple versions of the OS when MAC_OS_X_VERSION_10_3 may, or may not be defined?
A: Whenever you install or update a Framework (in this case QuickTime 6.4) you should always recompile any precompiled headers a project is relying on. Additionally, you should not rely on the existance of a specific OS version macro (in this case MAC_OS_X_VERSION_10_3 ) being defined as the way to conditionalizing your code.
QuickTime 6.4 introduces new APIs which are available on Mac OS X 10.2.x systems when QuickTime 6.4 is installed, and always available on Mac OS X 10.3 systems. These APIs are tagged with AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER ; this macro is defined in the updated version of AvailabilityMacros.h (/usr/include/AvailabilityMacros.h ) but was not defined in the version of this header file that shipped with Mac OS X 10.2.
Note:
The previous version of AvailabilityMacros.h is renamed to AvailabilityMacros.h.orig after installing QuickTime 6.4
|
These Availability Macros help you determine which OS versions or Framework updates introduced the APIs you are using, and can tell the compiler which routines should be weakly linked. For a more detailed explanation of Availability Macros see TN:2064 Ensuring Backward Binary Compatibility - Weak Linking and Availability Macros on Mac OS X.
Solutions:
- Rebuild your CodeWarrior precompiled headers.
- Rebuild your Project Builder precompiled headers.
- Do not test whether
MAC_OS_X_VERSION_10_3 is defined to distinguish between building on Mac OS X 10.2.x and Mac OS X 10.3.
1) If you were using precompiled headers for your CodeWarrior Mach-O project, MacHeadersMach-O.h as your Prefix File in the C/C++ Language Settings panel for example, you can rebuild them by following these steps:
- Navigate to your Metrowerks CodeWarrior directory.
- Find the Build.MacOSX.mcp project located in MSL/(MSL_Build_Projects)/OS X/.
- Double click to open the Build.MacOSX.mcp project.
- Select Make (Command+M) from the Project menu.
2) Project Builder/Xcode users developing using gcc 2.95 or gcc 3.1may notice errors such as:
/System/Library/Frameworks/QuickTime.framework/Headers/QuickTime.h:20:
warning: could not use precompiled header
'/System/Library/Frameworks/Carbon.framework/Headers/Carbon-gcc3.p',
because:/System/Library/Frameworks/QuickTime.framework/Headers/
QuickTime.h:20:
warning: 'AvailabilityMacros.h' has different date than in precomp
|
Fixing these errors also requires a rebuild of your precompiled headers using fixPrecomp .
From the Terminal type: sudo fixPrecomps -force
3) Do not rely on the existance of a specific OS version macro (in this case MAC_OS_X_VERSION_10_3 ) being defined as the way to conditionalizing your code. While it may be very tempting to perform the checks shown in Listing 1 and 1a, these are flawed and liable to fail.
Important:
To help visually demonstrate how using the macro MAC_OS_X_VERSION_10_3 as the way to conditionalize your code can cause unintentional results, Listing 1 and 1a are presented as examples of incorrect use.
|
Listing 1. Incorrect test -- do not do this!
|
// WRONG -- This fails on Mac OS 10.2 systems when
// QuickTime 6.4 is installed, because MAC_OS_X_VERSION_10_3 is defined.
#ifdef MAC_OS_X_VERSION_10_3
// Mac OS X 10.3 only code...
#endif
|
Listing 1a. Incorrect test -- do not do this!
|
// WRONG -- This fails on Mac OS 10.2 systems when
// QuickTime 6.4 is not installed.
// if MAC_OS_X_VERSION_10_3 is not defined, it may be interpreted
// as having the value zero, so the test becomes (1020 >= 0),
// which evaluates to true and could cause Mac OS X 10.3-only code
// to be used unintentionally.
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
// Mac OS X 10.3 only code...
#endif
|
By default, MAC_OS_X_VERSION_MAX_ALLOWED is the version of Mac OS X you are compiling on. For MacOS 10.2.x MAC_OS_X_VERSION_MAX_ALLOWED is defined as 1020 , for MacOS X 10.3 it is 1030 and so on. By using MAC_OS_X_VERSION_MAX_ALLOWED as the way to conditionalize, you are ensuring that the bracketed code will only compile on MacOS X 10.3 or later.
Listing 2. Specifically conditionalize for 10.3 or above
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
// Mac OS X 10.3 only code...
#endif
|
References:
[Oct 21, 2003] |