XcodePostFacto enables the use of Yosemite-only Xcode 6.3 on Mac OS X 10.9 Mavericks.
The name is, of course, a nod to the original XPostFacto.
It seems a bit gratitious to break compatibility with an OS release that was current less than 6 months ago, and while the the Yosemite upgrade is free, it has its own inherent costs -- especially in terms of privacy and quality issues.
Plus, I don't like being told what to do :-)
After building the xpf-bootstrap.framework
, Xcode can be launched from the command-line:
env DYLD_INSERT_LIBRARIES=$ABSOLUTE_PATH_TO_FRAMEWORK/xpf-bootstrap.framework/xpf-bootstrap /Applications/Xcode.app/Contents/MacOS/Xcode
Contribution of a wrapping launch application would be most appreciated, especially one that supports drag-and-drop of the Xcode binary to create a new launcher :-)
XcodePostFacto is fully self-hosting, and is being used for full-time Mac development work. However, issues certainly still remain, and I expect to find and fix issues during day-to-day use of Xcode.
There are a number of hurdles to getting Xcode 6.3 running on an earlier release:
- Xcode declares a minimum system version of 10.10, preventing launch via
LaunchServices
and triggering an abort() inHIServices
if you bypass the initialLaunchServices
check. - Xcode continues to ship with no-longer functional 10.9 compatibity code, and enables that code if it detects it's running on Mavericks. This results in crashes -- and even if you got past those, the result wouldn't actually be Xcode 6.3.
- Xcode links against 10.10-only APIs, which trigger both link-time and runtime crashes.
To resolve these issues, we must patch Xcode and system libraries: disabling the legacy compatibility code, all version checks, and performing runtime rebinding of missing symbols.
XcodePostFacto leverages the following mechanisms to achieve this:
- Prior to Xcode's main(), the private
dyld_register_image_state_change_handler
API is used to hookdyld
and modify library symbol references that are critical to bootstrapping the process:- After the library has been rebased, but before it has been linked, we use a custom single-stepping implementation of dyld symbol rebinding to find strong references to Yosemite-only symbols and rewrite them as weak references.
- Once the library has been linked, but before it has been initialized, we use the same
BIND_OPCODE_*
evaluator to rebind symbols to our custom replacements.
- Before handing control back to Xcode, the bootstrap code uses my PLPatchMaster library to register a future patch on Xcode's
DVTPlugInManager
class. This patch addsxpf_bootstrap.framework/Contents/Resources/Xcode
toDVTPlugInManager
's plugin search path. - A custom plugin in
xpf_bootstrap.framework/Contents/Resources/Xcode
uses Xcode's standard plugin mechanisms to hook theIDEInitialize
step, performing a final set of bootstrap operations within the now-initialized Xcode process.