Fix C++ standard detection

We cannot use a generator expression in an if statement, it does not
work. Instead, we could inspect the CMAKE_C/CXX_COMPILE_FEATURES list,
but unfortunately that's not reliable. For example it detects that ICPC
supports C++17 when in fact that depends on the installed libstdc++.
Therefore this patch revives our own configure tests.

Change-Id: Ic3bc5762fbe81837722523e3881ac16e84628519
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Simon Hausmann 2019-10-17 10:49:44 +02:00
parent 4df389eb4f
commit 2fa23e46c0
3 changed files with 78 additions and 17 deletions

View File

@ -472,7 +472,7 @@ function(qt_feature_copy_global_config_features_to_core target)
endfunction() endfunction()
function(qt_config_compile_test name) function(qt_config_compile_test name)
cmake_parse_arguments(arg "" "LABEL;PROJECT_PATH" "LIBRARIES;CODE" ${ARGN}) cmake_parse_arguments(arg "" "LABEL;PROJECT_PATH;C_STANDARD;CXX_STANDARD" "LIBRARIES;CODE" ${ARGN})
if(arg_PROJECT_PATH) if(arg_PROJECT_PATH)
message(STATUS "Performing Test ${arg_LABEL}") message(STATUS "Performing Test ${arg_LABEL}")
@ -499,10 +499,24 @@ function(qt_config_compile_test name)
endforeach() endforeach()
if(NOT DEFINED HAVE_${name}) if(NOT DEFINED HAVE_${name})
set(_save_CMAKE_C_STANDARD "${CMAKE_C_STANDARD}")
set(_save_CMAKE_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
if(arg_C_STANDARD)
set(CMAKE_C_STANDARD "${arg_C_STANDARD}")
endif()
if(arg_CXX_STANDARD)
set(CMAKE_CXX_STANDARD "${arg_CXX_STANDARD}")
endif()
set(_save_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") set(_save_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
set(CMAKE_REQUIRED_LIBRARIES "${arg_LIBRARIES}") set(CMAKE_REQUIRED_LIBRARIES "${arg_LIBRARIES}")
check_cxx_source_compiles("${arg_UNPARSED_ARGUMENTS} ${arg_CODE}" HAVE_${name}) check_cxx_source_compiles("${arg_UNPARSED_ARGUMENTS} ${arg_CODE}" HAVE_${name})
set(CMAKE_REQUIRED_LIBRARIES "${_save_CMAKE_REQUIRED_LIBRARIES}") set(CMAKE_REQUIRED_LIBRARIES "${_save_CMAKE_REQUIRED_LIBRARIES}")
set(CMAKE_C_STANDARD "${_save_CMAKE_C_STANDARD}")
set(CMAKE_CXX_STANDARD "${_save_CMAKE_CXX_STANDARD}")
endif() endif()
endif() endif()

View File

@ -15,6 +15,54 @@ qt_find_package(Libudev PROVIDED_TARGETS PkgConfig::Libudev)
#### Tests #### Tests
# c++14
qt_config_compile_test(cxx14
LABEL "C++14 support"
"#if __cplusplus > 201103L
// Compiler claims to support C++14, trust it
#else
# error __cplusplus must be > 201103L (the value of C++11)
#endif
int main(int argc, char **argv)
{
(void)argc; (void)argv;
/* BEGIN TEST: */
/* END TEST: */
return 0;
}
"
CXX_STANDARD 14
)
# c++17
qt_config_compile_test(cxx17
LABEL "C++17 support"
"#if __cplusplus > 201402L
// Compiler claims to support C++17, trust it
#else
# error __cplusplus must be > 201402L (the value for C++14)
#endif
#include <map> // https://bugs.llvm.org//show_bug.cgi?id=33117
#include <variant>
int main(int argc, char **argv)
{
(void)argc; (void)argv;
/* BEGIN TEST: */
std::variant<int> v(42);
int i = std::get<int>(v);
std::visit([](const auto &) { return 1; }, v);
/* END TEST: */
return 0;
}
"
CXX_STANDARD 17
)
# c++2a # c++2a
qt_config_compile_test(cxx2a qt_config_compile_test(cxx2a
LABEL "C++2a support" LABEL "C++2a support"
@ -33,7 +81,8 @@ int main(int argc, char **argv)
/* END TEST: */ /* END TEST: */
return 0; return 0;
} }
"# FIXME: qmake: CONFIG += c++11 c++14 c++17 c++2a "
CXX_STANDARD 20
) )
# precompile_header # precompile_header
@ -294,11 +343,11 @@ qt_feature("cxx11" PUBLIC
) )
qt_feature("cxx14" PUBLIC qt_feature("cxx14" PUBLIC
LABEL "C++14" LABEL "C++14"
CONDITION QT_FEATURE_cxx11 AND $<COMPILE_FEATURES:cxx_std_14> CONDITION QT_FEATURE_cxx11 AND TEST_cxx14
) )
qt_feature("cxx17" PUBLIC qt_feature("cxx17" PUBLIC
LABEL "C++17" LABEL "C++17"
CONDITION QT_FEATURE_cxx14 AND $<COMPILE_FEATURES:cxx_std_17> CONDITION QT_FEATURE_cxx14 AND TEST_cxx17
) )
qt_feature("cxx1z" PUBLIC qt_feature("cxx1z" PUBLIC
LABEL "C++17" LABEL "C++17"

View File

@ -54,13 +54,8 @@ class LibraryMapping:
def map_tests(test: str) -> Optional[str]: def map_tests(test: str) -> Optional[str]:
testmap = { testmap = {
"c++11": "$<COMPILE_FEATURES:cxx_std_11>", "c99": "c_std_99 IN_LIST CMAKE_C_COMPILE_FEATURES",
"c++14": "$<COMPILE_FEATURES:cxx_std_14>", "c11": "c_std_11 IN_LIST CMAKE_C_COMPILE_FEATURES",
"c++1z": "$<COMPILE_FEATURES:cxx_std_17>",
"c++17": "$<COMPILE_FEATURES:cxx_std_17>",
"c++20": "$<COMPILE_FEATURES:cxx_std_20>",
"c99": "$<COMPILE_FEATURES:c_std_99>",
"c11": "$<COMPILE_FEATURES:c_std_11>",
"x86SimdAlways": "ON", # FIXME: Make this actually do a compile test. "x86SimdAlways": "ON", # FIXME: Make this actually do a compile test.
"aesni": "TEST_subarch_aes", "aesni": "TEST_subarch_aes",
"avx": "TEST_subarch_avx", "avx": "TEST_subarch_avx",
@ -489,12 +484,6 @@ def parseInput(ctx, sinput, data, cm_fh):
# }, # },
def parseTest(ctx, test, data, cm_fh): def parseTest(ctx, test, data, cm_fh):
skip_tests = { skip_tests = {
"c++11",
"c++14",
"c++17",
"c++20",
"c++1y",
"c++1z",
"c11", "c11",
"c99", "c99",
"gc_binaries", "gc_binaries",
@ -572,6 +561,7 @@ endif()
sourceCode = sourceCode.replace('"', '\\"') sourceCode = sourceCode.replace('"', '\\"')
librariesCmakeName = "" librariesCmakeName = ""
languageStandard = ""
qmakeFixme = "" qmakeFixme = ""
cm_fh.write(f"# {test}\n") cm_fh.write(f"# {test}\n")
@ -594,6 +584,12 @@ endif()
elif details["qmake"] == "CONFIG += c++11": elif details["qmake"] == "CONFIG += c++11":
# do nothing we're always in c++11 mode # do nothing we're always in c++11 mode
pass pass
elif details["qmake"] == "CONFIG += c++11 c++14":
languageStandard = "CXX_STANDARD 14"
elif details["qmake"] == "CONFIG += c++11 c++14 c++17":
languageStandard = "CXX_STANDARD 17"
elif details["qmake"] == "CONFIG += c++11 c++14 c++17 c++2a":
languageStandard = "CXX_STANDARD 20"
else: else:
qmakeFixme = f"# FIXME: qmake: {details['qmake']}\n" qmakeFixme = f"# FIXME: qmake: {details['qmake']}\n"
@ -614,6 +610,8 @@ endif()
cm_fh.write('"' + sourceCode + '"') cm_fh.write('"' + sourceCode + '"')
if qmakeFixme != "": if qmakeFixme != "":
cm_fh.write(qmakeFixme) cm_fh.write(qmakeFixme)
if languageStandard != "":
cm_fh.write(f"\n {languageStandard}\n")
cm_fh.write(")\n\n") cm_fh.write(")\n\n")
elif data["type"] == "libclang": elif data["type"] == "libclang":