Building USB driver kext for our USB device on xcode 6.1 with build settings Architecture= Universal(32/64bit Intel) and Base SDK=10.8, Build fail with error,
clang: error: the clang compiler does not support 'fapple-kext' for C++ on Darwin/i386
Command /Applications/Xcode 2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang failed with exit code 1
The same project build successfully if I select "Build Active Architecture only = Yes" but in that case kextload failed with following errors on 10.8 OSX but it worked on 10.9 OSX
Dec 19 17:36:22 localhost com.apple.kextd[16]: Failed to load /System/Library/Extensions/gdmuwm.kext - (libkern/kext) link error.
Dec 19 17:36:22 localhost kernel[0]: kxld[com.gct.driver.gdmuwm]: The super class vtable '__ZTV12IOUserClient' for vtable '__ZTV13GdmUserClient' is out of date. Make sure your kext has been built against the correct headers.
Dec 19 17:36:22 localhost kernel[0]: kxld[com.gct.driver.gdmuwm]: The super class vtable '__ZTV19IOEthernetInterface' for vtable '__ZTV5gdmif' is out of date. Make sure your kext has been built against the correct headers.
Dec 19 17:36:22 localhost kernel[0]: kxld[com.gct.driver.gdmuwm]: The super class vtable '__ZTV20IOEthernetController' for vtable '__ZTV6gdmuwm' is out of date. Make sure your kext has been built against the correct headers.
Dec 19 17:36:22 localhost kernel[0]: Can't load kext com.gct.driver.gdmuwm - link failed.
Dec 19 17:36:22 localhost kernel[0]: Failed to load executable for kext com.gct.driver.gdmuwm.
Dec 19 17:36:22 localhost kernel[0]: Kext com.gct.driver.gdmuwm failed to load (0xdc008016).
Dec 19 17:36:22 localhost kernel[0]: Failed to load kext com.gct.driver.gdmuwm (error 0xdc008016).
Please help me how to resolve this link error for driver.
The universal build error has nothing to do with the OS X version you're running, and everything with the version of clang/Xcode. You can't use recent versions of clang to compile kexts for the i386 architecture. I think the last version of Xcode to support 32-bit kexts was 4.6.3. (available from the downloads section of Apple's developer site) Note that you can't codesign 32-bit or universal kexts either, so you'll need to provide 2 versions of your kext anyway if you're planning to support both OS X <= 10.7 and >= 10.9. You can build a universal kext with Xcode 4.6.3, and the signed version with Xcode 6.x.
The link/load error is due to the OS X SDK version you're using. In general, don't expect I/O kit based kexts built against OS X SDK 10.y to load on OS X 10.z if z < y. So if you need to support 10.8, build with the 10.8 SDK (or older). If you want to support features only available in a newer SDK, you will need to create multiple kext versions (you'll need to do this anyway if you want to support 10.7 or lower) or have a base kext that works for all supported versions, and an enhanced kext that depends on the base kext and adds the relevant features, but only works for newer OS versions. You will of course need to go back to an Xcode version that still ships with your required SDK.
Sensible OS X version groupings are:
You can of course split into more than 2 versions of your kext if you need more feature granularity.
Note that you can weakly link against pure C symbols, only the C++ linkage is problematic.
2018 Update, as this answer seems popular at the moment, >3 years on:
It's a little tricky to build 32-bit kexts on a modern system. The easiest is definitely to set up a VM with an old OS X version and use Xcode 4.6.3 there. However, that messes up the build for kexts and other project components targeting modern OS versions, so that prevents you from having a grand unified build that builds everything. It's fine for release builds if you're set up with a fancy CI system that can pull in the build artifacts from multiple build agents, but it's still a pain for the edit-build-debug cycle.
Another solution I've found is to use the old compiler on modern macOS. Xcode 4 itself doesn't run on recent versions, but the compiler can be persuaded to do so, and produces correct 32-bit kexts.
I have the following bash code in the preparation phase of one of our build scripts:
VERBOSE=1
export XCODE463APP=`mdfind 'kMDItemCFBundleIdentifier = "com.apple.dt.Xcode" && kMDItemVersion = "4.6.3"' | head -n 1`
DARWIN_MAJOR=`uname -r | sed -E 's/^([0-9]+)\..*$/\1/'`
if [ -e "./build-tools/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" ] && [ -e "./build-tools/Developer/usr/llvm-gcc-4.2/bin/llvm-gcc-4.2" ] ; then
if (( $VERBOSE )); then
echo 32-bit kext compiler appears to be in place
fi
else
echo "Setting up 32-bit kext compiler toolchain"
mkdir -p "./build-tools/Developer/Toolchains"
mkdir -p "./build-tools/Developer/usr/"
cp -r "$XCODE463APP/Contents/Developer/Toolchains/XcodeDefault.xctoolchain" "./build-tools/Developer/Toolchains/"
cp -r "$XCODE463APP/Contents/Developer/usr/llvm-gcc-4.2" "./build-tools/Developer/usr/"
fi
if [ -h "./build-tools/Developer/usr/llvm-gcc-4.2/libexec/gcc/i686-apple-darwin${DARWIN_MAJOR}" ] || [ -e "./build-tools/Developer/usr/llvm-gcc-4.2/libexec/gcc/i686-apple-darwin${DARWIN_MAJOR}" ] ; then
if (( $VERBOSE )); then
echo "32-bit kext compiler's Darwin-version-specific stuff appears to be set up"
fi
else
echo "Setting up 32-bit kext compiler's Darwin version specific symlink"
ln -s "i686-apple-darwin11" "./build-tools/Developer/usr/llvm-gcc-4.2/libexec/gcc/i686-apple-darwin${DARWIN_MAJOR}"
fi
This pulls out the 32-bit compiler from the Xcode 4.6.3 bundle and puts it in a local build directory, then adds a symlink with the macOS (Darwin) version in its name, which the compiler seems to look for. Xcode 4.6.3 itself only ships with those symlinks for up to 10.9 or 10.10 if I remember correctly, but adding them for newer versions seems to make it happy. I can confirm this works for building 32-bit kext slices with the 10.6 SDK on 10.11 and 10.12 systems.
A cleaner solution would probably be to build llvm-gcc from source, but probably more time consuming to set up too.