VSCode: native debugging with Xcode in a non-default location
Problem
If you are like me you use a Mac with often multiple versions of Xcode on it, installed into a
non-default (e.g. not /Applications/Xcode
) location. You also like to use VSCode to work on
cross-platform native projects.
If you do both of these things you have undoubtedly discovered that VSCode is unable to debug.
For reasons known only to its C++ extension developers it can only use lldb
debugger if LLDB.framework
is found in one of its default locations.
The official documentation hints at a possible workaround:
- Copy the
lldb-mi
executable in~/.vscode/extensions/ms-vscode.cpptools-<version>/debugAdapters/lldb-mi/bin
to the folder where theLLDB.framework
is located.- Add the full path of
lldb-mi
tomiDebuggerPath
in yourlaunch.json
configuration.
but this doesn’t make much sense when LLDB.framework
comes from Xcode. You don’t want to copy anything into your Xcode installation directory! You probably don’t want to have to type a path deep inside Xcode bundle into your launch.json
either.
More problematically, even if you did all that, it still doesn’t work when using CMake extension
and debugging from it. This doesn’t use launch.json
and is blissfully unaware of your custom lldb-mi
.
Solution
Fortunately, there is another way and it can even be made relatively painless with some scripting. The general approach is:
- Create a symbolic link to desired Xcode’s
LLDB.framework
in~/.vscode/extensions/ms-vscode.cpptools-<version>/debugAdapters/lldb-mi/bin
. Note that this is a user directory and so ok to write to. This alone takes care of CMake debugging. - Create a symbolic link somewhere easy to remember to
~/.vscode/extensions/ms-vscode.cpptools-<version>/debugAdapters/lldb-mi/bin/lldb-mi
. Then use that link asmiDebuggerPath
setting. This takes care oflaunch.json
-style debugging.
For example you could do something likemkdir ~/.vscode-lldb-mi ln -s ~/.vscode/extensions/ms-vscode.cpptools-1.9.7/debugAdapters/lldb-mi/bin/lldb-mi ~/.vscode-lldb-mi/lldb-mi
And then put the following in
launch.json
{ "name": "(lldb) Launch", "type": "cppdbg", "request": "launch", "program": "...path to my program...", "args": [], "stopAtEntry": false, "cwd": "...dir of my program...", "environment": [], "externalConsole": false, "osx": { "MIMode": "lldb", "miDebuggerPath": "${env:HOME}/.vscode-lldb-mi/lldb-mi" } }
This works but requires tedious manual maintenance. Every time you want to switch to a different Xcode you need to manually update the symbolic link. More annoyingly, every time C++ extension is updated (which is often) it creates a new folder for itself under ~/.vscode/extensions` and you need to re-create the symbolic link again.
To avoid the manual hassle I’ve created a script that automates the symbolic link creation. It can be found in this Github repo. The README
file there describes the usage which, hopefully, should be straightforward.
Of course, as with any workarounds the information here is accurate at the moment it was last updated. If you read this significantly later perhaps VSCode team have already addressed the problem (one can hope!) or the steps and the script might not work anymore.