Baum mit Augen's answer that _LIBCPP_DEBUG_LEVEL >= 2
standard library code for lower level iterator debugging is basically unusable, appears to still be the case with the out-of-the-box Xcode 11.6. But if you're up for extra work or just want more specifics, read on...
Enabling _LIBCPP_DEBUG_LEVEL
code is enabling LLVM's Debug Mode. According to that documentation, enabling this debug mode is done by defining the _LIBCPP_DEBUG
to a value of 0 (that "enables most of libc++’s assertions") or 1 (that "enables 'iterator debugging' which provides additional assertions about the validity of iterators used by the program").
In XCode 11.6, I've found that adding _LIBCPP_DEBUG=0
to a project's Debug Preprocessor Macros setting, compiles and links and indeed adds additional checks - at least checking against out of range references to std::vector
elements via its []
operator. Enabling the _LIBCPP_DEBUG_LEVEL >= 2
code is done by instead setting _LIBCPP_DEBUG=1
. That alone however won't fully link as not all the necessary symbols are found. Specifically, the std::__1::__libcpp_db::__insert_c(void*, std::__1::__c_node* (*)(void*, void*, std::__1::__c_node*))
symbol is reported as undefined and maybe others as well. Presumably, XCode 11.6 did not ship with this built into the standard C++ library it provides. If anybody knows better or could corroborate this, I'd appreciate hearing from them.
With the following extra work, I've been able to enable libc++'s assertions plus the additional iterator debugging capabilities:
- Install a recent LLVM package somewhere that doesn't interfere with Xcode's included LLVM package. I installed LLVM 10.0.1 using Homebrew and I was able to access it then under
/usr/local/Cellar/llvm/10.0.1
.
- Have Xcode recognize the Xcode tool chain support that this new LLVM package provides. I added a symbolic link to
/usr/local/Cellar/llvm/10.0.1/Toolchains/LLVM10.0.1.xctoolchain
into Xcode's /Applications/Xcode.app/Contents/Developer/Toolchains
directory. I'd done that while Xcode was running and it immediately saw the new tool chain but I had to restart Xcode to get it to compile with it.
- Under Xcode's "Xcode" -> "Toolchains" submenu, select the new tool chain. My setup showed "Xcode 11.7" and "org.llvm.10.0.1" and I selected the latter to accomplish this.
- Add the path to the new tool chain's
usr/lib
directory to the LIBRARY_SEARCH_PATHS
declaration for resulting executable Targets. I did this by adding /usr/local/Cellar/llvm/10.0.1/Toolchains/LLVM10.0.1.xctoolchain/usr/lib
to a project's executable target "Library Search Paths" "Debug" setting.
- Have the path to the new tool chain's include directory override the normal standard library's include directory. I haven't confirmed that this is necessary but did this by adding to my library and executable targets'
OTHER_CPLUSPLUSFLAGS
declaration the value of -nostdinc++ -I/usr/local/Cellar/llvm/10.0.1/Toolchains/LLVM10.0.1.xctoolchain/usr/include/c++/v1
. From within Xcode, I'd achieved that by setting the "Other C++ Flags" setting to include this value for the targets of interest. I suspect it's probably safer to make this change at the project level than target level.
- Set the
COMPILER_INDEX_STORE_ENABLE
declaration to NO
. This prevented "Unknown argument: '-index-store-path'" errors that stopped builds right from the beginning. I used Xcode's "Enable Index-While-Building Functionality" setting and set it to "No" for this.
- Add
_LIBCPP_DEBUG=1
to the GCC_PREPROCESSOR_DEFINITIONS
declaration for the project. Did this by adding it to Xcode's "Preprocessor Macros" "Debug" setting.
For related Q&A about this, see Is it possible to enable _LIBCPP_DEBUG2 in the current Xcode 4.6.1 toolchain on Mountain Lion?.