[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