How can I change the number of errors GCC displays without invaliding the CMake cache? - c++

I have a C++ project that I build using GCC and CMake.
Generally I like to compile with -fmax-errors=1. My normal workflow is to fix the first error and then rebuild since subsequent errors are often caused by the first one.
But unfortunately, with C++20, an error involving a constraint failure is often treated as multiple "errors" by GCC. In order to see why the constraint failed, I need to see more than one error.
So occasionally I like to set -fmax-errors to a higher number, probably 2, when such an error occurs.
But changing the compiler flags (by manually changing CMakeLists.txt or passing a cache variable to cmake on the command line) invalidates the CMake cache and makes the build start from scratch.
This behavior generally makes sense of course; arbitrary configuration changes could require a rebuild. But we humans understand that changing the compiler's error-formatting behavior doesn't require a rebuild. Is there a way of expressing this distinction to CMake?
Or, failing that, is there a clever way of working around this? I thought of having CMake read an environment variable at the time when the compiler is invoked (not at the time when cmake is run), but I can't find any documentation suggesting that this is actually possible.
(I could probably create a script that forwards most of its arguments to g++ but also adds -fmax-errors="$MY_COOL_ENV_VARIABLE" and then tell CMake that the script in question is the C++ compiler to build with, but I imagine that this might violate some of CMake's expectations about the "compiler.")

At the advice of Marc Glisse, I gave the approach that I hypothesized in parentheses at the end of the question a try. This in fact works quite well.
I now have a Python script called invoke_compiler.py in the top-level directory of my project. I point CMake to the script in the usual way in which one specifies a C++ compiler.
set(CMAKE_CXX_COMPILER ${PROJECT_SOURCE_DIR}/invoke_compiler.py)
Now I was actually a bit terse in the question for the sake of exposition. In actuality I regularly build this project with both GCC and Clang. So I want to be able to specify the C++ compiler to CMake when I invoke cmake.
cmake my-src-dir -DCMAKE_CXX_COMPILER=g++
So invoke_compiler.py has to take a few extra command-line flags, --my-project-cxx-compiler and --my-project-num-errors-flag.
Then the script invokes the compiler (whose executable is the one specified by --my-project-cxx-compiler), forwarding all of its command-line arguments except the extra ones mentioned above and adding f"{num_errors_flag}={os.environ.get('MY_PROJECT_NUM_ERRORS', 1)}". (The name of the compiler flag specifying the number of errors to display must itself be passed as an argument to the script because GCC and Clang call the flag --fmax-errors and --ferror-limit respectively.)
The trick is simply that the logic in CMakeLists.txt that determines which arguments to pass to invoke_compiler.py needs to execute before CMAKE_CXX_COMPILER is overwritten.
The user just interacts with CMake as usual and changes the value of the MY_PROJECT_NUM_ERRORS variable at any time in order to get a different number of errors from the compiler.

Related

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.

Project Settings Recommends Compiler Warning: "Suspicious Moves"

In an Xcode project, I'm getting a weird warning. What is it and is it a bad thing?
Here's the warning:
Project 'Little Hoot' - Enable Recommended Warning
This will enable the following recommended compiler warning:
Suspicious Moves
It is also recommending I updated another setting too.
Target 'Little Hoot' - Update C++ Standard Library
The 'libstdc++' C++ Standard Library is deprecated. This will update the setting for Target 'Little Hoot' to 'Compiler Default', which is the recommended value.
I have looked online and I'm unable to find an answer for at least the first warning.
The "Suspicious Moves" Project/Target setting seems to control the -Wmove compiler warning optionin LLVM/Clang, which is a group of 3 other warning options: -Wpessimizing-move, -Wredundant-move and -Wself-move.
Those options generate these warnings:
warning: moving a temporary object prevents copy elision
warning: moving a local object in a return statement prevents copy elision
warning: redundant move in return statement
warning: explicitly moving variable of type A to itself
(From the Clang documentation at http://clang.llvm.org/docs/DiagnosticsReference.html)
So it's probably not a big deal whether you accept the recommendation and enable the warning, or go without it. You just won't be told if you make things slower with those suspicious moves.
I also got this message from Xcode recently while setting up a new project. My steps were removing the reference from files (such as Info.plist), creating folders directly on Finder, and adding files back to Xcode. I suppose it's a security feature but if your case is like mine, it's only a warning.
Both of these warnings refer to settings in your project not reflecting the recommended defaults. They were probably both triggered after you upgraded your version of Xcode or imported an old project into a later version of Xcode.
Unless you have good reasons to do otherwise, it is best to follow the recommendation. The easiest way to do that is click in the yellow triangles that accompany the warnings and allow Xcode to make the appropriate changes to the settings.
You should turn all warnings on, with the exceptions of pedantic warnings, unused parameters, and auto-synthesised properties; these three warnings warn for tons of good code. Same for static analyser warnings.
Then you look at what warnings you get and fix them. If you haven't done this before, then I'll estimate that 20-40% of all warnings are actual bugs in your code.
You’ll be able to see warning detail in issue navigator section. You can fix it by selecting issue. This will show an alert stating necessary changes to be done in project settings.
Click on Perform Changes button. This will make necessary changes in Project settings and thereby removing this warning.

-mimplicit-it compiler flag not recognized

I am attempting to compile a C++ library for a Tegra TK1. The library links to TBB, which I pulled using the package manager. During compilation I got the following error
/tmp/cc4iLbKz.s: Assembler messages:
/tmp/cc4iLbKz.s:9541: Error: thumb conditional instruction should be in IT block -- `strexeq r2,r3,[r4]'
A bit of googling and this question led me to try adding -mimplicit-it=thumb to CMAKE_CXX_FLAGS, but the compiler doesn't recognize it.
I am compiling on the tegra with kernal 3.10.40-grinch-21.3.4, and using gcc 4.8.4 compiler (thats what comes back when I type c++ -v)
I'm not sure what the initial error message means, though I think it has something to do with the TBB linked library rather than the source I'm compiling. The problem with the fix is also mysterious. Can anyone shed some light on this?
-mimplicit-it is an option to the assembler, not to the compiler. Thus, in the absence of specific assembler flags in your makefile (which you probably don't have, given that you don't appear to be using a separate assembler step), you'll need to use the -Wa option to the compiler to pass it through, i.e. -Wa,-mimplicit-it=thumb.
The source of the issue is almost certainly some inline assembly - possibly from a static inline in a header file if you're really only linking pre-built libraries - which contains conditionally-executed instructions (I'm going to guess its something like a cmpxchg implementation). Since your toolchain could well be configured to compile to the Thumb instruction set - which requires a preceding it (If-Then) instruction to set up conditional instructions - by default, another alternative might be to just compile with -marm (and/or remove -mthumb if appropriate) and sidestep the issue by not using Thumb at all.
Adding compiler option:
-wa
should solve the problem.

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.

How to use C++11 features with Autoconf? [duplicate]

This question already has answers here:
Autotools check for C++11
(2 answers)
Closed 9 years ago.
I have a project configured via Autoconf, and I want to start using C++11 features in this project. How to have the "-std=gnu++0x" switch always enabled and support for the features checked while configuring?
Have you checked ax_cxx_compile_stdcxx_11 ?
I think this is exactly what you want.
There is a big macro library on gnu website.
You can do this with something like AX_CHECK_COMPILE_FLAG, e.g.:
AX_CHECK_COMPILE_FLAG([-std=c++0x], [
CXXFLAGS="$CXXFLAGS -std=c++0x"])
(You need to be careful here that AC_LANG is C++, not C at the point this is called because it's possible to use gcc for C and something else for C++ or vice versa).
I think the simplest way to do this is to add:
CXXFLAGS="$CXXFLAGS -std=c++0x"
in configure.ac before AC_PROG_CXX. If the compiler does not accept -std=c++0x, then configure will fail with "C++ compiler cannot create executables". It is not the best error messages, but it ensures that builds will succeed if configure succeeds. For a better error message, you can check that the compiler accepts the flag after AC_PROG_CXX. In either case, you want configure to fail if the compiler does not provide the necessary features but your software requires it.
Note that setting CXXFLAGS before AC_PROG_CXX has the undesirable side effect of preventing the default setting for CXXFLAGS in the case that the user does not set that variable when running configure. For this reason, it is normally not recommended to set CXXFLAGS in the configury, so it is probably better to check the flag after AC_PROG_CXX (eg using awoodland's solution)--just make sure you add an AC_MSG_ERROR in the third argument of AX_CHECK_COMPILE_FLAG so that configure fails if the features are not available.
To enable the compiler switch (unless, of course, the user overrides it), put this in your Makefile.am:
AM_CXXFLAGS=-std=c++0x
I don't think there's a check available for the presence of C++11 features, but you should be able to write a test program fairly easily with the features you want to use, that will fail if those features are not supported. Then you can write a test as described in this section of the Autoconf manual.