[cmake-developers] target_compile_features remaining issues
Stephen Kelly
steveire at gmail.com
Fri Mar 28 11:16:49 EDT 2014
Hi,
The target_compile_features topic in my clone is almost ready to merge to
next.
Here are some remaining issues to discuss:
1) Extensions
With GNU and Clang, standard C++ features are enabled with a compile flag
something like -std=c++98 or -std=c++11. Compiler specific extensions are
enabled with a flag like -std=c++98 or -std=gnu++11. It is a two-dimensional
system. One axis extends the C++ standard whose features are required, and
the other extends the compiler features.
With XL, compiler specific extensions are enabled with -qlanglvl=extended.
For GNU, Clang and XL, the compiler-specific extensions are enabled by
default.
http://pic.dhe.ibm.com/infocenter/lnxpcomp/v121v141/index.jsp?topic=%2Fcom.ibm.xlcpp121.linux.doc%2Flanguage_ref%2Fexts_general.html
The XL driver doesn't seem to be two dimensional in the same way as GNU.
That is, we can use -qlanglvl=extended0x to get the extensions *and*
the C++0x [sic] features. There doesn't seem to be a -qlanglvl=no-extended
to disable the compiler-specific extensions.
Because the XL driver offers more granularity in features that may be
enabled/disabled, it is possible to enable only the C++0x features by
specifying more flags.
COMPILER | CXX_STANDARD | CXX_EXTENSIONS | FLAG
GNU 98 0 -std=c++98
GNU 98 1 -std=gnu++98
Clang 98 0 -std=c++98
Clang 98 1 -std=gnu++98
XL 98 0 [NA] [1]
XL 98 1 -qlanglvl=extended
GNU 11 0 -std=c++11
GNU 11 1 -std=gnu++11
Clang 11 0 -std=c++11
Clang 11 1 -std=gnu++11
XL 11 0 -qlanglvl=extended0x [2]
XL 11 1 -qlanglvl=extended0x
GNU 14 [3] 0 -std=c++14
GNU 14 1 -std=gnu++14
Clang 14 0 -std=c++14
Clang 14 1 -std=gnu++14
XL 14 0 -qlanglvl=extended14 [4]
XL 14 1 -qlanglvl=extended14
[1] No known -qlanglvl=no-extended flag.
[2] Future versions of XL might enable the C++11 features by default. In
that case we would add no flags for this combination.
[3] CXX_STANDARD=14 allowed in a future CMake version, when it is ratified
and GNU/Clang support -std=c++14.
[4] Or whatever flag they choose to enable C++14 features.
I propose ignoring the granularity of XL and letting the user be more
granular if they wish (I think there's also granularity available with GNU
flags).
Does that have an impact on the order that built-in vs user flags are
specified in the compile commands?
2) Unavailable features
There will be some set of features supported by CMake.
Each tuple of {compiler id, compiler version, lang standard, extensions}
will have some subset of those features available.
If CMake is executed on a target which requires a particular feature, and
CMake knows that the particular feature is not supported by the compiler id
and version (with any extra flags), CMake reports an error.
Recording that a {compiler id, compiler version} supports a particular
feature is fairly easy, as is done in my topic already.
The distinction between "this compiler version supports an empty subset of
the features known to CMake" and "we have not tested the features of this
version of the compiler" is not quite so easy.
Currently my topic reports no error if there are no recorded features for a
compiler version. An error is only reported if the {compiler id, version}
is known to have features (which means someone must have investigated and
added them).
That means that if I try to use MSVC71 for example with a target which
requires cxx_constexpr, there will be no error reported by CMake, because
MSVC71 supports an empty subset of the current features known to CMake.
One way to enable that error would be to introduce a dummy cxx_no_features
feature for use with compilers known to have an empty subset of the features
known to CMake.
3) Maintenance
If CMake learns a cxx_partial_template_specialization feature in the future,
the cxx_no_features feature would be removed for MSVC71 and
cxx_partial_template_specialization added. That means that someone
(preferably with direct access to MSVC71) needs to maintain the list of
features for that {compiler id, compiler version} as the list of features
known to CMake grows.
This is more difficult maintenance to do for compilers which are no longer
widely available or common.
The same requirement of maintaining the list of features is present for
contemporary compilers, but it is easier to maintain for compilers which are
easily available to run.
My topic doesn't record the features of the XL compiler (any version). That
means that no feature requirement will report an error with that compiler
currently. Someone could record the features, but that would require some
commitment of ongoing maintenance of the list for future versions of the
compiler and for future features learned by CMake.
So, I could merge my topic initially with recorded features for GNU 4.8, but
no earlier version of GNU, and commit to maintaining that {GNU, 4.8} tuple
for future CMake features.
That would mean that if someone tries to use CMake with a target which
requires cxx_constexpr and {GNU, 4.6}, which supports that feature with the
-std=c++11 flag, CMake would not add the flag. If the same compiler is used
with a target which requires cxx_override (which GNU 4.6 does not support),
CMake would report no error.
At any time though, someone can come along and record the features of that
compiler and contribute it to CMake and maintain it there.
So, generically, adding new known features to CMake which are present in old
{compiler id, version} tuples will be more work (probably for more people)
than adding features which are known only to recent {compiler id, version}
tuples.
I expect that if the topic is merged, there will be an initial period of
time where C++11 and C++14 features are added, but I don't know if anyone
will want to record features of old or ancient compilers like partial
specicialization. There may be a long tail of things like that though.
Am I over-thinking this?
Do we need to require some kind of maintenance commitment from people who
want to add the first feature for a {compiler id, version} tuple, like is
currently required for adding new modules?
4) All available features use-case
Something that most projects (Qt, llvm, etc) want to have in their
buildsystem is 'Use the most features available from the compiler the user
is using'.
Qt does this with 'CONFIG += c++11' (I guess they'll add 'CONFIG += c++14'
eventually too), and LLVM uses similar CMake options. Then variadic
templates, the override keyword etc are used conditionally.
I added a prototype untested commit to my topic to use the flags for the
highest standard version available if the compiler doesn't support the
standard version specified. Users could use this together with a header
generated by write_compiler_detection_header.
Is it a use-case we want to support with this interface with CMake?
Thanks,
Steve.
More information about the cmake-developers
mailing list