How to enable _LIBCPP_DEBUG_LEVEL>=2 in xcode - c++

When reading the std library implementation I could see lots of checks enabled by #if _LIBCPP_DEBUG_LEVEL >= 2 conditions. I tried to add _LIBCPP_DEBUG_LEVEL = 3 in xcode preprocessor options, but <iterator> doesn't compile anymore:
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__insert_i(this); <----- the error is on this line
#endif
Is there something else I'm missing here to use a higher debug level for the standard library?

According to the libc++ documentation:
Debug mode is currently not functional. Defining _LIBCPP_DEBUG will result in fairly nasty compile errors.
So that is probably the source of that.

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?.

Related

VSCode C++ Intellisense can't discern C++20 features

I try to run codes like
#include <string>
#include <iostream>
int main() {
std::string str = "This is a string";
std::cout << str.starts_with("name");
}
But intellisense will give out an error
"std::__cxx11::basic_string<char, std::char_traits,
std::allocator>" has no member "starts_with" C/C++(135) [6,9]
And It still can be build and produce a correct result.
Also it can find implementation in header file.
But the macro __cplusplus is defined as 201703L
I've already added a command -std=c++20 when building, why this happened?
Compiler: minGW 11.2 compiled by msys2
Assuming you are using Microsoft's C/C++ extension, you must configure the extension to use C++ 20 standard for intellisense.
The easiest way to do this is to add the line "C_Cpp.default.cppStandard": "c++20" to your settings.json file. You can also find the setting in the GUI under the name "Cpp Standard". Selecting c++20 from its dropdown will achieve the same result.
Note that this setting is, by default, set as a global user defaults. You can configure it per-workspace by selecting the Workspace tab in the settings GUI and changing that Cpp Standard dropdown to c++20.
As for why adding the -std=c++20 flag didn't work: -std=c++20 just tells your compiler which standard to use to build your code. 'Intellisense' does not receive this flag because it is a separate tool from the compiler and is therefore not required to support all the standards the compiler supports. It may support less even, although Intellisense tools usually support as current a standard as possible. Therefore the language standard for Intellisense must be configured separately from the compiler (in this case).
Final Note: After changing the setting, try closing and re-opening VS Code. In my experience changing the language standard setting can cause some weirdness to happen. Closing and re-opening VS Code seems to ensure the setting changes take full effect.

How to specify c++ 14/17 with bazel.rc (tool specific to using GCC /G++, project not open to other tool chains)

Within my bazel.rc file for the C++ Bazel build options, I have specified:
'build --cxxopt="-std=c++1y"'
When I try to change to build --cxxopt="-std=c++14", bazel Throws error of :
''build --cxxopt="-std=c++14"' is not an option'
, with a cursor below 4 in c++14. If I change the 4 to y (c++1y), it compiles with no problem. I tried adding 'std:make_unique' in my code (c++14 addition) , and it clearly does not compile (make _unique is not part of std) which is assume is complaining that c++14 is not set as the standard, hence no make_unique for me.
What is the latest supported version of C++ in bazel? More specifically, how do I enable C++14 / C++17 (and even C++2x) for Bazel build, it those are supported? Thanks!
NOTE: this is not the same as How to set C++ standard version when build with Bazel??. (I am not asking about cpp 11 and I am asking about a very specific toolchain -- GCC/g++) I am not using any of the tools suggested by that thread. I am using GCC / g++ and am restricted in not being able to use the tools suggested by the answer in the previous question, I've RTFMd and googled. Thanks in advance.

Make ld ignore directory from /etc/ld.so.conf

TL,DR:
Is there a way for me (no root access) to make the linker (invoked by gcc) unaware of the contents of a directory contained in /etc/ld.so.conf after it has been cached via ldconfig?
In Detail:
I'm trying (and failing) to compile HTCondor on a custom linux distro without root access. For various reasons (see below) I believe that the problems I encounter are related to the fact that there are two versions of libssl and two versions of libcrypto installed on this machine. The newer version (1.0.0) of each of these is located at /usr/lib64 and an older version (0.9.8) is kept at /usr/local/lib64 for compatibility reasons. /etc/ld.so.conf contains both of these paths, so the linker knows about both.
During compilation I get an error
../condor_utils/libcondor_utils_8_7_9.so: undefined reference to `ERR_remove_thread_state'
since, for some reason, libcondor_utils_8_7_9.so is linked against libcrypto.so.0.9.8, while ERR_remove_thread_state was introduced in 1.0.0. It appears exactly once in the source code:
#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state( 0 );
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
ERR_remove_thread_state( 0 );
#endif
so the preprocessor seems to make its decision based on version 1.0.0.
This question made me aware of this blog post, so I tried surrogating cpp with the following script:
#!/bin/bash
/usr/bin/gcc -Wl,-rpath-link="/usr/lib64",-rpath="/usr/lib64" "$#"
to no avail, unfortunately.
Just for the heck of it, I also tried commenting the prepocessor directives in the source code snippet above to force the selection of ERR_remove_state. This results in the linker warning me that libssl.so.1.0.0 may conflict with libssl.so.0.9.8 and, unsurprisingly, produces another "undefined reference" error.
EDIT:
The problem turned out not to be related to the linker at all. See my answer. However, out of curiosity, I'll leave the question open to see if anyone has a solution for it in its original formulation.
The comments by #user463035818 and #jww pointed me in the right direction to solve my specific problem, which turned out not be related to the linker directly.
Condor uses cmake as build system, so obviously it makes more sense to try to solve this at the cmake level (n00b here). Somewhere in the depths of all the things cmake does it finds both versions of the libraries and mixes them up for some reason. Invoking find_library with a specific version as per this answer in the main CMakeLists.txt solves that problem although it leaves a bad taste of dirty workaround in my mouth.
Making cmake ignore a certain directory when looking for libraries should not be hard, according to the docs. I haven't tried it, though.

Eclipse indexer shows false-positive semantic errors

I've recently updated to Eclipse Mars.2 (version 4.5.2) and switched my project to C++11 development (yeah, it's about time!).
I've managed to configure all my Makefiles to build correctly (ie. no obvious errors or warnings) but the Eclipse built-in indexer reports several false-positive semantic errors. Not all of them have to do with C++11 specific features.
I'm referring to already existing threads [1] and [2] which are older and haven't brought any real solution for me.
False-positives examples
std::next(..) not recognized - but I have no problems with std::begin() or std::end():
std::vector<int> v;
for (auto i = std::begin(v); i != std::end(v); i++)
{
std::next(i);
}
Invalid arguments '
Candidates are:
#0 next(#0, std::iterator_traits<#0>::difference_type)
Semantic Error
std::string::substr(..) not recognized:
std::string myString = "test";
myString.substr(0, 1);
Invalid arguments '
Candidates are:
std::basic_string,std::allocator> substr(?, ?)
Semantic Error
googletest's ASSERT_EQ macro is not not recognized (however, other assertions work!):
std::string expValue = "test";
std::string actValue = "test";
ASSERT_EQ(expValue, actValue);
Function 'Compare' could not be resolved
Semantic Error
I've tested various project settings and I came to the conclusion that it has something to do with the Eclipse project's "Paths and Symbols" settings as well with the "Preprocessor Include Paths, Macros, etc." settings. Especially the order of the Providers is highly sensitive for any changes.
The additional problem is that I have an older system with gcc 4.4.4 compiler (default in /usr/bin/gcc) and an additional gcc 4.8.2 installed in /opt/... which shall be actually used for compilation. This also means that I have two sets of header files but only one includes the C++11 features.
My current configuration is this (as seen in Project Settings -> C/C++ General -> Preprocessor Includes Paths -> Entries):
CDT User Settings Entries
system headers of gcc 4.8.2 (treated as built-in)
preprocessor macro __cplusplus = 201103L
CDT Managed Build Settings Entries
paths to custom includes and library paths
CDT GCC Build Output Parser
CDT GCC Built-in Compiler Settings
non-changeable system headers of gcc 4.4.4
local includes
I have tried other combinations as well but this one gives me lowest amount of false-positive errors.
The indexer has project specific settings enabled. I haven't found any switch so far that makes the errors go away.
Has anybody experienced such problems as well? Is it a configuration issue of my paths and symbols or is it a bug in the Eclipse indexer?
std::next(i); is incorrect. When you use
for (auto i : v)
{
std::next(i);
}
i becomes of the type *(v.begin()) which in your code is an int. std::next requires an iterator and that iterator must also provide a difference_type type.
The whole purpose of a ranged based for loop is to not have to worry about advancing through the container. If you wanted to print everything out of the vector you would just use
for (auto i : v)
{
std::cout << i << " ";
}
I know this doesn't solve your other error but it fixes the first one
I updated Eclipse CDT to version 8.8.1 and the false-positive compile errors don't show up anymore. So after all it was a software bug.

Unable to add defines to boost build

I am trying to build a debug build of boost serialization/filesystem/system using boost buildsystem. Here is what I use:
b2 serialization filesystem system variant=debug link=static threading=multi
runtimelink=static define=_HAS_ITERATOR_DEBUGGING=0 toolset=msvc-11.0
However, when I include the library in my debug visual studio projects I still get errors like this:
(basic_iarchive.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in Game.obj
Which leads me to belive that my 'define' in the boost build did not have any effect. What is the proper syntax? I cannot find any examples, and the documentation dosnt say anything else on the matter.
EDIT: I would like to enforce that I want to define _HAS_ITERATOR_DEBUGGING=0 in my boost build
Adding define=_ITERATOR_DEBUG_LEVEL=0 works for me, as Igor commented.
_HAS_ITERATOR_DEBUGGING is then defined by the MS-headers based on the above setting, so you shouldn't try to set it directly.
Setting it to 0 improves debug performance dramatically in some cases (real-time 3d) so there are definitely use cases that speak for it, even though the pain of recompiling all DLLs that expose STL-containers/iterators in their interfaces.
_ITERATOR_DEBUG_LEVEL is not boost's thing but part of standard library implementation that ships with MSVC. You must take greatest care to compile everything in your build with a consistent value of this setting. In many cases a violation it's diagnosed by the linker like the message you quote, unfortunately it can go undetected. As it changes the size and layout of most std collections and related stuff, guess what follows.
By default it is not set to anything, and when you include some standard header it looks for _DEBUG and sets itself to 2. Good way if nothing in the system ever sets it and you consistently use _DEBUG.
With boost I'm not familiar, but would guess the setting you quote would force the macro with value 0. If so, no wonder you have a discrepancy. Set it to 2, or if you mean 0, go ahead and use that in all your projects.