Stephen Kelly
2014-05-31 13:17:59 UTC
Hi,
Here is a dump of some notes I have accumulated regarding compile features.
1) Extensions requiring compile options
The target_compile_features interface is designed to allow use with compiler
extensions such as gnu_cxx_typeof and msvc_cxx_sealed. The extensions
discussed so far have been extensions which happen to depend on 'big switch'
options like /Za and -std=gnu++11 vs -std=c++11.
However, there are other cases.
Clang supports msvc_cxx_sealed on all platforms if the -fms-extensions
option is passed:
$ clang++ -fms-extensions main.cpp
main.cpp:353:10: warning: 'sealed' keyword is a Microsoft extension [-
Wmicrosoft]
struct A sealed {};
^
1 warning generated.
It might make sense to allow passing additional options for compiler
extensions which need them. Eg
+set(_cmake_feature_test_msvc_cxx_sealed "${Clang34}")
+set(_cmake_feature_test_msvc_cxx_sealed_compile_option "-fms-extensions")
The patch at
https://www.mail-archive.com/cfe-***@cs.uiuc.edu/msg97160.html
requires -fplan9-extensions. I don't know if it enables any relevant
features, but I note it for completeness.
2) Incompatible features
Two features known to CMake might be incompatible.
For example, the cxx_auto_type feature (c++11) conflicts with a
cxx_auto_storage_type_specifier (c++98). In this case, it is a non-issue
because variables have automatic storage duration by default anyway, and the
feature of 'auto as a storage type specifier' is deprecated in c++11 partly
due to non-use, so no CMake user is likely to have a use for such a thing.
Another example is exported templates, which are removed from c++11:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf
(Why we can't afford ``export``)
which may conflict with the cxx_extern_templates feature (c++11). However,
only EDG implemented the exported templates feature, and it was only made
available for use with the Comeau compiler. I don't think it makes sense to
add it as a known feature to CMake.
So for now, I don't think incompatible features is an issue, but it may
become one in the future, and the CMake implementation would need some way
to handle that.
Another way that incompatible features could arise is if a compiler supports
a msvc_cxx_foo feature and a gnu_cxx_bar feature which may not be used
together because of compile options which may not be used together.
3) Extensions which may become standard
GNU 4.9 supports explicit template parameter syntax for generic lambdas:
https://gcc.gnu.org/gcc-4.9/changes.html
https://gcc.gnu.org/ml/gcc/2009-08/msg00174.html
int main()
{
// a functional object that will add two objects
auto add = [] (auto a, auto b) { return a + b; };
// Allowed by GNU 4.9 with -std=gnu++1y (and -std=c++1y)
// Adds only like-type objects
auto add_constrained = [] <typename T> (T a, T b) { return a + b; };
// Variadics not allowed:
// auto num_args = [] <typename T...> (T... t) { return sizeof(t...); };
int ret;
ret = add(3, -3);
ret = add_constrained(3, -3);
ret = add(3.0, -3);
// error: no match for call to ‘(main()::<lambda(T, T)>) (double, int)’
// ret = add_constrained(3.0, -3);
return ret;
}
Something like this might be added to the standard together with Concepts in
c++17, as per section 5.4 of
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf
So, today we might add a gnu_cxx_lambda_template_parameters feature to CMake
supported by GNU 4.9, but we might add a cxx_lambda_template_parameters in
the future which might subsume or might conflict with the gnu_ variant (if
standard behavior is somewhat different).
I don't see any independent problem with this, but I just thought I'd point
it out. It might lead to 'conflicting features', or we might decide it is an
error to specify both gnu_cxx_lambda_template_parameters and
cxx_lambda_template_parameters in that case.
See also cxx_inline_namespaces and GNU strong namespaces:
https://gcc.gnu.org/onlinedocs/gcc/Namespace-Association.html#Namespace-Association
See also the Modules feature, which is going toward standardization and
currently requires a compile option in the Clang implementation
http://clang.llvm.org/docs/Modules.html
Also, I think GNU allows the c_restrict feature (C11) in c++ mode, which may
become standardized in c++ in the future.
4) WG 21 standing document 6 (study group 10)
Just pointing this out for completeness:
https://isocpp.org/files/papers/n4030.htm
Clang and CMake generally refer to 'cxx' instead of 'cpp', and I think it's
ok for the features known to CMake to continue to have cxx_ prefixes.
The SD6 document might be a useful reference for naming things.
Note though that there are some essential differences. Those recommendations
use a single macro for the c++11 constexpr feature and for the c++14 relaxed
constexpr feature
__cpp_constexpr = 200704 (cxx_constexpr)
__cpp_constexpr = 201304 (cxx_relaxed_constexpr)
As the CMake features are not differentiated in that way, some differences
compared to that document will remain necessary.
5) Disabling features, aka 'Enabling' non-features
I could imagine adding a feature to control whether exceptions are allowed
in compiled code. With GNU there is a -fno-exceptions option which may be
passed to error on use of ``throw``. I believe with MSVC has something
similar.
Would a cxx_no_exceptions feature be a reasonable fit into the compile
features concept, with the corresponding compile option?
Something similar could be said for rtti.
6) target_compile_features as a universal feature interface
If compile features are to be linked in some way with compile options, the
idea of using it for cxx_position_independent_code arises. We already have
an interface in CMake for that, so I'm just listing this for completeness,
and for consideration of how future similar interfaces should be handled. We
might be able to think about that a bit now.
For example cxx_sse2 and cxx_avx features could be added which add
/arch:SSE2 or /arch:AVX for MSVC, and -msse2 or -mavx for GNU
http://stackoverflow.com/questions/661338/sse-sse2-and-sse3-for-gnu-c
This isn't something I think should definitely be done, but is something to
think about.
7) Extending the compiler feature support matrix.
I'm finished with extending the feature support matrix for now.
MSVC features are obviously missing, but someone else will have to add and
maintain those, and try them out to find any issues similar to those
recorded in comments for the GNU and Clang compilers such as discrepancy
between documented and actual features, broken features etc.
Extending the feature matrix to past releases also should be done carefully
(if at all). The c++11 standard evolved over almost a decade, things changed
in that time, and compilers implemented intermediate versions in that time.
For example, there are many versions of 'rvalue references' and MSVC does
not yet implement the accepted version
http://msdn.microsoft.com/en-us/library/hh567368.aspx#rvref
In this case, 'rvalue references v3' has a separate feature in CMake
(cxx_defaulted_move_initializers), so it is likely not an issue, but someone
extending support to that compiler or old releases of it, or old releases of
other compilers would need to check things like that.
http://rrsd.com/blincubator.com/bi_library/afio/
"and auto-generate implicit move constructors when all member data types
have move constructors (known in Microsoft as rvalue references v3.0)"
As well as consider whether 'pure bugs' in compiler releases are severe
enough to disable the feature for that compiler. This is mostly an issue for
older Clang/GNU releases
http://milianw.de/blog/c11-platform-support#comment-1401
and for MSVC releases (I recorded a few serious bugs at
https://gitorious.org/cmake/steveires-cmake/source/0156b7f4:Modules/Compiler/MSVC-CXX-FeatureTests.cmake
)
We previously agreed to treat documented features as available, but as the
compiler feature matrix is currently small, this decision has not yet had to
be made concrete, and could be re-visited if someone had a need to do so.
8) Standard library features
It would be possible to somewhat-selectively record features of the standard
library by including a stdlib header and check features of that by version.
http://thread.gmane.org/gmane.comp.compilers.clang.devel/22916/focus=22917
The GLIBCXX macro is not useful for version checking, but the compiler
macros could possibly be tested instead in that case because of tight-
coupling
http://stackoverflow.com/a/11925468/2428389
Standard library features are in-scope for the SD6 feature testing
https://isocpp.org/files/papers/n4030.htm
and as far as I know, it is in scope for Boost.Config too.
I'm not convinced they should be in scope for CMake however. There would be
too many features drowning out other features (for each class/algorithm?,
c++14 additions of constexpr
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3470.html
etc). We could consider using the SD6 macros for std lib feature detection,
but as those macros are designed to be defined in the header that contains
the feature, we would end up having to compile a header which includes a
large amount of std lib headers at the beginning of CMake time to record the
features, which does not seem worth it.
So I'm not planning to investigate that further.
Thanks,
Steve.
Here is a dump of some notes I have accumulated regarding compile features.
1) Extensions requiring compile options
The target_compile_features interface is designed to allow use with compiler
extensions such as gnu_cxx_typeof and msvc_cxx_sealed. The extensions
discussed so far have been extensions which happen to depend on 'big switch'
options like /Za and -std=gnu++11 vs -std=c++11.
However, there are other cases.
Clang supports msvc_cxx_sealed on all platforms if the -fms-extensions
option is passed:
$ clang++ -fms-extensions main.cpp
main.cpp:353:10: warning: 'sealed' keyword is a Microsoft extension [-
Wmicrosoft]
struct A sealed {};
^
1 warning generated.
It might make sense to allow passing additional options for compiler
extensions which need them. Eg
+set(_cmake_feature_test_msvc_cxx_sealed "${Clang34}")
+set(_cmake_feature_test_msvc_cxx_sealed_compile_option "-fms-extensions")
The patch at
https://www.mail-archive.com/cfe-***@cs.uiuc.edu/msg97160.html
requires -fplan9-extensions. I don't know if it enables any relevant
features, but I note it for completeness.
2) Incompatible features
Two features known to CMake might be incompatible.
For example, the cxx_auto_type feature (c++11) conflicts with a
cxx_auto_storage_type_specifier (c++98). In this case, it is a non-issue
because variables have automatic storage duration by default anyway, and the
feature of 'auto as a storage type specifier' is deprecated in c++11 partly
due to non-use, so no CMake user is likely to have a use for such a thing.
Another example is exported templates, which are removed from c++11:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf
(Why we can't afford ``export``)
which may conflict with the cxx_extern_templates feature (c++11). However,
only EDG implemented the exported templates feature, and it was only made
available for use with the Comeau compiler. I don't think it makes sense to
add it as a known feature to CMake.
So for now, I don't think incompatible features is an issue, but it may
become one in the future, and the CMake implementation would need some way
to handle that.
Another way that incompatible features could arise is if a compiler supports
a msvc_cxx_foo feature and a gnu_cxx_bar feature which may not be used
together because of compile options which may not be used together.
3) Extensions which may become standard
GNU 4.9 supports explicit template parameter syntax for generic lambdas:
https://gcc.gnu.org/gcc-4.9/changes.html
https://gcc.gnu.org/ml/gcc/2009-08/msg00174.html
int main()
{
// a functional object that will add two objects
auto add = [] (auto a, auto b) { return a + b; };
// Allowed by GNU 4.9 with -std=gnu++1y (and -std=c++1y)
// Adds only like-type objects
auto add_constrained = [] <typename T> (T a, T b) { return a + b; };
// Variadics not allowed:
// auto num_args = [] <typename T...> (T... t) { return sizeof(t...); };
int ret;
ret = add(3, -3);
ret = add_constrained(3, -3);
ret = add(3.0, -3);
// error: no match for call to ‘(main()::<lambda(T, T)>) (double, int)’
// ret = add_constrained(3.0, -3);
return ret;
}
Something like this might be added to the standard together with Concepts in
c++17, as per section 5.4 of
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf
So, today we might add a gnu_cxx_lambda_template_parameters feature to CMake
supported by GNU 4.9, but we might add a cxx_lambda_template_parameters in
the future which might subsume or might conflict with the gnu_ variant (if
standard behavior is somewhat different).
I don't see any independent problem with this, but I just thought I'd point
it out. It might lead to 'conflicting features', or we might decide it is an
error to specify both gnu_cxx_lambda_template_parameters and
cxx_lambda_template_parameters in that case.
See also cxx_inline_namespaces and GNU strong namespaces:
https://gcc.gnu.org/onlinedocs/gcc/Namespace-Association.html#Namespace-Association
See also the Modules feature, which is going toward standardization and
currently requires a compile option in the Clang implementation
http://clang.llvm.org/docs/Modules.html
Also, I think GNU allows the c_restrict feature (C11) in c++ mode, which may
become standardized in c++ in the future.
4) WG 21 standing document 6 (study group 10)
Just pointing this out for completeness:
https://isocpp.org/files/papers/n4030.htm
Clang and CMake generally refer to 'cxx' instead of 'cpp', and I think it's
ok for the features known to CMake to continue to have cxx_ prefixes.
The SD6 document might be a useful reference for naming things.
Note though that there are some essential differences. Those recommendations
use a single macro for the c++11 constexpr feature and for the c++14 relaxed
constexpr feature
__cpp_constexpr = 200704 (cxx_constexpr)
__cpp_constexpr = 201304 (cxx_relaxed_constexpr)
As the CMake features are not differentiated in that way, some differences
compared to that document will remain necessary.
5) Disabling features, aka 'Enabling' non-features
I could imagine adding a feature to control whether exceptions are allowed
in compiled code. With GNU there is a -fno-exceptions option which may be
passed to error on use of ``throw``. I believe with MSVC has something
similar.
Would a cxx_no_exceptions feature be a reasonable fit into the compile
features concept, with the corresponding compile option?
Something similar could be said for rtti.
6) target_compile_features as a universal feature interface
If compile features are to be linked in some way with compile options, the
idea of using it for cxx_position_independent_code arises. We already have
an interface in CMake for that, so I'm just listing this for completeness,
and for consideration of how future similar interfaces should be handled. We
might be able to think about that a bit now.
For example cxx_sse2 and cxx_avx features could be added which add
/arch:SSE2 or /arch:AVX for MSVC, and -msse2 or -mavx for GNU
http://stackoverflow.com/questions/661338/sse-sse2-and-sse3-for-gnu-c
This isn't something I think should definitely be done, but is something to
think about.
7) Extending the compiler feature support matrix.
I'm finished with extending the feature support matrix for now.
MSVC features are obviously missing, but someone else will have to add and
maintain those, and try them out to find any issues similar to those
recorded in comments for the GNU and Clang compilers such as discrepancy
between documented and actual features, broken features etc.
Extending the feature matrix to past releases also should be done carefully
(if at all). The c++11 standard evolved over almost a decade, things changed
in that time, and compilers implemented intermediate versions in that time.
For example, there are many versions of 'rvalue references' and MSVC does
not yet implement the accepted version
http://msdn.microsoft.com/en-us/library/hh567368.aspx#rvref
In this case, 'rvalue references v3' has a separate feature in CMake
(cxx_defaulted_move_initializers), so it is likely not an issue, but someone
extending support to that compiler or old releases of it, or old releases of
other compilers would need to check things like that.
http://rrsd.com/blincubator.com/bi_library/afio/
"and auto-generate implicit move constructors when all member data types
have move constructors (known in Microsoft as rvalue references v3.0)"
As well as consider whether 'pure bugs' in compiler releases are severe
enough to disable the feature for that compiler. This is mostly an issue for
older Clang/GNU releases
http://milianw.de/blog/c11-platform-support#comment-1401
and for MSVC releases (I recorded a few serious bugs at
https://gitorious.org/cmake/steveires-cmake/source/0156b7f4:Modules/Compiler/MSVC-CXX-FeatureTests.cmake
)
We previously agreed to treat documented features as available, but as the
compiler feature matrix is currently small, this decision has not yet had to
be made concrete, and could be re-visited if someone had a need to do so.
8) Standard library features
It would be possible to somewhat-selectively record features of the standard
library by including a stdlib header and check features of that by version.
http://thread.gmane.org/gmane.comp.compilers.clang.devel/22916/focus=22917
The GLIBCXX macro is not useful for version checking, but the compiler
macros could possibly be tested instead in that case because of tight-
coupling
http://stackoverflow.com/a/11925468/2428389
Standard library features are in-scope for the SD6 feature testing
https://isocpp.org/files/papers/n4030.htm
and as far as I know, it is in scope for Boost.Config too.
I'm not convinced they should be in scope for CMake however. There would be
too many features drowning out other features (for each class/algorithm?,
c++14 additions of constexpr
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3470.html
etc). We could consider using the SD6 macros for std lib feature detection,
but as those macros are designed to be defined in the header that contains
the feature, we would end up having to compile a header which includes a
large amount of std lib headers at the beginning of CMake time to record the
features, which does not seem worth it.
So I'm not planning to investigate that further.
Thanks,
Steve.