2
0
Эх сурвалжийг харах

Merge pull request #55778 from aaronfranke/use-arch-btw

[skip ci]
Rémi Verschelde 3 жил өмнө
parent
commit
c7eb423eeb

+ 4 - 4
.github/workflows/android_builds.yml

@@ -38,19 +38,19 @@ jobs:
       - name: Setup python and scons
         uses: ./.github/actions/godot-deps
 
-      - name: Compilation (armv7)
+      - name: Compilation (arm32)
         uses: ./.github/actions/godot-build
         with:
-          sconsflags: ${{ env.SCONSFLAGS }} android_arch=armv7
+          sconsflags: ${{ env.SCONSFLAGS }} arch=arm32
           platform: android
           target: release
           tools: false
           tests: false
 
-      - name: Compilation (arm64v8)
+      - name: Compilation (arm64)
         uses: ./.github/actions/godot-build
         with:
-          sconsflags: ${{ env.SCONSFLAGS }} android_arch=arm64v8
+          sconsflags: ${{ env.SCONSFLAGS }} arch=arm64
           platform: android
           target: release
           tools: false

+ 1 - 1
.github/workflows/ios_builds.yml

@@ -26,7 +26,7 @@ jobs:
       - name: Setup python and scons
         uses: ./.github/actions/godot-deps
 
-      - name: Compilation (arm64v8)
+      - name: Compilation (arm64)
         uses: ./.github/actions/godot-build
         with:
           sconsflags: ${{ env.SCONSFLAGS }}

+ 3 - 3
.github/workflows/linux_builds.yml

@@ -28,7 +28,7 @@ jobs:
             tests: false # Disabled due freeze caused by mix Mono build and CI
             sconsflags: module_mono_enabled=yes
             doc-test: true
-            bin: "./bin/godot.linuxbsd.opt.tools.64.mono"
+            bin: "./bin/godot.linuxbsd.opt.tools.x86_64.mono"
             build-mono: true
             proj-conv: true
             artifact: true
@@ -43,7 +43,7 @@ jobs:
             # Can be turned off for PRs that intentionally break compat with godot-cpp,
             # until both the upstream PR and the matching godot-cpp changes are merged.
             godot-cpp-test: true
-            bin: "./bin/godot.linuxbsd.double.tools.64.san"
+            bin: "./bin/godot.linuxbsd.double.tools.x86_64.san"
             build-mono: false
             # Skip 2GiB artifact speeding up action.
             artifact: false
@@ -54,7 +54,7 @@ jobs:
             tools: true
             tests: true
             sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes linker=lld
-            bin: "./bin/godot.linuxbsd.tools.64.llvm.san"
+            bin: "./bin/godot.linuxbsd.tools.x86_64.llvm.san"
             build-mono: false
             # Skip 2GiB artifact speeding up action.
             artifact: false

+ 1 - 1
.github/workflows/macos_builds.yml

@@ -24,7 +24,7 @@ jobs:
             target: release_debug
             tools: true
             tests: true
-            bin: "./bin/godot.macos.opt.tools.64"
+            bin: "./bin/godot.macos.opt.tools.x86_64"
 
           - name: Template (target=release, tools=no)
             cache-name: macos-template

+ 1 - 1
.github/workflows/windows_builds.yml

@@ -29,7 +29,7 @@ jobs:
             tests: true
             # Skip debug symbols, they're way too big with MSVC.
             sconsflags: debug_symbols=no
-            bin: "./bin/godot.windows.opt.tools.64.exe"
+            bin: "./bin/godot.windows.opt.tools.x86_64.exe"
 
           - name: Template (target=release, tools=no)
             cache-name: windows-template

+ 1 - 1
CONTRIBUTING.md

@@ -37,7 +37,7 @@ Godot runs on a large variety of platforms and operating systems and devices.
 
 For bugs that are likely OS-specific and/or graphics-related, please also specify:
 
-- Device (CPU model including architecture, e.g. x86, x86_64, ARM, etc.)
+- Device (CPU model including architecture, e.g. x86_64, arm64, etc.)
 - GPU model (and the driver version in use if you know it)
 
 **Bug reports not including the required information may be closed at the

+ 10 - 11
SConstruct

@@ -55,6 +55,7 @@ _helper_module("modules.modules_builders", "modules/modules_builders.py")
 import methods
 import glsl_builders
 import gles3_builders
+from platform_methods import architectures, architecture_aliases
 
 if methods.get_cmdline_bool("tools", True):
     _helper_module("editor.editor_builders", "editor/editor_builders.py")
@@ -161,12 +162,11 @@ if profile:
 opts = Variables(customs, ARGUMENTS)
 
 # Target build options
-opts.Add("p", "Platform (alias for 'platform')", "")
 opts.Add("platform", "Target platform (%s)" % ("|".join(platform_list),), "")
+opts.Add("p", "Platform (alias for 'platform')", "")
 opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True))
 opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release")))
-opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "")
-opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
+opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases))
 opts.Add(EnumVariable("float", "Floating-point precision", "default", ("default", "32", "64")))
 opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none")))
 opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
@@ -502,12 +502,17 @@ if selected_platform in platform_list:
     # Platform specific flags
     flag_list = platform_flags[selected_platform]
     for f in flag_list:
-        if not (f[0] in ARGUMENTS):  # allow command line to override platform flags
+        if not (f[0] in ARGUMENTS) or ARGUMENTS[f[0]] == "auto":  # Allow command line to override platform flags
             env[f[0]] = f[1]
 
     # Must happen after the flags' definition, so that they can be used by platform detect
     detect.configure(env)
 
+    print(
+        'Building for platform "%s", architecture "%s", %s, target "%s".'
+        % (selected_platform, env["arch"], "editor" if env["tools"] else "template", env["target"])
+    )
+
     # Set our C and C++ standard requirements.
     # C++17 is required as we need guaranteed copy elision as per GH-36436.
     # Prepending to make it possible to override.
@@ -693,13 +698,7 @@ if selected_platform in platform_list:
             )
             suffix += ".debug"
 
-    if env["arch"] != "":
-        suffix += "." + env["arch"]
-    elif env["bits"] == "32":
-        suffix += ".32"
-    elif env["bits"] == "64":
-        suffix += ".64"
-
+    suffix += "." + env["arch"]
     suffix += env.extra_suffix
 
     sys.path.remove(tmppath)

+ 1 - 1
drivers/png/SCsub

@@ -37,7 +37,7 @@ if env["builtin_libpng"]:
     import os
 
     # Enable ARM NEON instructions on 32-bit Android to compile more optimized code.
-    use_neon = "android_arch" in env and env["android_arch"] == "armv7" and os.name != "nt"
+    use_neon = env["platform"] == "android" and env["arch"] == "arm32" and os.name != "nt"
     if use_neon:
         env_png.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT", 2)])
     else:

+ 1 - 1
methods.py

@@ -540,7 +540,7 @@ def detect_visual_c_compiler_version(tools_env):
     # and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect
     # the proper vc version that will be called
 
-    # There is no flag to give to visual c compilers to set the architecture, i.e. scons bits argument (32,64,ARM etc)
+    # There is no flag to give to visual c compilers to set the architecture, i.e. scons arch argument (x86_32, x86_64, arm64, etc.).
     # There are many different cl.exe files that are run, and each one compiles & links to a different architecture
     # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program()
     # is to check the PATH variable and figure out which one will be called first. Code below does that and returns:

+ 1 - 8
modules/denoise/config.py

@@ -5,14 +5,7 @@ def can_build(env, platform):
     # as doing lightmap generation and denoising on Android or HTML5
     # would be a bit far-fetched.
     desktop_platforms = ["linuxbsd", "macos", "windows"]
-    supported_arch = env["bits"] == "64"
-    if env["arch"] == "arm64":
-        supported_arch = False
-    if env["arch"].startswith("ppc"):
-        supported_arch = False
-    if env["arch"].startswith("rv"):
-        supported_arch = False
-    return env["tools"] and platform in desktop_platforms and supported_arch
+    return env["tools"] and platform in desktop_platforms and env["arch"] == "x86_64"
 
 
 def configure(env):

+ 10 - 14
modules/mono/build_scripts/mono_configure.py

@@ -18,7 +18,7 @@ def configure(env, env_mono):
     # is_android = env["platform"] == "android"
     # is_javascript = env["platform"] == "javascript"
     # is_ios = env["platform"] == "ios"
-    # is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
+    # is_ios_sim = is_ios and env["arch"] in ["x86_32", "x86_64"]
 
     tools_enabled = env["tools"]
 
@@ -128,26 +128,22 @@ def find_dotnet_app_host_dir(env):
 
 
 def determine_runtime_identifier(env):
+    # The keys are Godot's names, the values are the Microsoft's names.
+    # List: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
     names_map = {
         "windows": "win",
         "macos": "osx",
         "linuxbsd": "linux",
     }
-
-    # .NET RID architectures: x86, x64, arm, or arm64
-
+    arch_map = {
+        "x86_64": "x64",
+        "x86_32": "x86",
+        "arm64": "arm64",
+        "arm32": "arm",
+    }
     platform = env["platform"]
-
     if is_desktop(platform):
-        if env["arch"] in ["arm", "arm32"]:
-            rid = "arm"
-        elif env["arch"] == "arm64":
-            rid = "arm64"
-        else:
-            bits = env["bits"]
-            bit_arch_map = {"64": "x64", "32": "x86"}
-            rid = bit_arch_map[bits]
-        return "%s-%s" % (names_map[platform], rid)
+        return "%s-%s" % (names_map[platform], arch_map[env["arch"]])
     else:
         raise NotImplementedError()
 

+ 24 - 20
modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs

@@ -75,8 +75,17 @@ namespace GodotTools.Export
             }
             else
             {
-                string bits = features.Contains("64") ? "64" : features.Contains("32") ? "32" : null;
-                CompileAssembliesForDesktop(exporter, platform, isDebug, bits, aotOpts, aotTempDir, outputDataDir, assembliesPrepared, bclDir);
+                string arch = "";
+                if (features.Contains("x86_64")) {
+                    arch = "x86_64";
+                } else if (features.Contains("x86_32")) {
+                    arch = "x86_32";
+                } else if (features.Contains("arm64")) {
+                    arch = "arm64";
+                } else if (features.Contains("arm32")) {
+                    arch = "arm32";
+                }
+                CompileAssembliesForDesktop(exporter, platform, isDebug, arch, aotOpts, aotTempDir, outputDataDir, assembliesPrepared, bclDir);
             }
         }
 
@@ -112,7 +121,7 @@ namespace GodotTools.Export
             }
         }
 
-        public static void CompileAssembliesForDesktop(ExportPlugin exporter, string platform, bool isDebug, string bits, AotOptions aotOpts, string aotTempDir, string outputDataDir, IDictionary<string, string> assemblies, string bclDir)
+        public static void CompileAssembliesForDesktop(ExportPlugin exporter, string platform, bool isDebug, string arch, AotOptions aotOpts, string aotTempDir, string outputDataDir, IDictionary<string, string> assemblies, string bclDir)
         {
             foreach (var assembly in assemblies)
             {
@@ -126,9 +135,9 @@ namespace GodotTools.Export
                 string outputFileName = assemblyName + ".dll" + outputFileExtension;
                 string tempOutputFilePath = Path.Combine(aotTempDir, outputFileName);
 
-                var compilerArgs = GetAotCompilerArgs(platform, isDebug, bits, aotOpts, assemblyPath, tempOutputFilePath);
+                var compilerArgs = GetAotCompilerArgs(platform, isDebug, arch, aotOpts, assemblyPath, tempOutputFilePath);
 
-                string compilerDirPath = GetMonoCrossDesktopDirName(platform, bits);
+                string compilerDirPath = GetMonoCrossDesktopDirName(platform, arch);
 
                 ExecuteCompiler(FindCrossCompiler(compilerDirPath), compilerArgs, bclDir);
 
@@ -432,9 +441,9 @@ MONO_AOT_MODE_LAST = 1000,
 
                 var androidToolPrefixes = new Dictionary<string, string>
                 {
-                    ["armeabi-v7a"] = "arm-linux-androideabi-",
-                    ["arm64-v8a"] = "aarch64-linux-android-",
-                    ["x86"] = "i686-linux-android-",
+                    ["arm32"] = "arm-linux-androideabi-",
+                    ["arm64"] = "aarch64-linux-android-",
+                    ["x86_32"] = "i686-linux-android-",
                     ["x86_64"] = "x86_64-linux-android-"
                 };
 
@@ -547,9 +556,9 @@ MONO_AOT_MODE_LAST = 1000,
         {
             var androidAbis = new[]
             {
-                "armeabi-v7a",
-                "arm64-v8a",
-                "x86",
+                "arm32",
+                "arm64",
+                "x86_32",
                 "x86_64"
             };
 
@@ -560,9 +569,9 @@ MONO_AOT_MODE_LAST = 1000,
         {
             var abiArchs = new Dictionary<string, string>
             {
-                ["armeabi-v7a"] = "armv7",
-                ["arm64-v8a"] = "aarch64-v8a",
-                ["x86"] = "i686",
+                ["arm32"] = "armv7",
+                ["arm64"] = "aarch64-v8a",
+                ["x86_32"] = "i686",
                 ["x86_64"] = "x86_64"
             };
 
@@ -571,30 +580,25 @@ MONO_AOT_MODE_LAST = 1000,
             return $"{arch}-linux-android";
         }
 
-        private static string GetMonoCrossDesktopDirName(string platform, string bits)
+        private static string GetMonoCrossDesktopDirName(string platform, string arch)
         {
             switch (platform)
             {
                 case OS.Platforms.Windows:
                 case OS.Platforms.UWP:
                 {
-                    string arch = bits == "64" ? "x86_64" : "i686";
                     return $"windows-{arch}";
                 }
                 case OS.Platforms.MacOS:
                 {
-                    Debug.Assert(bits == null || bits == "64");
-                    string arch = "x86_64";
                     return $"{platform}-{arch}";
                 }
                 case OS.Platforms.LinuxBSD:
                 {
-                    string arch = bits == "64" ? "x86_64" : "i686";
                     return $"linux-{arch}";
                 }
                 case OS.Platforms.Haiku:
                 {
-                    string arch = bits == "64" ? "x86_64" : "i686";
                     return $"{platform}-{arch}";
                 }
                 default:

+ 2 - 2
modules/raycast/SCsub

@@ -66,7 +66,7 @@ if env["builtin_embree"]:
     env_raycast.Append(CPPDEFINES=["EMBREE_TARGET_SSE2", "EMBREE_LOWEST_ISA", "TASKING_INTERNAL", "NDEBUG"])
 
     if not env.msvc:
-        if env["arch"] in ["x86", "x86_64"]:
+        if env["arch"] == "x86_64":
             env_raycast.Append(CPPFLAGS=["-msse2", "-mxsave"])
 
         if env["platform"] == "windows":
@@ -83,7 +83,7 @@ if env["builtin_embree"]:
     env_thirdparty.disable_warnings()
     env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
 
-    if not env["arch"] in ["x86", "x86_64"] or env.msvc:
+    if env["arch"] == "arm64" or env.msvc:
         # Embree needs those, it will automatically use SSE2NEON in ARM
         env_thirdparty.Append(CPPDEFINES=["__SSE2__", "__SSE__"])
 

+ 2 - 14
modules/raycast/config.py

@@ -1,18 +1,6 @@
 def can_build(env, platform):
-    # Depends on Embree library, which only supports x86_64 and aarch64.
-    if env["arch"].startswith("rv") or env["arch"].startswith("ppc"):
-        return False
-
-    if platform == "android":
-        return env["android_arch"] in ["arm64v8", "x86_64"]
-
-    if platform == "javascript":
-        return False  # No SIMD support yet
-
-    if env["bits"] == "32":
-        return False
-
-    return True
+    # Depends on Embree library, which only supports x86_64 and arm64.
+    return env["arch"] in ["x86_64", "arm64"]
 
 
 def configure(env):

+ 4 - 4
platform/android/SCsub

@@ -41,13 +41,13 @@ lib = env_android.add_shared_library("#bin/libgodot", [android_objects], SHLIBSU
 env.Depends(lib, thirdparty_obj)
 
 lib_arch_dir = ""
-if env["android_arch"] == "armv7":
+if env["arch"] == "arm32":
     lib_arch_dir = "armeabi-v7a"
-elif env["android_arch"] == "arm64v8":
+elif env["arch"] == "arm64":
     lib_arch_dir = "arm64-v8a"
-elif env["android_arch"] == "x86":
+elif env["arch"] == "x86_32":
     lib_arch_dir = "x86"
-elif env["android_arch"] == "x86_64":
+elif env["arch"] == "x86_64":
     lib_arch_dir = "x86_64"
 else:
     print("WARN: Architecture not suitable for embedding into APK; keeping .so at \\bin")

+ 23 - 21
platform/android/detect.py

@@ -22,7 +22,6 @@ def get_opts():
     return [
         ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()),
         ("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"),
-        EnumVariable("android_arch", "Target architecture", "arm64v8", ("armv7", "arm64v8", "x86", "x86_64")),
     ]
 
 
@@ -46,6 +45,7 @@ def get_ndk_version():
 
 def get_flags():
     return [
+        ("arch", "arm64"),  # Default for convenience.
         ("tools", False),
     ]
 
@@ -75,35 +75,37 @@ def install_ndk_if_needed(env):
 
 
 def configure(env):
+    # Validate arch.
+    supported_arches = ["x86_32", "x86_64", "arm32", "arm64"]
+    if env["arch"] not in supported_arches:
+        print(
+            'Unsupported CPU architecture "%s" for Android. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
+        )
+        sys.exit()
+
     install_ndk_if_needed(env)
     ndk_root = env["ANDROID_NDK_ROOT"]
 
     # Architecture
 
-    if env["android_arch"] not in ["armv7", "arm64v8", "x86", "x86_64"]:
-        env["android_arch"] = "arm64v8"
-
-    print("Building for Android, platform " + env["ndk_platform"] + " (" + env["android_arch"] + ")")
-
-    if get_min_sdk_version(env["ndk_platform"]) < 21:
-        if env["android_arch"] == "x86_64" or env["android_arch"] == "arm64v8":
-            print(
-                "WARNING: android_arch="
-                + env["android_arch"]
-                + " is not supported by ndk_platform lower than android-21; setting ndk_platform=android-21"
-            )
-            env["ndk_platform"] = "android-21"
+    if get_min_sdk_version(env["ndk_platform"]) < 21 and env["arch"] in ["x86_64", "arm64"]:
+        print(
+            'WARNING: arch="%s" is not supported with "ndk_platform" lower than "android-21". Forcing platform 21.'
+            % env["arch"]
+        )
+        env["ndk_platform"] = "android-21"
 
-    if env["android_arch"] == "armv7":
+    if env["arch"] == "arm32":
         target_triple = "armv7a-linux-androideabi"
         env.extra_suffix = ".armv7" + env.extra_suffix
-    elif env["android_arch"] == "arm64v8":
+    elif env["arch"] == "arm64":
         target_triple = "aarch64-linux-android"
         env.extra_suffix = ".armv8" + env.extra_suffix
-    elif env["android_arch"] == "x86":
+    elif env["arch"] == "x86_32":
         target_triple = "i686-linux-android"
         env.extra_suffix = ".x86" + env.extra_suffix
-    elif env["android_arch"] == "x86_64":
+    elif env["arch"] == "x86_64":
         target_triple = "x86_64-linux-android"
         env.extra_suffix = ".x86_64" + env.extra_suffix
 
@@ -176,14 +178,14 @@ def configure(env):
     if get_min_sdk_version(env["ndk_platform"]) >= 24:
         env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)])
 
-    if env["android_arch"] == "x86":
+    if env["arch"] == "x86_32":
         # The NDK adds this if targeting API < 24, so we can drop it when Godot targets it at least
         env.Append(CCFLAGS=["-mstackrealign"])
-    elif env["android_arch"] == "armv7":
+    elif env["arch"] == "arm32":
         env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split())
         env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"])
         env.Append(CPPDEFINES=["__ARM_NEON__"])
-    elif env["android_arch"] == "arm64v8":
+    elif env["arch"] == "arm64":
         env.Append(CCFLAGS=["-mfix-cortex-a53-835769"])
         env.Append(CPPDEFINES=["__ARM_ARCH_8A__"])
 

+ 4 - 4
platform/android/export/export_plugin.cpp

@@ -588,9 +588,9 @@ zip_fileinfo EditorExportPlatformAndroid::get_zip_fileinfo() {
 
 Vector<String> EditorExportPlatformAndroid::get_abis() {
 	Vector<String> abis;
-	abis.push_back("armeabi-v7a");
-	abis.push_back("arm64-v8a");
-	abis.push_back("x86");
+	abis.push_back("arm32");
+	abis.push_back("arm64");
+	abis.push_back("x86_32");
 	abis.push_back("x86_64");
 	return abis;
 }
@@ -1710,7 +1710,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
 		const String abi = abis[i];
 		// All Android devices supporting Vulkan run 64-bit Android,
 		// so there is usually no point in exporting for 32-bit Android.
-		const bool is_default = abi == "arm64-v8a";
+		const bool is_default = abi == "arm64";
 		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("architectures"), abi)), is_default));
 	}
 

+ 2 - 2
platform/android/java/build.gradle

@@ -28,7 +28,7 @@ allprojects {
 }
 
 ext {
-    supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"]
+    supportedAbis = ["arm32", "arm64", "x86_32", "x86_64"]
     supportedTargetsMap = [release: "release", dev: "debug", debug: "release_debug"]
     supportedFlavors = ["editor", "template"]
 
@@ -37,7 +37,7 @@ ext {
     // If building manually on the command line, it's recommended to use the
     // `./gradlew generateGodotTemplates` build command instead after running the `scons` command(s).
     // The {selectedAbis} values must be from the {supportedAbis} values.
-    selectedAbis = ["arm64v8"]
+    selectedAbis = ["arm64"]
 }
 
 def rootDir = "../../.."

+ 1 - 1
platform/android/java/lib/build.gradle

@@ -159,7 +159,7 @@ android {
             def taskName = getSconsTaskName(flavorName, buildType, selectedAbi)
             tasks.create(name: taskName, type: Exec) {
                 executable sconsExecutableFile.absolutePath
-                args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "android_arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors()
+                args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors()
             }
 
             // Schedule the tasks so the generated libs are present before the aar file is packaged.

+ 3 - 3
platform/android/os_android.cpp

@@ -370,15 +370,15 @@ bool OS_Android::_check_internal_feature_support(const String &p_feature) {
 		return true;
 	}
 #if defined(__aarch64__)
-	if (p_feature == "arm64-v8a") {
+	if (p_feature == "arm64-v8a" || p_feature == "arm64") {
 		return true;
 	}
 #elif defined(__ARM_ARCH_7A__)
-	if (p_feature == "armeabi-v7a" || p_feature == "armeabi") {
+	if (p_feature == "armeabi-v7a" || p_feature == "armeabi" || p_feature == "arm32") {
 		return true;
 	}
 #elif defined(__arm__)
-	if (p_feature == "armeabi") {
+	if (p_feature == "armeabi" || p_feature == "arm") {
 		return true;
 	}
 #endif

+ 10 - 5
platform/ios/detect.py

@@ -36,12 +36,22 @@ def get_opts():
 
 def get_flags():
     return [
+        ("arch", "arm64"),  # Default for convenience.
         ("tools", False),
         ("use_volk", False),
     ]
 
 
 def configure(env):
+    # Validate arch.
+    supported_arches = ["x86_64", "arm64"]
+    if env["arch"] not in supported_arches:
+        print(
+            'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
+        )
+        sys.exit()
+
     ## Build type
 
     if env["target"].startswith("release"):
@@ -64,11 +74,6 @@ def configure(env):
         env.Append(CCFLAGS=["-flto"])
         env.Append(LINKFLAGS=["-flto"])
 
-    ## Architecture
-    env["bits"] = "64"
-    if env["arch"] != "x86_64":
-        env["arch"] = "arm64"
-
     ## Compiler configuration
 
     # Save this in environment for use by other modules

+ 10 - 0
platform/javascript/detect.py

@@ -46,6 +46,7 @@ def get_opts():
 
 def get_flags():
     return [
+        ("arch", "wasm32"),
         ("tools", False),
         ("builtin_pcre2_with_jit", False),
         ("vulkan", False),
@@ -53,6 +54,15 @@ def get_flags():
 
 
 def configure(env):
+    # Validate arch.
+    supported_arches = ["wasm32"]
+    if env["arch"] not in supported_arches:
+        print(
+            'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
+        )
+        sys.exit()
+
     try:
         env["initial_memory"] = int(env["initial_memory"])
     except Exception:

+ 19 - 23
platform/linuxbsd/detect.py

@@ -2,6 +2,7 @@ import os
 import platform
 import sys
 from methods import get_compiler_version, using_gcc
+from platform_methods import detect_arch
 
 
 def is_active():
@@ -52,10 +53,21 @@ def get_opts():
 
 
 def get_flags():
-    return []
+    return [
+        ("arch", detect_arch()),
+    ]
 
 
 def configure(env):
+    # Validate arch.
+    supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"]
+    if env["arch"] not in supported_arches:
+        print(
+            'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
+        )
+        sys.exit()
+
     ## Build type
 
     if env["target"] == "release":
@@ -80,23 +92,7 @@ def configure(env):
         env.Prepend(CCFLAGS=["-g3"])
         env.Append(LINKFLAGS=["-rdynamic"])
 
-    ## Architecture
-
-    is64 = sys.maxsize > 2**32
-    if env["bits"] == "default":
-        env["bits"] = "64" if is64 else "32"
-
-    machines = {
-        "riscv64": "rv64",
-        "ppc64le": "ppc64",
-        "ppc64": "ppc64",
-        "ppcle": "ppc",
-        "ppc": "ppc",
-    }
-
-    if env["arch"] == "" and platform.machine() in machines:
-        env["arch"] = machines[platform.machine()]
-
+    # CPU architecture flags.
     if env["arch"] == "rv64":
         # G = General-purpose extensions, C = Compression extension (very common).
         env.Append(CCFLAGS=["-march=rv64gc"])
@@ -262,8 +258,7 @@ def configure(env):
         env["builtin_libvorbis"] = False  # Needed to link against system libtheora
         env.ParseConfig("pkg-config theora theoradec --cflags --libs")
     else:
-        list_of_x86 = ["x86_64", "x86", "i386", "i586"]
-        if any(platform.machine() in s for s in list_of_x86):
+        if env["arch"] in ["x86_64", "x86_32"]:
             env["x86_libtheora_opt_gcc"] = True
 
     if not env["builtin_libvorbis"]:
@@ -405,11 +400,12 @@ def configure(env):
                 env.Append(LINKFLAGS=["-T", "platform/linuxbsd/pck_embed.legacy.ld"])
 
     ## Cross-compilation
-
-    if is64 and env["bits"] == "32":
+    # TODO: Support cross-compilation on architectures other than x86.
+    host_is_64_bit = sys.maxsize > 2**32
+    if host_is_64_bit and env["arch"] == "x86_32":
         env.Append(CCFLAGS=["-m32"])
         env.Append(LINKFLAGS=["-m32", "-L/usr/lib/i386-linux-gnu"])
-    elif not is64 and env["bits"] == "64":
+    elif not host_is_64_bit and env["arch"] == "x86_64":
         env.Append(CCFLAGS=["-m64"])
         env.Append(LINKFLAGS=["-m64", "-L/usr/lib/i686-linux-gnu"])
 

+ 17 - 12
platform/macos/detect.py

@@ -1,6 +1,7 @@
 import os
 import sys
 from methods import detect_darwin_sdk_path
+from platform_methods import detect_arch
 
 
 def is_active():
@@ -37,6 +38,7 @@ def get_opts():
 
 def get_flags():
     return [
+        ("arch", detect_arch()),
         ("use_volk", False),
     ]
 
@@ -71,6 +73,15 @@ def get_mvk_sdk_path():
 
 
 def configure(env):
+    # Validate arch.
+    supported_arches = ["x86_64", "arm64"]
+    if env["arch"] not in supported_arches:
+        print(
+            'Unsupported CPU architecture "%s" for macOS. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
+        )
+        sys.exit()
+
     ## Build type
 
     if env["target"] == "release":
@@ -96,25 +107,20 @@ def configure(env):
         env.Prepend(CCFLAGS=["-g3"])
         env.Prepend(LINKFLAGS=["-Xlinker", "-no_deduplicate"])
 
-    ## Architecture
-
-    # macOS no longer runs on 32-bit since 10.7 which is unsupported since 2014
-    # As such, we only support 64-bit
-    env["bits"] = "64"
-
     ## Compiler configuration
 
     # Save this in environment for use by other modules
     if "OSXCROSS_ROOT" in os.environ:
         env["osxcross"] = True
 
+    # CPU architecture.
     if env["arch"] == "arm64":
-        print("Building for macOS 11.0+, platform arm64.")
+        print("Building for macOS 11.0+.")
         env.Append(ASFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
         env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
         env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
-    else:
-        print("Building for macOS 10.12+, platform x86_64.")
+    elif env["arch"] == "x86_64":
+        print("Building for macOS 10.12+.")
         env.Append(ASFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
         env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
         env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
@@ -185,9 +191,8 @@ def configure(env):
 
     ## Dependencies
 
-    if env["builtin_libtheora"]:
-        if env["arch"] != "arm64":
-            env["x86_libtheora_opt_gcc"] = True
+    if env["builtin_libtheora"] and env["arch"] == "x86_64":
+        env["x86_libtheora_opt_gcc"] = True
 
     ## Flags
 

+ 19 - 20
platform/uwp/detect.py

@@ -1,6 +1,7 @@
 import methods
 import os
 import sys
+from platform_methods import detect_arch
 
 
 def is_active():
@@ -31,6 +32,7 @@ def get_opts():
 
 def get_flags():
     return [
+        ("arch", detect_arch()),
         ("tools", False),
         ("xaudio2", True),
         ("builtin_pcre2_with_jit", False),
@@ -38,19 +40,17 @@ def get_flags():
 
 
 def configure(env):
-    env.msvc = True
-
-    if env["bits"] != "default":
-        print("Error: bits argument is disabled for MSVC")
+    # Validate arch.
+    supported_arches = ["x86_32", "x86_64", "arm32"]
+    if env["arch"] not in supported_arches:
         print(
-            """
-            Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console
-            (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits
-            argument (example: scons p=uwp) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
-            """
+            'Unsupported CPU architecture "%s" for UWP. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
         )
         sys.exit()
 
+    env.msvc = True
+
     ## Build type
 
     if env["target"] == "release":
@@ -101,11 +101,10 @@ def configure(env):
 
     arch = ""
     if str(os.getenv("Platform")).lower() == "arm":
-
-        print("Compiled program architecture will be an ARM executable. (forcing bits=32).")
+        print("Compiled program architecture will be an ARM executable (forcing arch=arm32).")
 
         arch = "arm"
-        env["bits"] = "32"
+        env["arch"] = "arm32"
         env.Append(LINKFLAGS=["/MACHINE:ARM"])
         env.Append(LIBPATH=[vc_base_path + "lib/store/arm"])
 
@@ -117,20 +116,20 @@ def configure(env):
         compiler_version_str = methods.detect_visual_c_compiler_version(env["ENV"])
 
         if compiler_version_str == "amd64" or compiler_version_str == "x86_amd64":
-            env["bits"] = "64"
-            print("Compiled program architecture will be a x64 executable (forcing bits=64).")
+            env["arch"] = "x86_64"
+            print("Compiled program architecture will be a x64 executable (forcing arch=x86_64).")
         elif compiler_version_str == "x86" or compiler_version_str == "amd64_x86":
-            env["bits"] = "32"
-            print("Compiled program architecture will be a x86 executable. (forcing bits=32).")
+            env["arch"] = "x86_32"
+            print("Compiled program architecture will be a x86 executable (forcing arch=x86_32).")
         else:
             print(
-                "Failed to detect MSVC compiler architecture version... Defaulting to 32-bit executable settings"
-                " (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture"
+                "Failed to detect MSVC compiler architecture version... Defaulting to x86 32-bit executable settings"
+                " (forcing arch=x86_32). Compilation attempt will continue, but SCons can not detect for what architecture"
                 " this build is compiled for. You should check your settings/compilation setup."
             )
-            env["bits"] = "32"
+            env["arch"] = "x86_32"
 
-        if env["bits"] == "32":
+        if env["arch"] == "x86_32":
             arch = "x86"
 
             angle_build_cmd += "Win32"

+ 61 - 39
platform/windows/detect.py

@@ -1,5 +1,6 @@
 import methods
 import os
+from platform_methods import detect_arch
 
 # To match other platforms
 STACK_SIZE = 8388608
@@ -46,6 +47,7 @@ def can_build():
 def get_opts():
     from SCons.Variables import BoolVariable, EnumVariable
 
+    # TODO: These shouldn't be hard-coded for x86.
     mingw32 = ""
     mingw64 = ""
     if os.name == "posix":
@@ -77,11 +79,14 @@ def get_opts():
 
 
 def get_flags():
-    return []
+    return [
+        ("arch", detect_arch()),
+    ]
 
 
 def build_res_file(target, source, env):
-    if env["bits"] == "32":
+    # TODO: This shouldn't be hard-coded for x86.
+    if env["arch"] == "x86_32":
         cmdbase = env["mingw_prefix_32"]
     else:
         cmdbase = env["mingw_prefix_64"]
@@ -100,21 +105,27 @@ def build_res_file(target, source, env):
 
 
 def setup_msvc_manual(env):
+    # FIXME: This is super hacky, and probably obsolete.
+    # Won't work with detect_arch() used for `arch` by default.
+
     """Set up env to use MSVC manually, using VCINSTALLDIR"""
-    if env["bits"] != "default":
+    if env["arch"] != "auto":
         print(
             """
-            Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console
-            (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits
-            argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
+            Arch argument is not supported for MSVC manual configuration (VCINSTALLDIR configured).
+            Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons.
+            As a consequence, the arch argument is disabled. Run scons again without arch argument (example: scons p=windows)
+            and SCons will attempt to detect what MSVC compiler will be executed and inform you.
             """
         )
-        raise SCons.Errors.UserError("Bits argument should not be used when using VCINSTALLDIR")
+        raise SCons.Errors.UserError("Arch argument should not be used when using VCINSTALLDIR")
 
-    # Force bits arg
+    # Force ARCH arg
     # (Actually msys2 mingw can support 64-bit, we could detect that)
-    env["bits"] = "32"
-    env["x86_libtheora_opt_vc"] = True
+    # TODO: This is wrong, but not sure what to do about it.
+    # We want to determine the arch and bitness in the SConstruct only.
+    # We can check if it's correct in here, but if it's not, it should
+    # just fail with an error message instead of trying to force it.
 
     # find compiler manually
     compiler_version_str = methods.detect_visual_c_compiler_version(env["ENV"])
@@ -122,17 +133,19 @@ def setup_msvc_manual(env):
 
     # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writing)... vc compiler for 64bit can not compile _asm
     if compiler_version_str == "amd64" or compiler_version_str == "x86_amd64":
-        env["bits"] = "64"
+        env["arch"] = "x86_64"
         env["x86_libtheora_opt_vc"] = False
-        print("Compiled program architecture will be a 64 bit executable (forcing bits=64).")
+        print("Compiled program architecture will be a 64 bit executable (forcing arch=x86_64).")
     elif compiler_version_str == "x86" or compiler_version_str == "amd64_x86":
-        print("Compiled program architecture will be a 32 bit executable. (forcing bits=32).")
+        env["arch"] = "x86_32"
+        env["x86_libtheora_opt_vc"] = True
+        print("Compiled program architecture will be a 32 bit executable (forcing arch=x86_32).")
     else:
         print(
-            "Failed to manually detect MSVC compiler architecture version... Defaulting to 32bit executable settings"
-            " (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this"
-            " build is compiled for. You should check your settings/compilation setup, or avoid setting VCINSTALLDIR."
+            "Failed to manually detect MSVC compiler architecture version.\n"
+            "You should check your settings/compilation setup, or avoid setting VCINSTALLDIR."
         )
+        sys.exit()
 
 
 def setup_msvc_auto(env):
@@ -141,6 +154,18 @@ def setup_msvc_auto(env):
     # If MSVC_VERSION is set by SCons, we know MSVC is installed.
     # But we may want a different version or target arch.
 
+    # Valid architectures for MSVC's TARGET_ARCH:
+    # ['amd64', 'emt64', 'i386', 'i486', 'i586', 'i686', 'ia64', 'itanium', 'x86', 'x86_64', 'arm', 'arm64', 'aarch64']
+    # Our x86_64 and arm64 are the same, and we need to map the 32-bit
+    # architectures to other names since MSVC isn't as explicit.
+    # The rest we don't need to worry about because they are
+    # aliases or aren't supported by Godot (itanium & ia64).
+    msvc_arch_aliases = {"x86_32": "x86", "arm32": "arm"}
+    if env["arch"] in msvc_arch_aliases.keys():
+        env["TARGET_ARCH"] = msvc_arch_aliases[env["arch"]]
+    else:
+        env["TARGET_ARCH"] = env["arch"]
+
     # The env may have already been set up with default MSVC tools, so
     # reset a few things so we can set it up with the tools we want.
     # (Ideally we'd decide on the tool config before configuring any
@@ -149,21 +174,14 @@ def setup_msvc_auto(env):
     env["MSVC_SETUP_RUN"] = False  # Need to set this to re-run the tool
     env["MSVS_VERSION"] = None
     env["MSVC_VERSION"] = None
-    env["TARGET_ARCH"] = None
-    if env["bits"] != "default":
-        env["TARGET_ARCH"] = {"32": "x86", "64": "x86_64"}[env["bits"]]
+
     if "msvc_version" in env:
         env["MSVC_VERSION"] = env["msvc_version"]
     env.Tool("msvc")
     env.Tool("mssdk")  # we want the MS SDK
     # Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015
-    # Get actual target arch into bits (it may be "default" at this point):
-    if env["TARGET_ARCH"] in ("amd64", "x86_64"):
-        env["bits"] = "64"
-    else:
-        env["bits"] = "32"
-    print("Found MSVC version %s, arch %s, bits=%s" % (env["MSVC_VERSION"], env["TARGET_ARCH"], env["bits"]))
-    if env["TARGET_ARCH"] in ("amd64", "x86_64"):
+    print("Found MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["TARGET_ARCH"]))
+    if env["arch"] == "x86_32":
         env["x86_libtheora_opt_vc"] = False
 
 
@@ -244,7 +262,7 @@ def configure_msvc(env, manual_msvc_config):
         ]
     )
     env.AppendUnique(CPPDEFINES=["NOMINMAX"])  # disable bogus min/max WinDef.h macros
-    if env["bits"] == "64":
+    if env["arch"] == "x86_64":
         env.AppendUnique(CPPDEFINES=["_WIN64"])
 
     ## Libs
@@ -328,10 +346,10 @@ def configure_mingw(env):
         env.Append(CCFLAGS=["-msse2"])
 
         if env["optimize"] == "speed":  # optimize for speed (default)
-            if env["bits"] == "64":
-                env.Append(CCFLAGS=["-O3"])
-            else:
+            if env["arch"] == "x86_32":
                 env.Append(CCFLAGS=["-O2"])
+            else:
+                env.Append(CCFLAGS=["-O3"])
         else:  # optimize for size
             env.Prepend(CCFLAGS=["-Os"])
 
@@ -365,15 +383,12 @@ def configure_mingw(env):
     if os.name != "nt":
         env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe"  # for linux cross-compilation
 
-    if env["bits"] == "default":
-        if os.name == "nt":
-            env["bits"] = "64" if "PROGRAMFILES(X86)" in os.environ else "32"
-        else:  # default to 64-bit on Linux
-            env["bits"] = "64"
-
     mingw_prefix = ""
 
-    if env["bits"] == "32":
+    # TODO: This doesn't seem to be working, or maybe I just have
+    # MinGW set up incorrectly. It always gives me x86_64 builds,
+    # even though arch == "x86_32" and the file name has x86_32 in it.
+    if env["arch"] == "x86_32":
         if env["use_static_cpp"]:
             env.Append(LINKFLAGS=["-static"])
             env.Append(LINKFLAGS=["-static-libgcc"])
@@ -460,11 +475,18 @@ def configure_mingw(env):
 
 
 def configure(env):
+    # Validate arch.
+    supported_arches = ["x86_32", "x86_64", "arm32", "arm64"]
+    if env["arch"] not in supported_arches:
+        print(
+            'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.'
+            % (env["arch"], ", ".join(supported_arches))
+        )
+        sys.exit()
+
     # At this point the env has been set up with basic tools/compilers.
     env.Prepend(CPPPATH=["#platform/windows"])
 
-    print("Configuring for Windows: target=%s, bits=%s" % (env["target"], env["bits"]))
-
     if os.name == "nt":
         env["ENV"] = os.environ  # this makes build less repeatable, but simplifies some things
         env["ENV"]["TMP"] = os.environ["TMP"]

+ 1 - 1
platform/windows/platform_windows_builders.py

@@ -9,7 +9,7 @@ from platform_methods import subprocess_main
 
 def make_debug_mingw(target, source, env):
     mingw_prefix = ""
-    if env["bits"] == "32":
+    if env["arch"] == "x86_32":
         mingw_prefix = env["mingw_prefix_32"]
     else:
         mingw_prefix = env["mingw_prefix_64"]

+ 35 - 1
platform_methods.py

@@ -1,6 +1,7 @@
 import os
 import sys
 import json
+import platform
 import uuid
 import functools
 import subprocess
@@ -71,9 +72,42 @@ def run_in_subprocess(builder_function):
 
 
 def subprocess_main(namespace):
-
     with open(sys.argv[1]) as json_file:
         data = json.load(json_file)
 
     fn = namespace[data["fn"]]
     fn(*data["args"])
+
+
+# CPU architecture options.
+architectures = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64", "wasm32"]
+architecture_aliases = {
+    "x86": "x86_32",
+    "x64": "x86_64",
+    "amd64": "x86_64",
+    "armv7": "arm32",
+    "armv8": "arm64",
+    "arm64v8": "arm64",
+    "aarch64": "arm64",
+    "rv": "rv64",
+    "riscv": "rv64",
+    "riscv64": "rv64",
+    "ppcle": "ppc32",
+    "ppc": "ppc32",
+    "ppc64le": "ppc64",
+}
+
+
+def detect_arch():
+    host_machine = platform.machine().lower()
+    if host_machine in architectures:
+        return host_machine
+    elif host_machine in architecture_aliases.keys():
+        return architecture_aliases[host_machine]
+    elif "86" in host_machine:
+        # Catches x86, i386, i486, i586, i686, etc.
+        return "x86_32"
+    else:
+        print("Unsupported CPU architecture: " + host_machine)
+        print("Falling back to x86_64.")
+        return "x86_64"