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

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.

Related

Ninja Build System + gcc/clang doesn't output diagnostic colors

When invoking ninja on a C or C++ (hence both tags) project, with the clang or gcc compiler, the output is not colored with ANSI colors.
For example:
error should be red, but isn't.
warning should be yellow/orange, but isn't.
Everything is the same color, and it's really hard to tell what's going on!
Why this happens
This happens because ninja internally creates a pipe(), which stdout and stderr from the compiler (gcc or clang in this case) is re-routed. This makes the check inside gcc and clang, which checks for terminals (which may support color), fail.
A check such as isatty(stdout) does not return true for a pipe, even though that pipe is then forwarded to stdout once again.
It's documented
Ninja's FAQ talks about this on GitHub.com, but this FAQ is not included with the software, not mentioned in the --help, there are no ninja manpages, and common search engines (ddg, google) do not seem to find that FAQ for common search queries relating to color.
Hence, this post, since SO has good SSO.
The fix
Add -fdiagnostics-color=always to your C or CXX flags. For example, with cmake, you can append -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always (or CMAKE_C_FLAGS for C) (or, if you are using CMake 3.24 or later, you can use the CMAKE_COLOR_DIAGNOSTICS variable or environment variable).
This works for gcc (as documented in its manpage) and clang (clang's manpages do not mention this option, but it is included in their command line reference on llvm.org.
As a permanent fix, you could append the following to your .zshrc, .bashrc, or similar:
# force C colored diagnostic output
export CFLAGS="${CFLAGS} -fdiagnostics-color=always"
# force C++ colored diagnostic output
export CXXFLAGS="${CXXFLAGS} -fdiagnostics-color=always"
export CCFLAGS="${CCFLAGS} -fdiagnostics-color=always"
# force C, C++, Cpp (pre-processor) colored diagnostic output
export CPPFLAGS="${CPPFLAGS} -fdiagnostics-color=always"
You should only do this if you KNOW you will never need to pipe your compiler's output anywhere else. Also, this will only work with clang and gcc, and other compilers which support this - so make sure you dont use compilers that choke on this flag.

Warning: range-based for loop is a C++11 extension

While trying to compile a simple range based for loop on MacOS Big Sur, I got this warning:
warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
I tried using clang++ and g++ but both gave the same warning. Is there a way to always compile with C++11 without having to use -std=c++11 and without using aliases?
Edit: The reason I would prefer not to use -std=c++11 is because I want the compiler to default to C++11 or higher.
To provide this question with a proper answer, based on the discussion in the comments:
Compilers such as GCC and Clang set the default in their source code and it cannot be changed by, e.g., modifying a config file. The only way to change the default would be to change it in the source code and to compile the compiler yourself. This is not worth it.
Furthermore, compilers change their default language from time to time, and setting another default, e.g. to C++11, will make all non-C++11 code require setting the language version explicitly.
Here's the key point: code and compilation options belong together. Do not rely on compiler defaults. Any serious project will use a build system (e.g. Make) which specifies how to compile the project.
Edit
For completeness sake, the default C++ version for GCC 10.2.0 is hardcoded in /gcc/c-family/c-opts.c:
/* Set C++ standard to C++17 if not specified on the command line. */
if (c_dialect_cxx ())
set_std_cxx17 (/*ISO*/false);

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

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.

Mingw Disable Classes/Functions/Types Marked Deprecated?

Currently i have a problem with the deprecated messages flooding my output and i want to stop it without disabling all deprecated messages. It is warning me about auto_ptr (which i don't even use in my own code). Even if it can't be done with a compiler flag, the std library looks like it could disable it, though i couldn't find out how:
#if _GLIBCXX_USE_DEPRECATED
template<typename> class auto_ptr;
#endif
You probably selected the -std=c++11 or -std=c++0x language dialect, or it's your GCC versions default setting.
std::auto_ptr is marked as deprecated with the current standard, in favor of the c++11 smart pointers from the dynamic memory management library.
" (which i don't even use in my own code)."
Are you sure that you don't even include any 3rd party (non standard) stuff, that might make use of std::auto_ptr<>?
"the std library looks like it could disable it, though i couldn't find out how"
Just make sure that this flag (_GLIBCXX_USE_DEPRECATED) is undefined, when compiling your code:
$ g++ -U_GLIBCXX_USE_DEPRECATED ...

how can I check a particular gcc feature in configure.ac

For example, gcc 4.7 has a new feature -Wnarrowing. In configure.ac, how can I test where a feature is supported by the current gcc or not?
There's a file in gnulibc, but doesn't make much sense to me.
Both gcc and clang support -W[no-]narrowing and -W[no-]error=narrowing options.
With -std=c++11, gcc emits a warning by default, and clang emits an error by default. Even though you only mention gcc, I think you could extend the functionality check to compilers like clang that attempt to provide the same options and extensions. That might include Intel's icc too.
Let's assume you've selected the C++ compiler with AC_PROG_CXX, and have ensured that it's using the C++11 standard.
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -Werror -Wno-error=narrowing"
AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
[[int i {1.0}; (void) i;]])],
[ac_cxx_warn_narrowing=1], [ac_cxx_warn_narrowing=0])
AS_IF([test $ac_cxx_warn_narrowing -ne 0],
[AC_MSG_RESULT(['$CXX' supports -Wnarrowing])])
AC_LANG_POP([C++])
CXXFLAGS="$ac_save_CXXFLAGS"
Compilation will only succeed if: 1) the compiler supports -Wnarrowing related options, which implies it supports -Werror, and: 2) recognizes C++11 initialization syntax.
Normally, configure.ac scripts and flags passed to configure should avoid -Werror, as it breaks too many internal tests. In this context, we ensure there are no other warnings besides the narrowing, which is why (void) i; is needed to prevent a warning about unused variables.
The logic behind this should probably be:
Create a correct file that should get a warning with -Wnarrowing. Verify that it gets compiled correctly. This is a sanity check.
Then compile that same file with -Wnarrowing, and verify that it still gets compiled correctly. This makes sure you detect compilers that don't support -Wnarrowing as an option, and don't attempt to pass bogus options to them.
Finally, compile that same file with -Werror=narrowing, and verify that it now does not get compiled correctly. If it now fails, you can be fairly certain that the compiler does indeed support -Wnarrowing. This last check is useful to detect compilers that do accept -Wnarrowing/-Werror=narrowing, but spit out a warning "ignoring unknown option -Wnarrowing". In that case, you shouldn't be passing -Wnarrowing.
Optionally, you may also want to compile a file that shouldn't get a warning with -Wnarrowing with -Werror=narrowing, in case you find a compiler where -Wnarrowing is useless and -Werror=narrowing is a hard error. I cannot think of a compiler where this would be required, though.
Translating this to a configure check should be trivial.
See http://code.google.com/p/opendoom/source/browse/trunk/VisualC8/autotools/ac_c_compile_flags.m4 for an example test of this sort - this tries to compile a trivial program with the given compiler flag, and adds it to CFLAGS if it works.