Skip to content

Commit d6c0509

Browse files
committed
Merge pull request godotengine#91069 from Repiteo/scons/msvc-detect-compiler
SCons: Detect MSVC compiler version
2 parents 285ebed + 1043c00 commit d6c0509

File tree

2 files changed

+61
-34
lines changed

2 files changed

+61
-34
lines changed

SConstruct

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -640,25 +640,18 @@ if env.dev_build:
640640
print("NOTE: Developer build, with debug optimization level and debug symbols (unless overridden).")
641641

642642
# Enforce our minimal compiler version requirements
643-
cc_version = methods.get_compiler_version(env) or {
644-
"major": None,
645-
"minor": None,
646-
"patch": None,
647-
"metadata1": None,
648-
"metadata2": None,
649-
"date": None,
650-
}
651-
cc_version_major = int(cc_version["major"] or -1)
652-
cc_version_minor = int(cc_version["minor"] or -1)
653-
cc_version_metadata1 = cc_version["metadata1"] or ""
654-
655-
if methods.using_gcc(env):
656-
if cc_version_major == -1:
657-
print_warning(
658-
"Couldn't detect compiler version, skipping version checks. "
659-
"Build may fail if the compiler doesn't support C++17 fully."
660-
)
661-
elif cc_version_major < 9:
643+
cc_version = methods.get_compiler_version(env)
644+
cc_version_major = cc_version["major"]
645+
cc_version_minor = cc_version["minor"]
646+
cc_version_metadata1 = cc_version["metadata1"]
647+
648+
if cc_version_major == -1:
649+
print_warning(
650+
"Couldn't detect compiler version, skipping version checks. "
651+
"Build may fail if the compiler doesn't support C++17 fully."
652+
)
653+
elif methods.using_gcc(env):
654+
if cc_version_major < 9:
662655
print_error(
663656
"Detected GCC version older than 9, which does not fully support "
664657
"C++17, or has bugs when compiling Godot. Supported versions are 9 "
@@ -678,17 +671,12 @@ if methods.using_gcc(env):
678671
print_warning("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
679672
env["debug_paths_relative"] = False
680673
elif methods.using_clang(env):
681-
if cc_version_major == -1:
682-
print_warning(
683-
"Couldn't detect compiler version, skipping version checks. "
684-
"Build may fail if the compiler doesn't support C++17 fully."
685-
)
686674
# Apple LLVM versions differ from upstream LLVM version \o/, compare
687675
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
688-
elif env["platform"] == "macos" or env["platform"] == "ios":
676+
if env["platform"] == "macos" or env["platform"] == "ios":
689677
vanilla = methods.is_vanilla_clang(env)
690678
if vanilla and cc_version_major < 6:
691-
print_warning(
679+
print_error(
692680
"Detected Clang version older than 6, which does not fully support "
693681
"C++17. Supported versions are Clang 6 and later."
694682
)
@@ -713,6 +701,28 @@ elif methods.using_clang(env):
713701
if env["debug_paths_relative"] and cc_version_major < 10:
714702
print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
715703
env["debug_paths_relative"] = False
704+
elif env.msvc:
705+
# Ensure latest minor builds of Visual Studio 2017/2019.
706+
# https://github.com/godotengine/godot/pull/94995#issuecomment-2336464574
707+
if cc_version_major == 16 and cc_version_minor < 11:
708+
print_error(
709+
"Detected Visual Studio 2019 version older than 16.11, which has bugs "
710+
"when compiling Godot. Use a newer VS2019 version, or VS2022."
711+
)
712+
Exit(255)
713+
if cc_version_major == 15 and cc_version_minor < 9:
714+
print_error(
715+
"Detected Visual Studio 2017 version older than 15.9, which has bugs "
716+
"when compiling Godot. Use a newer VS2017 version, or VS2019/VS2022."
717+
)
718+
Exit(255)
719+
if cc_version_major < 15:
720+
print_error(
721+
"Detected Visual Studio 2015 or earlier, which is unsupported in Godot. "
722+
"Supported versions are Visual Studio 2017 and later."
723+
)
724+
Exit(255)
725+
716726

717727
# Set optimize and debug_symbols flags.
718728
# "custom" means do nothing and let users set their own optimization flags.
@@ -790,13 +800,17 @@ if env["lto"] != "none":
790800
# This needs to come after `configure`, otherwise we don't have env.msvc.
791801
if not env.msvc:
792802
# Specifying GNU extensions support explicitly, which are supported by
793-
# both GCC and Clang. Both currently default to gnu11 and gnu++14.
803+
# both GCC and Clang. Both currently default to gnu11 and gnu++17.
794804
env.Prepend(CFLAGS=["-std=gnu11"])
795805
env.Prepend(CXXFLAGS=["-std=gnu++17"])
796806
else:
797-
# MSVC doesn't have clear C standard support, /std only covers C++.
798-
# We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
799-
env.Prepend(CCFLAGS=["/std:c++17"])
807+
# MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all
808+
# of our supported VS2019 & VS2022 versions; VS2017 will only pass the C++ standard.
809+
env.Prepend(CXXFLAGS=["/std:c++17"])
810+
if cc_version_major < 16:
811+
print_warning("Visual Studio 2017 cannot specify a C-Standard.")
812+
else:
813+
env.Prepend(CFLAGS=["/std:c11"])
800814
# MSVC is non-conforming with the C++ standard by default, so we enable more conformance.
801815
# Note that this is still not complete conformance, as certain Windows-related headers
802816
# don't compile under complete conformance.

methods.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -795,9 +795,9 @@ def get_compiler_version(env):
795795
"major": -1,
796796
"minor": -1,
797797
"patch": -1,
798-
"metadata1": None,
799-
"metadata2": None,
800-
"date": None,
798+
"metadata1": "",
799+
"metadata2": "",
800+
"date": "",
801801
"apple_major": -1,
802802
"apple_minor": -1,
803803
"apple_patch1": -1,
@@ -806,7 +806,20 @@ def get_compiler_version(env):
806806
}
807807

808808
if env.msvc and not using_clang(env):
809-
# TODO: Implement for MSVC
809+
try:
810+
args = [env["VSWHERE"], "-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"]
811+
version = subprocess.check_output(args, encoding="utf-8").strip()
812+
for line in version.splitlines():
813+
split = line.split(":", 1)
814+
if split[0] == "catalog_productDisplayVersion":
815+
sem_ver = split[1].split(".")
816+
ret["major"] = int(sem_ver[0])
817+
ret["minor"] = int(sem_ver[1])
818+
ret["patch"] = int(sem_ver[2])
819+
if split[0] == "catalog_buildVersion":
820+
ret["metadata1"] = split[1]
821+
except (subprocess.CalledProcessError, OSError):
822+
print_warning("Couldn't find vswhere to determine compiler version.")
810823
return ret
811824

812825
# Not using -dumpversion as some GCC distros only return major, and

0 commit comments

Comments
 (0)