From 346cbc7f1f206f4540520a92bf7def97b9be0af8 Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Fri, 24 May 2024 15:07:22 +0200 Subject: [PATCH] Add support for compiling with VS clang-cl toolset --- .github/workflows/windows_builds.yml | 11 ++++++ SConstruct | 15 +++++--- core/io/packed_data_container.h | 2 +- drivers/gles3/storage/light_storage.h | 2 +- methods.py | 27 +++++++------- modules/mono/editor/hostfxr_resolver.cpp | 2 ++ .../windows/crash_handler_windows_seh.cpp | 2 +- platform/windows/detect.py | 35 ++++++++++++++----- scene/3d/voxelizer.h | 3 +- .../renderer_rd/storage_rd/light_storage.h | 2 +- servers/rendering/rendering_device.h | 4 ++- .../libwebp/patches/godot-clang-cl-fix.patch | 19 ++++++++++ thirdparty/libwebp/src/dsp/cpu.h | 4 +-- 13 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 thirdparty/libwebp/patches/godot-clang-cl-fix.patch diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml index 90629204e6a..0c215765178 100644 --- a/.github/workflows/windows_builds.yml +++ b/.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 }} diff --git a/SConstruct b/SConstruct index e1c943bd458..0297cd6e616 100644 --- a/SConstruct +++ b/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") diff --git a/core/io/packed_data_container.h b/core/io/packed_data_container.h index cc9996101e2..f4ffa090223 100644 --- a/core/io/packed_data_container.h +++ b/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, }; diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 81e7220439f..ed00dd235f3 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/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, diff --git a/methods.py b/methods.py index 6d81b35aff2..bfd08cfc7b5 100644 --- a/methods.py +++ b/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\d+)" diff --git a/modules/mono/editor/hostfxr_resolver.cpp b/modules/mono/editor/hostfxr_resolver.cpp index 7fa482969e0..30dd0a8c565 100644 --- a/modules/mono/editor/hostfxr_resolver.cpp +++ b/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 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) diff --git a/platform/windows/crash_handler_windows_seh.cpp b/platform/windows/crash_handler_windows_seh.cpp index 2abe285d310..a6015092e84 100644 --- a/platform/windows/crash_handler_windows_seh.cpp +++ b/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 modules; DWORD cbNeeded; std::vector module_handles(1); diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 82a98655c07..d2a9c2315ff 100644 --- a/platform/windows/detect.py +++ b/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(";")]) diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h index 6ea1cfdbb08..08d018eee98 100644 --- a/scene/3d/voxelizer.h +++ b/scene/3d/voxelizer.h @@ -35,9 +35,8 @@ class Voxelizer { private: - enum { + enum : uint32_t { CHILD_EMPTY = 0xFFFFFFFF - }; struct Cell { diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 94ab219dc21..1db58d72f9d 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/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, diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index d8f9e2c31a7..1405f585b24 100644 --- a/servers/rendering/rendering_device.h +++ b/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; diff --git a/thirdparty/libwebp/patches/godot-clang-cl-fix.patch b/thirdparty/libwebp/patches/godot-clang-cl-fix.patch new file mode 100644 index 00000000000..ee4f5989519 --- /dev/null +++ b/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 diff --git a/thirdparty/libwebp/src/dsp/cpu.h b/thirdparty/libwebp/src/dsp/cpu.h index c86540f2801..4dbe607aeca 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