1from conans.client.build.cppstd_flags import cppstd_flag
2from conans.errors import ConanException
3from conans.util.conan_v2_mode import conan_v2_error
4from conans.util.log import logger
5
6
7def preprocess(settings):
8    _fill_runtime(settings)
9    _check_cppstd(settings)
10
11
12def _check_cppstd(settings):
13    compiler = settings.get_safe("compiler")
14    compiler_version = settings.get_safe("compiler.version")
15    cppstd = settings.get_safe("cppstd")
16    compiler_cppstd = settings.get_safe("compiler.cppstd")
17
18    if not cppstd and not compiler_cppstd:
19        return
20
21    # Checks: one or the other, but not both
22    if cppstd and compiler_cppstd:
23        raise ConanException("Do not use settings 'compiler.cppstd' together with 'cppstd'."
24                             " Use only the former one.")
25
26    conan_v2_error("Setting 'cppstd' is deprecated in favor of 'compiler.cppstd'", cppstd)
27
28    if compiler not in ("gcc", "clang", "apple-clang", "Visual Studio"):
29        return
30
31    # Check that we have a flag available for that value of the C++ Standard
32    def check_flag_available(values_range, value, setting_id):
33        available = [v for v in values_range if cppstd_flag(compiler, compiler_version, v)]
34        if str(value) not in available:
35            raise ConanException("The specified '%s=%s' is not available "
36                                 "for '%s %s'. Possible values are %s'" % (setting_id,
37                                                                           value,
38                                                                           compiler,
39                                                                           compiler_version,
40                                                                           available))
41
42    if cppstd:
43        check_flag_available(settings.cppstd.values_range, cppstd, "cppstd")
44    else:
45        check_flag_available(settings.compiler.cppstd.values_range,
46                             compiler_cppstd, "compiler.cppstd")
47
48
49def _fill_runtime(settings):
50    try:
51        if settings.compiler == "Visual Studio":
52            if settings.get_safe("compiler.runtime") is None:
53                runtime = "MDd" if settings.get_safe("build_type") == "Debug" else "MD"
54                settings.compiler.runtime = runtime
55                msg = "Setting 'compiler.runtime' not declared, automatically adjusted to '%s'"
56                logger.info(msg % runtime)
57        elif settings.compiler == "intel" and settings.get_safe("compiler.base") == "Visual Studio":
58            if settings.get_safe("compiler.base.runtime") is None:
59                runtime = "MDd" if settings.get_safe("build_type") == "Debug" else "MD"
60                settings.compiler.base.runtime = runtime
61                msg = "Setting 'compiler.base.runtime' not declared, automatically adjusted to '%s'"
62                logger.info(msg % runtime)
63        elif settings.compiler == "msvc":
64            if settings.get_safe("compiler.runtime_type") is None:
65                runtime = "Debug" if settings.get_safe("build_type") == "Debug" else "Release"
66                settings.compiler.runtime_type = runtime
67    except Exception:  # If the settings structure doesn't match these general
68        # asumptions, like unexistant runtime
69        pass
70