From 71684cff021d3470365ffb95717e2dc537aa2996 Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Thu, 13 Jul 2023 20:04:15 -0400 Subject: [PATCH] Machine architecture checks - Prevent running on 32bit Windows or 32bit Python on 64bit Windows - Support i386 for AppImage - Support building Linux System packages on i386 - Support installing JDK for armv6/7/8 --- src/briefcase/commands/base.py | 17 +++++++++++++++++ src/briefcase/integrations/java.py | 4 +++- src/briefcase/integrations/linuxdeploy.py | 9 +++++++-- src/briefcase/platforms/linux/appimage.py | 3 ++- src/briefcase/platforms/linux/system.py | 2 ++ src/briefcase/platforms/windows/__init__.py | 1 + 6 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/briefcase/commands/base.py b/src/briefcase/commands/base.py index 07d6d2c2d..880a6edad 100644 --- a/src/briefcase/commands/base.py +++ b/src/briefcase/commands/base.py @@ -107,6 +107,8 @@ class BaseCommand(ABC): cmd_line = "briefcase {command} {platform} {output_format}" supported_host_os = {"Darwin", "Linux", "Windows"} supported_host_os_reason = f"This command is not supported on {platform.system()}." + supported_host_arch: set() + supports_32bit_python = False # defined by platform-specific subclasses command: str description: str @@ -484,6 +486,21 @@ def verify_host(self): if self.tools.host_os not in self.supported_host_os: raise UnsupportedHostError(self.supported_host_os_reason) + if ( + self.supported_host_arch + and self.tools.host_arch not in self.supported_host_arch + ): + raise BriefcaseCommandError( + f"Briefcase is not supported on {platform.system()} for {platform.machine()}." + ) + + # if the machine's largest supported pointer address is less than 2^32, + # then assume the machine is 32 bits or Python itself is 32 bits + if not self.supports_32bit_python and self.tools.sys.maxsize <= 2**32: + raise BriefcaseCommandError( + f"This command is not supported for a 32bit {platform.machine()} or 32bit Python" + ) + def verify_tools(self): """Verify that the tools needed to run this Command exist. diff --git a/src/briefcase/integrations/java.py b/src/briefcase/integrations/java.py index 4f041349e..dc8f7e6b4 100644 --- a/src/briefcase/integrations/java.py +++ b/src/briefcase/integrations/java.py @@ -29,7 +29,9 @@ def OpenJDK_download_url(self): arch = { "x86_64": "x64", # Linux\macOS x86-64 "aarch64": "aarch64", # Linux arm64 - "armv6l": "arm", # Linux arm + "armv6l": "arm", # Linux armv6 + "armv7l": "arm", # Linux armv7 + "armv8l": "arm", # Linux armv8 "arm64": "aarch64", # macOS arm64 "AMD64": "x64", # Windows x86-64 }.get(self.tools.host_arch) diff --git a/src/briefcase/integrations/linuxdeploy.py b/src/briefcase/integrations/linuxdeploy.py index 9d5d9f5f5..50b875d95 100644 --- a/src/briefcase/integrations/linuxdeploy.py +++ b/src/briefcase/integrations/linuxdeploy.py @@ -48,6 +48,11 @@ def download_url(self) -> str: def file_path(self) -> Path: """The folder on the local filesystem that contains the file_name.""" + @property + def arch(self): + """Return architecture for LinuxDeploy.""" + return {"i686": "i386"}.get(self.tools.host_arch, self.tools.host_arch) + def exists(self) -> bool: return (self.file_path / self.file_name).is_file() @@ -208,7 +213,7 @@ class LinuxDeployQtPlugin(LinuxDeployPluginBase, ManagedTool): @property def file_name(self) -> str: - return f"linuxdeploy-plugin-qt-{self.tools.host_arch}.AppImage" + return f"linuxdeploy-plugin-qt-{self.arch}.AppImage" @property def download_url(self) -> str: @@ -319,7 +324,7 @@ def file_path(self) -> Path: @property def file_name(self) -> str: - return f"linuxdeploy-{self.tools.host_arch}.AppImage" + return f"linuxdeploy-{self.arch}.AppImage" @property def download_url(self) -> str: diff --git a/src/briefcase/platforms/linux/appimage.py b/src/briefcase/platforms/linux/appimage.py index f9916a5f4..afd3787bd 100644 --- a/src/briefcase/platforms/linux/appimage.py +++ b/src/briefcase/platforms/linux/appimage.py @@ -44,7 +44,8 @@ def project_path(self, app): def binary_name(self, app): safe_name = app.formal_name.replace(" ", "_") - return f"{safe_name}-{app.version}-{self.tools.host_arch}.AppImage" + arch = {"i686": "i386"}.get(self.tools.host_arch, self.tools.host_arch) + return f"{safe_name}-{app.version}-{arch}.AppImage" def binary_path(self, app): return self.bundle_path(app) / self.binary_name(app) diff --git a/src/briefcase/platforms/linux/system.py b/src/briefcase/platforms/linux/system.py index 829f4dabd..4d7fb09b6 100644 --- a/src/briefcase/platforms/linux/system.py +++ b/src/briefcase/platforms/linux/system.py @@ -34,6 +34,7 @@ class LinuxSystemPassiveMixin(LinuxMixin): # Docker exists. It is used by commands that are "passive" from the # perspective of the build system (e.g., Run). output_format = "system" + supports_32bit_python = True supported_host_os = {"Darwin", "Linux"} supported_host_os_reason = ( "Linux system projects can only be built on Linux, or on macOS using Docker." @@ -61,6 +62,7 @@ def linux_arch(self): "x86_64": "amd64", "aarch64": "arm64", "armv6l": "armhf", + "i686": "i386", }.get(self.tools.host_arch, self.tools.host_arch) def build_path(self, app): diff --git a/src/briefcase/platforms/windows/__init__.py b/src/briefcase/platforms/windows/__init__.py index fbd2c18f0..2b096eb70 100644 --- a/src/briefcase/platforms/windows/__init__.py +++ b/src/briefcase/platforms/windows/__init__.py @@ -19,6 +19,7 @@ class WindowsMixin: platform = "windows" supported_host_os = {"Windows"} supported_host_os_reason = "Windows applications can only be built on Windows." + supported_host_arch = {"AMD64"} def binary_path(self, app): return self.bundle_path(app) / self.packaging_root / f"{app.formal_name}.exe"