From 1043c00137adfe8ef61937f15078ccc448f3437c Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Tue, 23 Apr 2024 11:00:46 -0500 Subject: [PATCH] SCons: Detect msvc compiler version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • C standard now passed on msvc if the version is supported --- SConstruct | 72 ++++++++++++++++++++++++++++++++---------------------- methods.py | 21 +++++++++++++--- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/SConstruct b/SConstruct index 5566770148b..33e072b27fa 100644 --- a/SConstruct +++ b/SConstruct @@ -640,25 +640,18 @@ if env.dev_build: print("NOTE: Developer build, with debug optimization level and debug symbols (unless overridden).") # Enforce our minimal compiler version requirements -cc_version = methods.get_compiler_version(env) or { - "major": None, - "minor": None, - "patch": None, - "metadata1": None, - "metadata2": None, - "date": None, -} -cc_version_major = int(cc_version["major"] or -1) -cc_version_minor = int(cc_version["minor"] or -1) -cc_version_metadata1 = cc_version["metadata1"] or "" +cc_version = methods.get_compiler_version(env) +cc_version_major = cc_version["major"] +cc_version_minor = cc_version["minor"] +cc_version_metadata1 = cc_version["metadata1"] -if methods.using_gcc(env): - if cc_version_major == -1: - print_warning( - "Couldn't detect compiler version, skipping version checks. " - "Build may fail if the compiler doesn't support C++17 fully." - ) - elif cc_version_major < 9: +if cc_version_major == -1: + print_warning( + "Couldn't detect compiler version, skipping version checks. " + "Build may fail if the compiler doesn't support C++17 fully." + ) +elif methods.using_gcc(env): + if cc_version_major < 9: print_error( "Detected GCC version older than 9, which does not fully support " "C++17, or has bugs when compiling Godot. Supported versions are 9 " @@ -678,17 +671,12 @@ if methods.using_gcc(env): print_warning("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") env["debug_paths_relative"] = False elif methods.using_clang(env): - if cc_version_major == -1: - print_warning( - "Couldn't detect compiler version, skipping version checks. " - "Build may fail if the compiler doesn't support C++17 fully." - ) # Apple LLVM versions differ from upstream LLVM version \o/, compare # in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions - elif env["platform"] == "macos" or env["platform"] == "ios": + if env["platform"] == "macos" or env["platform"] == "ios": vanilla = methods.is_vanilla_clang(env) if vanilla and cc_version_major < 6: - print_warning( + print_error( "Detected Clang version older than 6, which does not fully support " "C++17. Supported versions are Clang 6 and later." ) @@ -713,6 +701,28 @@ elif methods.using_clang(env): if env["debug_paths_relative"] and cc_version_major < 10: print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") env["debug_paths_relative"] = False +elif env.msvc: + # Ensure latest minor builds of Visual Studio 2017/2019. + # https://github.com/godotengine/godot/pull/94995#issuecomment-2336464574 + if cc_version_major == 16 and cc_version_minor < 11: + print_error( + "Detected Visual Studio 2019 version older than 16.11, which has bugs " + "when compiling Godot. Use a newer VS2019 version, or VS2022." + ) + Exit(255) + if cc_version_major == 15 and cc_version_minor < 9: + print_error( + "Detected Visual Studio 2017 version older than 15.9, which has bugs " + "when compiling Godot. Use a newer VS2017 version, or VS2019/VS2022." + ) + Exit(255) + if cc_version_major < 15: + print_error( + "Detected Visual Studio 2015 or earlier, which is unsupported in Godot. " + "Supported versions are Visual Studio 2017 and later." + ) + Exit(255) + # Set optimize and debug_symbols flags. # "custom" means do nothing and let users set their own optimization flags. @@ -790,13 +800,17 @@ if env["lto"] != "none": # This needs to come after `configure`, otherwise we don't have env.msvc. if not env.msvc: # Specifying GNU extensions support explicitly, which are supported by - # both GCC and Clang. Both currently default to gnu11 and gnu++14. + # both GCC and Clang. Both currently default to gnu11 and gnu++17. env.Prepend(CFLAGS=["-std=gnu11"]) env.Prepend(CXXFLAGS=["-std=gnu++17"]) else: - # MSVC doesn't have clear C standard support, /std only covers C++. - # We apply it to CCFLAGS (both C and C++ code) in case it impacts C features. - env.Prepend(CCFLAGS=["/std:c++17"]) + # MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all + # of our supported VS2019 & VS2022 versions; VS2017 will only pass the C++ standard. + env.Prepend(CXXFLAGS=["/std:c++17"]) + if cc_version_major < 16: + print_warning("Visual Studio 2017 cannot specify a C-Standard.") + else: + env.Prepend(CFLAGS=["/std:c11"]) # MSVC is non-conforming with the C++ standard by default, so we enable more conformance. # Note that this is still not complete conformance, as certain Windows-related headers # don't compile under complete conformance. diff --git a/methods.py b/methods.py index 3f11d39bd0d..411ce59d9e2 100644 --- a/methods.py +++ b/methods.py @@ -795,9 +795,9 @@ def get_compiler_version(env): "major": -1, "minor": -1, "patch": -1, - "metadata1": None, - "metadata2": None, - "date": None, + "metadata1": "", + "metadata2": "", + "date": "", "apple_major": -1, "apple_minor": -1, "apple_patch1": -1, @@ -806,7 +806,20 @@ def get_compiler_version(env): } if env.msvc and not using_clang(env): - # TODO: Implement for MSVC + try: + args = [env["VSWHERE"], "-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"] + version = subprocess.check_output(args, encoding="utf-8").strip() + for line in version.splitlines(): + split = line.split(":", 1) + if split[0] == "catalog_productDisplayVersion": + sem_ver = split[1].split(".") + ret["major"] = int(sem_ver[0]) + ret["minor"] = int(sem_ver[1]) + ret["patch"] = int(sem_ver[2]) + if split[0] == "catalog_buildVersion": + ret["metadata1"] = split[1] + except (subprocess.CalledProcessError, OSError): + print_warning("Couldn't find vswhere to determine compiler version.") return ret # Not using -dumpversion as some GCC distros only return major, and