Selaa lähdekoodia

Merge pull request #92316 from alula/msvc-clang

Add support for compiling with VS clang-cl toolset
Rémi Verschelde 1 vuosi sitten
vanhempi
commit
cb96fc95c3

+ 11 - 0
.github/workflows/windows_builds.yml

@@ -30,6 +30,14 @@ jobs:
             # Skip debug symbols, they're way too big with MSVC.
             sconsflags: debug_symbols=no vsproj=yes vsproj_gen_only=no windows_subsystem=console
             bin: "./bin/godot.windows.editor.x86_64.exe"
+            artifact: true
+
+          - name: Editor w/ clang-cl (target=editor, tests=yes, use_llvm=yes)
+            cache-name: windows-editor-clang
+            target: editor
+            tests: true
+            sconsflags: debug_symbols=no windows_subsystem=console use_llvm=yes
+            bin: ./bin/godot.windows.editor.x86_64.llvm.exe
 
           - name: Template (target=template_release)
             cache-name: windows-template
@@ -37,6 +45,7 @@ jobs:
             tests: true
             sconsflags: debug_symbols=no tests=yes
             bin: "./bin/godot.windows.template_release.x86_64.console.exe"
+            artifact: true
 
     steps:
       - uses: actions/checkout@v4
@@ -84,10 +93,12 @@ jobs:
         continue-on-error: true
 
       - name: Prepare artifact
+        if: ${{ matrix.artifact }}
         run: |
           Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
 
       - name: Upload artifact
+        if: ${{ matrix.artifact }}
         uses: ./.github/actions/upload-artifact
         with:
           name: ${{ matrix.cache-name }}

+ 10 - 5
SConstruct

@@ -803,7 +803,7 @@ elif env.msvc:
     env.Append(CXXFLAGS=["/EHsc"])
 
 # Configure compiler warnings
-if env.msvc:  # MSVC
+if env.msvc and not methods.using_clang(env):  # MSVC
     if env["warnings"] == "no":
         env.Append(CCFLAGS=["/w"])
     else:
@@ -853,8 +853,11 @@ else:  # GCC, Clang
         # for putting them in `Set` or `Map`. We don't mind about unreliable ordering.
         common_warnings += ["-Wno-ordered-compare-function-pointers"]
 
+    # clang-cl will interpret `-Wall` as `-Weverything`, workaround with compatibility cast
+    W_ALL = "-Wall" if not env.msvc else "-W3"
+
     if env["warnings"] == "extra":
-        env.Append(CCFLAGS=["-Wall", "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
+        env.Append(CCFLAGS=[W_ALL, "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
         env.Append(CXXFLAGS=["-Wctor-dtor-privacy", "-Wnon-virtual-dtor"])
         if methods.using_gcc(env):
             env.Append(
@@ -876,9 +879,9 @@ else:  # GCC, Clang
         elif methods.using_clang(env) or methods.using_emcc(env):
             env.Append(CCFLAGS=["-Wimplicit-fallthrough"])
     elif env["warnings"] == "all":
-        env.Append(CCFLAGS=["-Wall"] + common_warnings)
+        env.Append(CCFLAGS=[W_ALL] + common_warnings)
     elif env["warnings"] == "moderate":
-        env.Append(CCFLAGS=["-Wall", "-Wno-unused"] + common_warnings)
+        env.Append(CCFLAGS=[W_ALL, "-Wno-unused"] + common_warnings)
     else:  # 'no'
         env.Append(CCFLAGS=["-w"])
 
@@ -1032,7 +1035,9 @@ if env["vsproj"]:
 if env["compiledb"]:
     if env.scons_version < (4, 0, 0):
         # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
-        print_error("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version)
+        print_error(
+            "The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version
+        )
         Exit(255)
 
     env.Tool("compilation_db")

+ 1 - 1
core/io/packed_data_container.h

@@ -36,7 +36,7 @@
 class PackedDataContainer : public Resource {
 	GDCLASS(PackedDataContainer, Resource);
 
-	enum {
+	enum : uint32_t {
 		TYPE_DICT = 0xFFFFFFFF,
 		TYPE_ARRAY = 0xFFFFFFFE,
 	};

+ 1 - 1
drivers/gles3/storage/light_storage.h

@@ -203,7 +203,7 @@ struct LightmapInstance {
 
 class LightStorage : public RendererLightStorage {
 public:
-	enum ShadowAtlastQuadrant {
+	enum ShadowAtlastQuadrant : uint32_t {
 		QUADRANT_SHIFT = 27,
 		OMNI_LIGHT_FLAG = 1 << 26,
 		SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1,

+ 13 - 14
methods.py

@@ -163,7 +163,7 @@ def add_source_files(self, sources, files, allow_gen=False):
 
 def disable_warnings(self):
     # 'self' is the environment
-    if self.msvc:
+    if self.msvc and not using_clang(self):
         # We have to remove existing warning level defines before appending /w,
         # otherwise we get: "warning D9025 : overriding '/W3' with '/w'"
         self["CCFLAGS"] = [x for x in self["CCFLAGS"] if not (x.startswith("/W") or x.startswith("/w"))]
@@ -817,21 +817,20 @@ def get_compiler_version(env):
         "apple_patch3": -1,
     }
 
-    if not env.msvc:
-        # Not using -dumpversion as some GCC distros only return major, and
-        # Clang used to return hardcoded 4.2.1: # https://reviews.llvm.org/D56803
-        try:
-            version = (
-                subprocess.check_output([env.subst(env["CXX"]), "--version"], shell=(os.name == "nt"))
-                .strip()
-                .decode("utf-8")
-            )
-        except (subprocess.CalledProcessError, OSError):
-            print_warning("Couldn't parse CXX environment variable to infer compiler version.")
-            return ret
-    else:
+    if env.msvc and not using_clang(env):
         # TODO: Implement for MSVC
         return ret
+
+    # Not using -dumpversion as some GCC distros only return major, and
+    # Clang used to return hardcoded 4.2.1: # https://reviews.llvm.org/D56803
+    try:
+        version = subprocess.check_output(
+            [env.subst(env["CXX"]), "--version"], shell=(os.name == "nt"), encoding="utf-8"
+        ).strip()
+    except (subprocess.CalledProcessError, OSError):
+        print_warning("Couldn't parse CXX environment variable to infer compiler version.")
+        return ret
+
     match = re.search(
         r"(?:(?<=version )|(?<=\) )|(?<=^))"
         r"(?P<major>\d+)"

+ 2 - 0
modules/mono/editor/hostfxr_resolver.cpp

@@ -216,6 +216,7 @@ bool get_default_installation_dir(String &r_dotnet_root) {
 #endif
 }
 
+#ifndef WINDOWS_ENABLED
 bool get_install_location_from_file(const String &p_file_path, String &r_dotnet_root) {
 	Error err = OK;
 	Ref<FileAccess> f = FileAccess::open(p_file_path, FileAccess::READ, &err);
@@ -233,6 +234,7 @@ bool get_install_location_from_file(const String &p_file_path, String &r_dotnet_
 	r_dotnet_root = line;
 	return true;
 }
+#endif
 
 bool get_dotnet_self_registered_dir(String &r_dotnet_root) {
 #if defined(WINDOWS_ENABLED)

+ 1 - 1
platform/windows/crash_handler_windows_seh.cpp

@@ -118,7 +118,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
 	HANDLE process = GetCurrentProcess();
 	HANDLE hThread = GetCurrentThread();
 	DWORD offset_from_symbol = 0;
-	IMAGEHLP_LINE64 line = { 0 };
+	IMAGEHLP_LINE64 line = {};
 	std::vector<module_data> modules;
 	DWORD cbNeeded;
 	std::vector<HMODULE> module_handles(1);

+ 27 - 8
platform/windows/detect.py

@@ -381,6 +381,15 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
 
     ## Compile/link flags
 
+    if env["use_llvm"]:
+        env["CC"] = "clang-cl"
+        env["CXX"] = "clang-cl"
+        env["LINK"] = "lld-link"
+        env["AR"] = "llvm-lib"
+
+        env.AppendUnique(CPPDEFINES=["R128_STDC_ONLY"])
+        env.extra_suffix = ".llvm" + env.extra_suffix
+
     env["MAXLINELENGTH"] = 8192  # Windows Vista and beyond, so always applicable.
 
     if env["silence_msvc"] and not env.GetOption("clean"):
@@ -465,7 +474,6 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
 
     env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"])
     env.AppendUnique(CCFLAGS=["/utf-8"])  # Force to use Unicode encoding.
-    env.AppendUnique(CXXFLAGS=["/TP"])  # assume all sources are C++
     # Once it was thought that only debug builds would be too large,
     # but this has recently stopped being true. See the mingw function
     # for notes on why this shouldn't be enabled for gcc
@@ -590,6 +598,9 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
     if env["target"] in ["editor", "template_debug"]:
         LIBS += ["psapi", "dbghelp"]
 
+    if env["use_llvm"]:
+        LIBS += [f"clang_rt.builtins-{env['arch']}"]
+
     env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
 
     if vcvars_msvc_config:
@@ -605,14 +616,22 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
 
     if env["lto"] != "none":
         if env["lto"] == "thin":
-            print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
-            sys.exit(255)
-        env.AppendUnique(CCFLAGS=["/GL"])
-        env.AppendUnique(ARFLAGS=["/LTCG"])
-        if env["progress"]:
-            env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
+            if not env["use_llvm"]:
+                print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
+                sys.exit(255)
+
+            env.Append(CCFLAGS=["-flto=thin"])
+            env.Append(LINKFLAGS=["-flto=thin"])
+        elif env["use_llvm"]:
+            env.Append(CCFLAGS=["-flto"])
+            env.Append(LINKFLAGS=["-flto"])
         else:
-            env.AppendUnique(LINKFLAGS=["/LTCG"])
+            env.AppendUnique(CCFLAGS=["/GL"])
+            env.AppendUnique(ARFLAGS=["/LTCG"])
+            if env["progress"]:
+                env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
+            else:
+                env.AppendUnique(LINKFLAGS=["/LTCG"])
 
     if vcvars_msvc_config:
         env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")])

+ 1 - 2
scene/3d/voxelizer.h

@@ -35,9 +35,8 @@
 
 class Voxelizer {
 private:
-	enum {
+	enum : uint32_t {
 		CHILD_EMPTY = 0xFFFFFFFF
-
 	};
 
 	struct Cell {

+ 1 - 1
servers/rendering/renderer_rd/storage_rd/light_storage.h

@@ -49,7 +49,7 @@ namespace RendererRD {
 
 class LightStorage : public RendererLightStorage {
 public:
-	enum ShadowAtlastQuadrant {
+	enum ShadowAtlastQuadrant : uint32_t {
 		QUADRANT_SHIFT = 27,
 		OMNI_LIGHT_FLAG = 1 << 26,
 		SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1,

+ 3 - 1
servers/rendering/rendering_device.h

@@ -377,7 +377,9 @@ public:
 	// used for the render pipelines.
 
 	struct AttachmentFormat {
-		enum { UNUSED_ATTACHMENT = 0xFFFFFFFF };
+		enum : uint32_t {
+			UNUSED_ATTACHMENT = 0xFFFFFFFF
+		};
 		DataFormat format;
 		TextureSamples samples;
 		uint32_t usage_flags;

+ 19 - 0
thirdparty/libwebp/patches/godot-clang-cl-fix.patch

@@ -0,0 +1,19 @@
+diff --git a/thirdparty/libwebp/src/dsp/cpu.h b/thirdparty/libwebp/src/dsp/cpu.h
+index c86540f280..4dbe607aec 100644
+--- a/thirdparty/libwebp/src/dsp/cpu.h
++++ b/thirdparty/libwebp/src/dsp/cpu.h
+@@ -47,12 +47,12 @@
+ // x86 defines.
+ 
+ #if !defined(HAVE_CONFIG_H)
+-#if defined(_MSC_VER) && _MSC_VER > 1310 && \
++#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER > 1310 && \
+     (defined(_M_X64) || defined(_M_IX86))
+ #define WEBP_MSC_SSE2  // Visual C++ SSE2 targets
+ #endif
+ 
+-#if defined(_MSC_VER) && _MSC_VER >= 1500 && \
++#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER >= 1500 && \
+     (defined(_M_X64) || defined(_M_IX86))
+ #define WEBP_MSC_SSE41  // Visual C++ SSE4.1 targets
+ #endif

+ 2 - 2
thirdparty/libwebp/src/dsp/cpu.h

@@ -47,12 +47,12 @@
 // x86 defines.
 
 #if !defined(HAVE_CONFIG_H)
-#if defined(_MSC_VER) && _MSC_VER > 1310 && \
+#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER > 1310 && \
     (defined(_M_X64) || defined(_M_IX86))
 #define WEBP_MSC_SSE2  // Visual C++ SSE2 targets
 #endif
 
-#if defined(_MSC_VER) && _MSC_VER >= 1500 && \
+#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER >= 1500 && \
     (defined(_M_X64) || defined(_M_IX86))
 #define WEBP_MSC_SSE41  // Visual C++ SSE4.1 targets
 #endif