Discussion:
[patch] Extend AC_PROG_CXX to check for standards conformance
Roger Leigh
2013-01-20 21:27:05 UTC
Permalink
Patch attached. Probably not in its final form, but I hope
it will be useful as a basis for discussion.

This is like the existing C89/99/11 checks, but for C++.
In this patch, I've implemented three checks:

AC_PROG_CXX_CXX98
AC_PROG_CXX_CXX98TR1
AC_PROG_CXX_CXX11

and AC_PROG_CXX will try them in the order
AC_PROG_CXX_CXX11, AC_PROG_CXX_CXX98TR1, AC_PROG_CXX_CXX98
in order to put the compiler in the highest available mode
by default. Each one performs a set of language and/or
library tests for each standard version.

Note that like the C equivalents, these are marked deprecated
and are not usable in their own right. I'm still of the opinion
that it's useful to restrict the compiler to a minimum standard
so that you can
- prevent the use of features you don't want to use
- ensure that the features you do want are present
So ideally, I'd like to re-enable the C and C++ standard-
specific checks, if the consensus is that these remain useful,
and also add AC_PROG_CC_C11, which is currently missing.

Other points for discussion:
- The flags for non-GCC compilers were obtained from online
documentation. They are untested, and may be wrong; they
are certainly not complete since I don't use non-GCC
compilers myself. Fairly trivial to test and update if
anyone has access to such compilers.
- The feature tests are restricted to those which pass with
GCC 4.7. Depending upon which other compilers we want to
put into "C++11 mode", this test set may need reducing to
the common set which are usable across different compilers
and/or compiler versions.

I've not updated the manual yet; I'll do this if people are
generally happy with things.


Kind regards,
Roger
--
.''`. Roger Leigh
: :' : Debian GNU/Linux http://people.debian.org/~rleigh/
`. `' schroot and sbuild http://alioth.debian.org/projects/buildd-tools
`- GPG Public Key F33D 281D 470A B443 6756 147C 07B3 C8BC 4083 E800
Paul Eggert
2013-01-21 06:47:05 UTC
Permalink
Thanks for doing that.

I don't use C++, so I'm not the best person to review this patch.
But from a quick look I can see one thing missing: the documentation
needs updating.
Post by Roger Leigh
it's useful to restrict the compiler to a minimum standard
so that you can
- prevent the use of features you don't want to use
- ensure that the features you do want are present
In practice, for C at least, almost nobody wants the
former, and Autoconf already does the latter, so it's
good enough.
Roger Leigh
2013-01-21 13:46:13 UTC
Permalink
Post by Paul Eggert
Thanks for doing that.
I don't use C++, so I'm not the best person to review this patch.
But from a quick look I can see one thing missing: the documentation
needs updating.
Sure, I mentioned why it was missing in my mail. I'll add it in
when I next post an updated patch. If it's useful, I can also split
up the checks into individual feature tests for each
C++11/C++98TR1/C++98 language/library test, and have the general mode
tests aggregate these togther as they are now.
Post by Paul Eggert
Post by Roger Leigh
it's useful to restrict the compiler to a minimum standard
so that you can
- prevent the use of features you don't want to use
- ensure that the features you do want are present
In practice, for C at least, almost nobody wants the
former, and Autoconf already does the latter, so it's
good enough.
For both C and C++, I think there are some considerations
here where it does make sense:

- If my project supports language standard n, enabling
standard n+1 or n+2 enables language features which are
actively harmful to use, since unintentional introduction
of later language features will break building on systems
which don't support it.

- If my project supports language standard n, and autoconf
autodetects n-1, configure will succeed unless I do
additional feature tests. It will of course fail at
compile time, but the fallbacks are essentially useless to
me.

Examples:
I'm using C++11 language features in my code. These are unavailable
to me unless the compiler supports it natively, which may require
putting it into C++11 mode with -std=gnu++11 or equivalent. With
this patch, AC_PROC_CXX will put the compiler into C++11 mode if
available, or it will fall back to C++98TR1 or C++98 (or earlier).
*None* of these fallbacks are helpful. Using
AC_PROG_CXX_CXX11 clearly states that the system must have a C++11
compiler, or else bail out. The same applies to C11/C99 etc.

Selecting the latest available standard is certainly useful as the
default, I don't disagree with that at all. But if I need a
minimum compiler version, I don't want a fallback to an even earlier
version. I need the minimum version or nothing. This is completely
orthogonal to the feature tests I might perform with the compiler in a
particular standard mode; I need it to be in that mode to start with.
Post by Paul Eggert
From the other POV, if my code is written using ISO C89, having the
compiler in C99 or C11 modes is not /actively/ harmful. But if I
really don't want those language features, AC_PROG_CC_C89 is the
minimum. Now this might still leave the compiler in a higher mode;
we can't help that. But, on compilers which do support -std=c89 or
equivalent, I've turned off the extra features which might get silently
introduced into my code, ultimately breaking stuff. I'll catch them
as I'm developing, rather than after release.


Regards,
Roger
--
.''`. Roger Leigh
: :' : Debian GNU/Linux http://people.debian.org/~rleigh/
`. `' schroot and sbuild http://alioth.debian.org/projects/buildd-tools
`- GPG Public Key F33D 281D 470A B443 6756 147C 07B3 C8BC 4083 E800
Paul Eggert
2013-01-21 18:02:01 UTC
Permalink
Post by Roger Leigh
For both C and C++, I think there are some considerations
- If my project supports language standard n, enabling
standard n+1 or n+2 enables language features which are
actively harmful to use, since unintentional introduction
of later language features will break building on systems
which don't support it.
Yes, if this were a real problem, we'd have to do something
about it. But for C, it's not, and it hasn't been a problem
ever since Autoconf was introduced. Historically, the biggest
problem in this area was when C89 supplanted K&R C; and even
back then, Autoconf was firmly in the "let's default to the
latest version". This approach worked fine then and works
even better now.
Post by Roger Leigh
- If my project supports language standard n, and autoconf
autodetects n-1, configure will succeed unless I do
additional feature tests. It will of course fail at
compile time, but the fallbacks are essentially useless to
me.
They may not help, but in practice they don't hurt. Right now,
for example, one would be crazy to insist on C11, as that would
prevent too many people from using one's package. By the time
it's safe to insist on C11, almost everyone will have it, and
the few people who don't have it will all know what to
do when the fallback kicks in.

I'm not saying that we shouldn't do anything in this area, but I
am leery about adding a half-dozen published macros and the resultant
complexity in documentation for a feature that hardly any
developer will actually need, a feature that (unless carefully documented)
is likely to confuse developers into thinking that they need it.

I think the main issue here is philosophical. Autoconf is designed
to tailor the program to whatever the host provides. The C and C++
standards follow a different tradition: they specify what the host
must provide. Both approaches work, indeed the Autoconf way depends
on a minimal standard substrate, but once you're in the Autoconf
world it's better to do things the Autoconf way.

This is why, for example, there's no Autoconf macro for specifying
which POSIX version the package wants, or which version of the GNU
C library the package wants. There's just AC_USE_SYSTEM_EXTENSIONS,
which gives you everything, and that's good enough. The sort of
standards-lawyering that requires the use of macros like _POSIX_SOURCE
is exactly the sort of thing that Autoconf is supposed to liberate
developers from.
Roger Leigh
2013-01-21 20:36:37 UTC
Permalink
Post by Paul Eggert
Post by Roger Leigh
For both C and C++, I think there are some considerations
- If my project supports language standard n, enabling
standard n+1 or n+2 enables language features which are
actively harmful to use, since unintentional introduction
of later language features will break building on systems
which don't support it.
Yes, if this were a real problem, we'd have to do something
about it. But for C, it's not, and it hasn't been a problem
ever since Autoconf was introduced. Historically, the biggest
problem in this area was when C89 supplanted K&R C; and even
back then, Autoconf was firmly in the "let's default to the
latest version". This approach worked fine then and works
even better now.
I think the fundamental issue is in the behaviour of what we
do when the system doesn't provide a required feature. In the
case of many of the historical features, autoconf permits the
program to adapt to the system by implementing various
workarounds to enable the code to build and run when certain
features are missing or not compatible. For C stuff like
const/restrict/volatile/inline, it's possible to achieve this
fairly simply, and autoconf does a very good job here.

However, if you look at the C++11 features like declspec,
automatic type inference, array initialisers, delegate
constructors, range-based for loops, lambdas, etc. these
features can not be substituted for. If you use them, you
absolutely require a C++11 compiler; there is no sane fallback.
A fallback is certainly possible for some of the keywords,
e.g. "final" and is very much possible for library functionality
e.g. shared_ptr. But for the core language changes, for the
most part this is simply impossible.

It's this situation that calls for the ability to disable the
fallbacks and require a specific version.

Note that this also applies to C11, but to a lesser extent.
Post by Paul Eggert
Post by Roger Leigh
- If my project supports language standard n, and autoconf
autodetects n-1, configure will succeed unless I do
additional feature tests. It will of course fail at
compile time, but the fallbacks are essentially useless to
me.
They may not help, but in practice they don't hurt. Right now,
for example, one would be crazy to insist on C11, as that would
prevent too many people from using one's package. By the time
it's safe to insist on C11, almost everyone will have it, and
the few people who don't have it will all know what to
do when the fallback kicks in.
At least from my perspective, my primary target is contemporary
GNU/Linux systems. Given that the current compiler in use in
Debian is GCC 4.7 and in the next+1 stable release will be >=4.8,
and what I'm developing right now will target the next+1 stable
release, I have no reason not to use C++11 features today. The
only current thing preventing this is lack of portable support
for it in autoconf, which this patch aims to solve. This is
certainly not the norm, and I can quite understand people not
wanting to use it today, but I would certainly like to have
support for it sooner rather than later.
Post by Paul Eggert
I'm not saying that we shouldn't do anything in this area, but I am
leery about adding a half-dozen published macros and the resultant
complexity in documentation for a feature that hardly any developer will
actually need, a feature that (unless carefully documented) is likely to
confuse developers into thinking that they need it.
I quite accept that the default macros will serve the vast
majority of users well. But with the many new keywords introduced
which don't have fallbacks, I do think that being able to select
"C++11 only" or "C++98 only" is needed here.
Post by Paul Eggert
I think the main issue here is philosophical. Autoconf is designed
to tailor the program to whatever the host provides. The C and C++
standards follow a different tradition: they specify what the host
must provide. Both approaches work, indeed the Autoconf way depends
on a minimal standard substrate, but once you're in the Autoconf
world it's better to do things the Autoconf way.
Agreed for the most part. However, for both the C and C++ macros
it doesn't really /cost/ us anything to give the user the choice;
they can use the recommended way with autodetection and best-effort
fallback to the latest available standard, or choose a specific
standard. While for both C and C++, using the latest by default
is certainly sensible, when your code is using features which
/unconditionally require/ a strict dependency on a minimum version,
I do feel that being able to request autoconf satisfy that need
is needed and useful.



Regards,
Roger
--
.''`. Roger Leigh
: :' : Debian GNU/Linux http://people.debian.org/~rleigh/
`. `' schroot and sbuild http://alioth.debian.org/projects/buildd-tools
`- GPG Public Key F33D 281D 470A B443 6756 147C 07B3 C8BC 4083 E800
Miles Bader
2013-01-22 00:01:43 UTC
Permalink
However, if you look at the C++11 features like declspec, automatic
type inference, array initialisers, delegate constructors,
range-based for loops, lambdas, etc. these features can not be
substituted for. If you use them, you absolutely require a C++11
compiler; there is no sane fallback.
That's not true for _every_ C++11 feature though.

E.g., I use std::thread, the std:: random classes if available,
otherwise I look for boost (etc). I can use either std::unique_ptr or
std::auto_ptr (via a thin wrapper); the former is safer and better for
development, but the latter is good enough for running.

If you need C++11 features and don't have any compatibility fallbacks,
isn't following the autoconf language test in configure.ac by
"if not c++11 then AC_ERROR([BARF! Need a C++11 compiler!])" good
enough?

-miles
--
In New York, most people don't have cars, so if you want to kill a person, you
have to take the subway to their house. And sometimes on the way, the train
is delayed and you get impatient, so you have to kill someone on the subway.
[George Carlin]
Paul Eggert
2013-01-22 06:38:15 UTC
Permalink
Post by Roger Leigh
For C stuff like
const/restrict/volatile/inline, it's possible to achieve this
fairly simply, and autoconf does a very good job here.
However, if you look at the C++11 features like declspec,
automatic type inference, array initialisers, delegate
constructors, range-based for loops, lambdas, etc. these
features can not be substituted for.
C++11 is not materially different from C11 in
this respect. C11 has features such as _Generic,
_Thread_local, anonymous unions, _Atomic, etc.,
that also can't be substituted for.

And this issue isn't new to C11. C99 has many features,
such as variable length arrays and 'long long', that
simply can't be implemented via macro substitutes in
C89-only systems. If you want to use variable length
arrays, you really need a compiler that supports them.

So there's nothing new here. Some features can be
backported, others can't. But that doesn't mean Autoconf
should be encouraging the use of obsolete standards.
Post by Roger Leigh
I have no reason not to use C++11 features today. The
only current thing preventing this is lack of portable support
for it in autoconf
This is a good argument for Autoconf encouraging the use of the
latest C++ version. But it's not an argument for Autoconf
encouraging the use of some *older* C++ version.
Post by Roger Leigh
If you need C++11 features and don't have any compatibility fallbacks,
isn't following the autoconf language test in configure.ac by
"if not c++11 then AC_ERROR([BARF! Need a C++11 compiler!])" good
enough?
Yes, that's the right question.
Roger Leigh
2013-01-22 20:07:01 UTC
Permalink
Post by Roger Leigh
For C stuff like
const/restrict/volatile/inline, it's possible to achieve this
fairly simply, and autoconf does a very good job here.
However, if you look at the C++11 features like declspec,
automatic type inference, array initialisers, delegate
constructors, range-based for loops, lambdas, etc. these
features can not be substituted for.
If you need C++11 features and don't have any compatibility fallbacks,
isn't following the autoconf language test in configure.ac by
"if not c++11 then AC_ERROR([BARF! Need a C++11 compiler!])" good
enough?
That would probably satisfy my own particular use case sufficiently.

Please find attached a reworked and simplified patch. This patch
adds no user-visible macros, and removes the TR1 checks which can
be done simply enough by the user. This means it will check for
only C++11 and C++98. We have the specific ac_cv_prog_cxx_cxx11
and ac_cv_prog_cxx_cxx98 which are both set to no if unavailable,
exactly like for C, and these can be checked to see if the
compiler satisfies your requirements.

Hope that's all OK with you.


Regards,
Roger
--
.''`. Roger Leigh
: :' : Debian GNU/Linux http://people.debian.org/~rleigh/
`. `' schroot and sbuild http://alioth.debian.org/projects/buildd-tools
`- GPG Public Key F33D 281D 470A B443 6756 147C 07B3 C8BC 4083 E800
Roger Leigh
2013-01-28 22:02:37 UTC
Permalink
Post by Roger Leigh
Post by Roger Leigh
For C stuff like
const/restrict/volatile/inline, it's possible to achieve this
fairly simply, and autoconf does a very good job here.
However, if you look at the C++11 features like declspec,
automatic type inference, array initialisers, delegate
constructors, range-based for loops, lambdas, etc. these
features can not be substituted for.
If you need C++11 features and don't have any compatibility fallbacks,
isn't following the autoconf language test in configure.ac by
"if not c++11 then AC_ERROR([BARF! Need a C++11 compiler!])" good
enough?
That would probably satisfy my own particular use case sufficiently.
Please find attached a reworked and simplified patch. This patch
adds no user-visible macros, and removes the TR1 checks which can
be done simply enough by the user. This means it will check for
only C++11 and C++98. We have the specific ac_cv_prog_cxx_cxx11
and ac_cv_prog_cxx_cxx98 which are both set to no if unavailable,
exactly like for C, and these can be checked to see if the
compiler satisfies your requirements.
Hope that's all OK with you.
If there's anything here you're unhappy with, I'll be happy to
make any needed changes.


Thanks,
Roger
--
.''`. Roger Leigh
: :' : Debian GNU/Linux http://people.debian.org/~rleigh/
`. `' schroot and sbuild http://alioth.debian.org/projects/buildd-tools
`- GPG Public Key F33D 281D 470A B443 6756 147C 07B3 C8BC 4083 E800
Paul Eggert
2013-01-29 07:32:36 UTC
Permalink
Thanks, I installed that, with a NEWS item added.

Roger Leigh
2013-01-21 22:07:46 UTC
Permalink
Post by Paul Eggert
Thanks for doing that.
I don't use C++, so I'm not the best person to review this patch.
But from a quick look I can see one thing missing: the documentation
needs updating.
I've attached an updated patch which includes all the texinfo
manual updates, plus some further improvements to the existing
patch.

Note that it could be simplified if required by removing the C++98TR1
checks, since these are library features only, so is otherwise
identical to the C++98 checks for all practical purposes. End
users could do regular feature tests for them if they wish. I'll
be happy to remove them if needed. Likewise I'll be happy to make
any further changes you need.

WRT copyright assignment, I filled in all the paperwork when I
submitted the C99 macros a few years back now.


Kind regards,
Roger
--
.''`. Roger Leigh
: :' : Debian GNU/Linux http://people.debian.org/~rleigh/
`. `' schroot and sbuild http://alioth.debian.org/projects/buildd-tools
`- GPG Public Key F33D 281D 470A B443 6756 147C 07B3 C8BC 4083 E800
Loading...