conans/client/build/cppstd_flags.py
import warnings
from conans.errors import ConanException
from conans.model.version import Version
def cppstd_from_settings(settings):
cppstd = settings.get_safe("cppstd")
compiler_cppstd = settings.get_safe("compiler.cppstd")
if not cppstd and not compiler_cppstd:
return None
if cppstd and compiler_cppstd:
# Both should never arrive with a value to build_helpers
warnings.warn("Both settings, 'cppstd' and 'compiler.cppstd', should never arrive"
" with values to build_helpers")
if cppstd != compiler_cppstd:
raise ConanException("Can't decide value for C++ standard, settings mismatch: "
"'cppstd={}', 'compiler.cppstd='".format(cppstd, compiler_cppstd))
return compiler_cppstd or cppstd
def cppstd_flag(compiler, compiler_version, cppstd, compiler_base=None):
if not compiler or not compiler_version or not cppstd:
return ""
cppstd_intel = _cppstd_intel_visualstudio if compiler_base == "Visual Studio" else \
_cppstd_intel_gcc
func = {"gcc": _cppstd_gcc,
"clang": _cppstd_clang,
"apple-clang": _cppstd_apple_clang,
"Visual Studio": _cppstd_visualstudio,
"msvc": _cppstd_msvc,
"intel": cppstd_intel,
"mcst-lcc": _cppstd_mcst_lcc}.get(str(compiler), None)
flag = None
if func:
flag = func(str(compiler_version), str(cppstd))
return flag
def cppstd_flag_new(settings):
compiler = settings.get_safe("compiler")
compiler_version = settings.get_safe("compiler.version")
compiler_base = settings.get_safe("compiler.base")
cppstd = cppstd_from_settings(settings)
return cppstd_flag(compiler, compiler_version, cppstd, compiler_base)
def cppstd_default(settings):
compiler = settings.get_safe("compiler")
compiler_version = settings.get_safe("compiler.version")
compiler_base = settings.get_safe("compiler.base")
intel_cppstd_default = _intel_visual_cppstd_default if compiler_base == "Visual Studio" \
else _intel_gcc_cppstd_default
default = {"gcc": _gcc_cppstd_default(compiler_version),
"clang": _clang_cppstd_default(compiler_version),
"apple-clang": "gnu98", # Confirmed in apple-clang 9.1 with a simple "auto i=1;"; 14.0 still the same
"Visual Studio": _visual_cppstd_default(compiler_version),
"intel": intel_cppstd_default(compiler_version),
"mcst-lcc": _mcst_lcc_cppstd_default(compiler_version)}.get(str(compiler), None)
return default
def _clang_cppstd_default(compiler_version):
if Version(compiler_version) >= "16":
return "gnu17"
# Official docs are wrong, in 6.0 the default is gnu14 to follow gcc's choice
return "gnu98" if Version(compiler_version) < "6" else "gnu14"
def _gcc_cppstd_default(compiler_version):
if Version(compiler_version) >= "11":
return "gnu17"
return "gnu98" if Version(compiler_version) < "6" else "gnu14"
def _visual_cppstd_default(compiler_version):
if Version(compiler_version) >= "14": # VS 2015 update 3 only
return "14"
return None
def _intel_visual_cppstd_default(_):
return None
def _intel_gcc_cppstd_default(_):
return "gnu98"
def _mcst_lcc_cppstd_default(compiler_version):
return "gnu14" if Version(compiler_version) >= "1.24" else "gnu98"
def _cppstd_visualstudio(visual_version, cppstd):
# https://docs.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version
v14 = None
v17 = None
v20 = None
v23 = None
if Version(visual_version) >= "14":
v14 = "c++14"
v17 = "c++latest"
if Version(visual_version) >= "15":
v17 = "c++17"
v20 = "c++latest"
if Version(visual_version) >= "17":
v20 = "c++20"
v23 = "c++latest"
flag = {"14": v14, "17": v17, "20": v20, "23": v23}.get(str(cppstd), None)
return "/std:%s" % flag if flag else None
def _cppstd_msvc(visual_version, cppstd):
# https://docs.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version
v14 = None
v17 = None
v20 = None
v23 = None
if Version(visual_version) >= "190":
v14 = "c++14"
v17 = "c++latest"
if Version(visual_version) >= "191":
v17 = "c++17"
v20 = "c++latest"
if Version(visual_version) >= "193":
v20 = "c++20"
v23 = "c++latest"
flag = {"14": v14, "17": v17, "20": v20, "23": v23}.get(str(cppstd), None)
return "/std:%s" % flag if flag else None
def _cppstd_apple_clang(clang_version, cppstd):
"""
Inspired in:
https://github.com/Kitware/CMake/blob/master/Modules/Compiler/AppleClang-CXX.cmake
"""
v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = v23 = vgnu23 = None
if Version(clang_version) >= "4.0":
v98 = "c++98"
vgnu98 = "gnu++98"
v11 = "c++11"
vgnu11 = "gnu++11"
if Version(clang_version) >= "6.1":
v14 = "c++14"
vgnu14 = "gnu++14"
elif Version(clang_version) >= "5.1":
v14 = "c++1y"
vgnu14 = "gnu++1y"
# Not confirmed that it didn't work before 9.1 but 1z is still valid, so we are ok
# Note: cmake allows c++17 since version 10.0
if Version(clang_version) >= "9.1":
v17 = "c++17"
vgnu17 = "gnu++17"
elif Version(clang_version) >= "6.1":
v17 = "c++1z"
vgnu17 = "gnu++1z"
if Version(clang_version) >= "13.0":
v20 = "c++20"
vgnu20 = "gnu++20"
elif Version(clang_version) >= "10.0":
v20 = "c++2a"
vgnu20 = "gnu++2a"
if Version(clang_version) >= "13.0":
v23 = "c++2b"
vgnu23 = "gnu++2b"
flag = {"98": v98, "gnu98": vgnu98,
"11": v11, "gnu11": vgnu11,
"14": v14, "gnu14": vgnu14,
"17": v17, "gnu17": vgnu17,
"20": v20, "gnu20": vgnu20,
"23": v23, "gnu23": vgnu23}.get(cppstd, None)
return "-std=%s" % flag if flag else None
def _cppstd_clang(clang_version, cppstd):
"""
Inspired in:
https://github.com/Kitware/CMake/blob/
1fe2dc5ef2a1f262b125a2ba6a85f624ce150dd2/Modules/Compiler/Clang-CXX.cmake
https://clang.llvm.org/cxx_status.html
"""
v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = v23 = vgnu23 = None
if Version(clang_version) >= "2.1":
v98 = "c++98"
vgnu98 = "gnu++98"
if Version(clang_version) >= "3.1":
v11 = "c++11"
vgnu11 = "gnu++11"
elif Version(clang_version) >= "2.1":
v11 = "c++0x"
vgnu11 = "gnu++0x"
if Version(clang_version) >= "3.5":
v14 = "c++14"
vgnu14 = "gnu++14"
elif Version(clang_version) >= "3.4":
v14 = "c++1y"
vgnu14 = "gnu++1y"
if Version(clang_version) >= "5":
v17 = "c++17"
vgnu17 = "gnu++17"
elif Version(clang_version) >= "3.5":
v17 = "c++1z"
vgnu17 = "gnu++1z"
if Version(clang_version) >= "6":
v20 = "c++2a"
vgnu20 = "gnu++2a"
if Version(clang_version) >= "12":
v20 = "c++20"
vgnu20 = "gnu++20"
v23 = "c++2b"
vgnu23 = "gnu++2b"
flag = {"98": v98, "gnu98": vgnu98,
"11": v11, "gnu11": vgnu11,
"14": v14, "gnu14": vgnu14,
"17": v17, "gnu17": vgnu17,
"20": v20, "gnu20": vgnu20,
"23": v23, "gnu23": vgnu23}.get(cppstd, None)
return "-std=%s" % flag if flag else None
def _cppstd_gcc(gcc_version, cppstd):
"""https://github.com/Kitware/CMake/blob/master/Modules/Compiler/GNU-CXX.cmake"""
# https://gcc.gnu.org/projects/cxx-status.html
v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = v23 = vgnu23 = None
if Version(gcc_version) >= "3.4":
v98 = "c++98"
vgnu98 = "gnu++98"
if Version(gcc_version) >= "4.7":
v11 = "c++11"
vgnu11 = "gnu++11"
elif Version(gcc_version) >= "4.3":
v11 = "c++0x"
vgnu11 = "gnu++0x"
if Version(gcc_version) >= "4.9":
v14 = "c++14"
vgnu14 = "gnu++14"
elif Version(gcc_version) >= "4.8":
v14 = "c++1y"
vgnu14 = "gnu++1y"
if Version(gcc_version) >= "5":
v17 = "c++1z"
vgnu17 = "gnu++1z"
if Version(gcc_version) >= "5.2": # Not sure if even in 5.1 gnu17 is valid, but gnu1z is
v17 = "c++17"
vgnu17 = "gnu++17"
if Version(gcc_version) >= "8":
v20 = "c++2a"
vgnu20 = "gnu++2a"
if Version(gcc_version) >= "11":
v23 = "c++2b"
vgnu23 = "gnu++2b"
flag = {"98": v98, "gnu98": vgnu98,
"11": v11, "gnu11": vgnu11,
"14": v14, "gnu14": vgnu14,
"17": v17, "gnu17": vgnu17,
"20": v20, "gnu20": vgnu20,
"23": v23, "gnu23": vgnu23}.get(cppstd)
return "-std=%s" % flag if flag else None
def _cppstd_intel_common(intel_version, cppstd, vgnu98, vgnu0x):
# https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-std-qstd
# https://software.intel.com/en-us/articles/intel-cpp-compiler-release-notes
# NOTE: there are only gnu++98 and gnu++0x, and only for Linux/macOS
v98 = v11 = v14 = v17 = v20 = None
vgnu11 = vgnu14 = vgnu17 = vgnu20 = None
if Version(intel_version) >= "12":
v11 = "c++0x"
vgnu11 = vgnu0x
if Version(intel_version) >= "14":
v11 = "c++11"
vgnu11 = vgnu0x
if Version(intel_version) >= "16":
v14 = "c++14"
if Version(intel_version) >= "18":
v17 = "c++17"
if Version(intel_version) >= "19.1":
v20 = "c++20"
return {"98": v98, "gnu98": vgnu98,
"11": v11, "gnu11": vgnu11,
"14": v14, "gnu14": vgnu14,
"17": v17, "gnu17": vgnu17,
"20": v20, "gnu20": vgnu20}.get(cppstd)
def _cppstd_intel_gcc(intel_version, cppstd):
flag = _cppstd_intel_common(intel_version, cppstd, "gnu++98", "gnu++0x")
return "-std=%s" % flag if flag else None
def _cppstd_intel_visualstudio(intel_version, cppstd):
flag = _cppstd_intel_common(intel_version, cppstd, None, None)
return "/Qstd=%s" % flag if flag else None
def _cppstd_mcst_lcc(mcst_lcc_version, cppstd):
v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = None
if Version(mcst_lcc_version) >= "1.21":
v11 = "c++11"
vgnu11 = "gnu++11"
v14 = "c++14"
vgnu14 = "gnu++14"
if Version(mcst_lcc_version) >= "1.24":
v17 = "c++17"
vgnu17 = "gnu++17"
if Version(mcst_lcc_version) >= "1.25":
v20 = "c++2a"
vgnu20 = "gnu++2a"
flag = {"98": "c++98", "gnu98": "gnu++98",
"03": "c++03", "gnu03": "gnu++03",
"11": v11, "gnu11": vgnu11,
"14": v14, "gnu14": vgnu14,
"17": v17, "gnu17": vgnu17,
"20": v20, "gnu20": vgnu20}.get(cppstd)
return "-std=%s" % flag if flag else None