On Sep 30, 2005, at 4:33 PM, Norm Schuster wrote:
I'm currently in the process of migrating to XCode and probably the biggest stumbling block is how to deal with c/c++ libraries that have endian-specific code that is included or removed at compile time. For example:
#if __LITTLE_ENDIAN__
// do this
#elif __BIG_ENDIAN__
// do that
#endif
Apple's "Universal Binary Programming Guidelines" doesn't say much about this except "Use the __BIG_ENDIAN__ and __LITTLE_ENDIAN__ macros only if you must" but I fail to see how this works unless it builds two separate variants for running on PowerPC and Intel. Can anyone enlighten me on how exactly this works.
The "only if you must" part comes about because nearly all of the cases in which folks want to write "endian-specific" code involves byte-swapping. Whenever you want to swap bytes, you should use OSByteOrder.h, CFByteOrder.h, NSByteOrder.h, or Endian.h, and regardless of which header you use, the compiler won't emit any code that it doesn't have to.
For example, if you're compiling for PowerPC and you call CFSwapInt32HostToBig, the compiler will do nothing on PowerPC and only emit code on Intel.
This lets you avoid #ifdefs in your code and makes your code easier to read.
If you have architecture-specific code that does something other than byte swapping (which is rare), use the appropriate #ifdef. For example, if it's code specific to PowerPC hardware that doesn't exist on any other architecture, use #if __ppc__. But if it's code that would be appropriate to all little-endian systems, use #if __LITTLE_ENDIAN__.
Also, why didn't Apple just add another folder in the bundle containing two different executable files like it did with PEF and Mach-)? Why not have a bundle structure like this:
/Contents/MacOSClassic/PEF_Executable_PPC
/Contents/MacOS/MachO_Exectuable_PPC
/Contents/MacOSIntel/MachO_Executable_Intel
This would have made more sense rather than having a "fat" application with no obvious way to make it leaner.
I'm not sure what you mean by making it leaner. Packaging the two sides of the binary into a single Mach-O executable, as we do today, incurs no performance penalty at all -- only the side that you're running gets mapped in -- and is about as clean as you can get.