diff --git a/qt/package/.cargo/config b/qt/package/.cargo/config index 0a543e7c1..1b80d9ae5 100644 --- a/qt/package/.cargo/config +++ b/qt/package/.cargo/config @@ -15,6 +15,9 @@ rustflags = ["-C", "link-args=-Wl,-export-dynamic"] [target.x86_64-unknown-linux-gnu] rustflags = ["-C", "link-args=-Wl,-export-dynamic"] +[target.aarch64-unknown-linux-gnu] +rustflags = ["-C", "link-args=-Wl,-export-dynamic"] + [target.aarch64-apple-darwin] rustflags = ["-C", "link-args=-rdynamic"] diff --git a/qt/package/Cargo.lock b/qt/package/Cargo.lock index dda019616..743be6f64 100644 --- a/qt/package/Cargo.lock +++ b/qt/package/Cargo.lock @@ -345,7 +345,7 @@ dependencies = [ [[package]] name = "pyembed" version = "0.20.0-pre" -source = "git+https://github.com/ankitects/PyOxidizer.git?rev=200fbd25894e9000451b0c562085bf70b8b9f6c1#200fbd25894e9000451b0c562085bf70b8b9f6c1" +source = "git+https://github.com/ankitects/PyOxidizer.git?rev=eb26dd7cd1290de6503869f3d719eabcec45e139#eb26dd7cd1290de6503869f3d719eabcec45e139" dependencies = [ "anyhow", "dunce", @@ -410,7 +410,7 @@ dependencies = [ [[package]] name = "python-oxidized-importer" version = "0.5.0-pre" -source = "git+https://github.com/ankitects/PyOxidizer.git?rev=200fbd25894e9000451b0c562085bf70b8b9f6c1#200fbd25894e9000451b0c562085bf70b8b9f6c1" +source = "git+https://github.com/ankitects/PyOxidizer.git?rev=eb26dd7cd1290de6503869f3d719eabcec45e139#eb26dd7cd1290de6503869f3d719eabcec45e139" dependencies = [ "anyhow", "memmap", @@ -426,7 +426,7 @@ dependencies = [ [[package]] name = "python-packaging" version = "0.12.0-pre" -source = "git+https://github.com/ankitects/PyOxidizer.git?rev=200fbd25894e9000451b0c562085bf70b8b9f6c1#200fbd25894e9000451b0c562085bf70b8b9f6c1" +source = "git+https://github.com/ankitects/PyOxidizer.git?rev=eb26dd7cd1290de6503869f3d719eabcec45e139#eb26dd7cd1290de6503869f3d719eabcec45e139" dependencies = [ "anyhow", "byteorder", @@ -445,7 +445,7 @@ dependencies = [ [[package]] name = "python-packed-resources" version = "0.9.0-pre" -source = "git+https://github.com/ankitects/PyOxidizer.git?rev=200fbd25894e9000451b0c562085bf70b8b9f6c1#200fbd25894e9000451b0c562085bf70b8b9f6c1" +source = "git+https://github.com/ankitects/PyOxidizer.git?rev=eb26dd7cd1290de6503869f3d719eabcec45e139#eb26dd7cd1290de6503869f3d719eabcec45e139" dependencies = [ "anyhow", "byteorder", @@ -555,12 +555,12 @@ dependencies = [ [[package]] name = "tugger-file-manifest" version = "0.7.0-pre" -source = "git+https://github.com/ankitects/PyOxidizer.git?rev=200fbd25894e9000451b0c562085bf70b8b9f6c1#200fbd25894e9000451b0c562085bf70b8b9f6c1" +source = "git+https://github.com/ankitects/PyOxidizer.git?rev=eb26dd7cd1290de6503869f3d719eabcec45e139#eb26dd7cd1290de6503869f3d719eabcec45e139" [[package]] name = "tugger-licensing" version = "0.6.0-pre" -source = "git+https://github.com/ankitects/PyOxidizer.git?rev=200fbd25894e9000451b0c562085bf70b8b9f6c1#200fbd25894e9000451b0c562085bf70b8b9f6c1" +source = "git+https://github.com/ankitects/PyOxidizer.git?rev=eb26dd7cd1290de6503869f3d719eabcec45e139#eb26dd7cd1290de6503869f3d719eabcec45e139" dependencies = [ "anyhow", "spdx", diff --git a/qt/package/Cargo.toml b/qt/package/Cargo.toml index 2b1e37808..fcc42cbe9 100644 --- a/qt/package/Cargo.toml +++ b/qt/package/Cargo.toml @@ -11,7 +11,7 @@ libc-stdhandle = "=0.1.0" [dependencies.pyembed] git = "https://github.com/ankitects/PyOxidizer.git" -rev = "200fbd25894e9000451b0c562085bf70b8b9f6c1" +rev = "eb26dd7cd1290de6503869f3d719eabcec45e139" default-features = false [dependencies.jemallocator] diff --git a/qt/package/build.py b/qt/package/build.py index 17df9bd2b..1d7dde1c9 100644 --- a/qt/package/build.py +++ b/qt/package/build.py @@ -1,6 +1,9 @@ # Copyright: Ankitects Pty Ltd and contributors # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +from __future__ import annotations + import glob import os import platform @@ -38,7 +41,9 @@ os.environ["CARGO_TARGET_DIR"] = str(cargo_target) # OS-specific things pyqt5_folder_name = "pyqt515" +pyqt6_folder_path = bazel_external / "pyqt6" / "PyQt6" is_lin = False +arm64_linux = False if is_win: os.environ["TARGET"] = "x86_64-pc-windows-msvc" elif sys.platform.startswith("darwin"): @@ -56,7 +61,12 @@ else: os.environ["TARGET"] = "x86_64-unknown-linux-gnu" else: os.environ["TARGET"] = "aarch64-unknown-linux-gnu" - raise Exception("building on this architecture is not currently supported") + pyqt5_folder_name = None + arm64_linux = True + # path to a custom-built/prepared PyQt5 folder + # must be provided + pyqt6_folder_path = os.getenv("PREPARED_QT_PATH") + assert pyqt6_folder_path python = python_bin_folder / "python" @@ -80,7 +90,7 @@ def build_pyoxidizer(): "https://github.com/ankitects/PyOxidizer.git", "--rev", # when updating, make sure Cargo.toml updated too - "200fbd25894e9000451b0c562085bf70b8b9f6c1", + "eb26dd7cd1290de6503869f3d719eabcec45e139", "pyoxidizer", ], check=True, @@ -117,6 +127,10 @@ def install_wheels_into_venv(): subprocess.run( [pip, "install", "--force-reinstall", "--no-deps", protobuf], check=True ) + if arm64_linux: + # orjson doesn't get packaged correctly; remove it and we'll + # copy a copy in later + subprocess.run([pip, "uninstall", "-y", "orjson"], check=True) def build_artifacts(): @@ -225,6 +239,25 @@ def merge_into_dist(output_folder: Path, pyqt_src_path: Path): ], check=True, ) + # Linux ARM workarounds + if arm64_linux: + with open(output_folder / "qt.conf", "w") as file: + file.write( + """[Paths] +Prefix = lib/PyQt5/Qt5 +""" + ) + # copy orjson ends up broken; copy from venv + subprocess.run( + [ + "rsync", + "-a", + "--delete", + os.path.expanduser("~/orjson"), + output_folder / "lib/", + ], + check=True, + ) # Ensure all files are world-readable if not is_win: subprocess.run(["chmod", "-R", "a+r", output_folder]) @@ -234,6 +267,6 @@ build_pyoxidizer() install_wheels_into_venv() build_artifacts() build_pkg() -merge_into_dist(dist_folder / "std", bazel_external / "pyqt6" / "PyQt6") +merge_into_dist(dist_folder / "std", pyqt6_folder_path) if pyqt5_folder_name: merge_into_dist(dist_folder / "alt", bazel_external / pyqt5_folder_name / "PyQt5") diff --git a/qt/package/prepare-system-pyqt.sh b/qt/package/prepare-system-pyqt.sh new file mode 100644 index 000000000..7dee44aa9 --- /dev/null +++ b/qt/package/prepare-system-pyqt.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# This script copies a system-installed PyQt. Written for Debian Bullseye; +# will need adjusting for other platforms. + +set -e + +sudo apt install -y python3-pyqt5.{qtwebengine,qtmultimedia} patchelf + +pyqtBase=/usr/lib/python3/dist-packages/PyQt5 +qtData=/usr/share/qt5 +qtLibBase=/usr/lib/aarch64-linux-gnu +qtLibExtra=$qtLibBase/qt5 + +outDir=~/PyQtPrepared/PyQt5/ +qtOutputBase=$outDir/Qt5 +rm -rf $outDir +mkdir -p $qtOutputBase + +# pyqt +rsync -ai --exclude-from=qt.exclude --exclude Qt5 \ + $pyqtBase/ $outDir/ +patchelf --set-rpath '$ORIGIN/Qt5/lib' $outDir/*.so + +# qt libs +rsync -ai $qtLibBase/libQt5* $qtOutputBase/lib/ +patchelf --set-rpath '$ORIGIN' $qtOutputBase/lib/*.so.* + +# qt libexec/plugins +rsync -ai --exclude=qml $qtLibExtra/ $qtOutputBase/ +patchelf --set-rpath '$ORIGIN/../../lib' $qtOutputBase/plugins/*/*.so +patchelf --set-rpath '$ORIGIN/../lib' $qtOutputBase/libexec/QtWebEngineProcess +cat > $qtOutputBase/libexec/qt.conf <