Update the AppImage build scripts (#2392)

This commit is contained in:
Veronica Berglyd Olsen
2025-06-09 22:52:17 +02:00
committed by GitHub
13 changed files with 173 additions and 196 deletions
+13 -4
View File
@@ -10,15 +10,21 @@ jobs:
needs: buildAssets needs: buildAssets
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.13"
LINUX_TAG: "manylinux_2_28_x86_64" LINUX_TAG: "manylinux_2_28"
LINUX_ARCH: "x86_64"
steps: steps:
- name: Python Setup - name: Python Setup
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: "3.11" python-version: "3.13"
architecture: x64 architecture: x64
- name: Install Packages (apt)
run: |
sudo apt update
sudo apt install libxcb-cursor0
- name: Install Packages (pip) - name: Install Packages (pip)
run: pip install python-appimage setuptools run: pip install python-appimage setuptools
@@ -34,8 +40,11 @@ jobs:
- name: Build AppImage - name: Build AppImage
id: build id: build
run: | run: |
wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$LINUX_ARCH.AppImage
chmod +x appimagetool-$LINUX_ARCH.AppImage
export APPIMAGE_TOOL_EXEC="$(pwd)/appimagetool-$LINUX_ARCH.AppImage"
echo "BUILD_VERSION=$(python pkgutils.py version)" >> $GITHUB_OUTPUT echo "BUILD_VERSION=$(python pkgutils.py version)" >> $GITHUB_OUTPUT
python pkgutils.py build-appimage --linux-tag $LINUX_TAG --python-version $PYTHON_VERSION python pkgutils.py build-appimage $LINUX_TAG $LINUX_ARCH $PYTHON_VERSION
- name: Upload Artifacts - name: Upload Artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
+6 -18
View File
@@ -272,24 +272,12 @@ if __name__ == "__main__":
cmdBuildUbuntu.set_defaults(func=utils.build_debian.launchpad) cmdBuildUbuntu.set_defaults(func=utils.build_debian.launchpad)
# Build AppImage # Build AppImage
cmdBuildAppImage = parsers.add_parser( # See https://github.com/pypa/manylinux
"build-appimage", help=( # See https://python-appimage.readthedocs.io/en/latest/#available-python-appimages
"Build an AppImage. " cmdBuildAppImage = parsers.add_parser("build-appimage", help="Build an AppImage.")
"Argument --linux-tag defaults manylinux_2_28_x86_64, and --python-version to 3.13." cmdBuildAppImage.add_argument("linux", help="Manylinux version, e.g. manylinux_2_28.")
) cmdBuildAppImage.add_argument("arch", help="Architecture, e.g. x86_64.")
) cmdBuildAppImage.add_argument("python", help="Python version, e.g. 3.13.")
cmdBuildAppImage.add_argument(
"--linux-tag",
default="manylinux_2_28_x86_64",
help=(
"Linux compatibility tag (e.g. manylinux_2_28_x86_64) "
"see https://python-appimage.readthedocs.io/en/latest/#available-python-appimages "
"and https://github.com/pypa/manylinux for a list of valid tags."
),
)
cmdBuildAppImage.add_argument(
"--python-version", default="3.13", help="Python version (e.g. 3.13)"
)
cmdBuildAppImage.set_defaults(func=utils.build_appimage.appImage) cmdBuildAppImage.set_defaults(func=utils.build_appimage.appImage)
# Build Windows Inno Setup Installer # Build Windows Inno Setup Installer
+1 -1
View File
@@ -7,7 +7,7 @@ name = "novelWriter"
authors = [ authors = [
{name = "Veronica Berglyd Olsen", email = "code@vkbo.net"}, {name = "Veronica Berglyd Olsen", email = "code@vkbo.net"},
] ]
description = "A markdown-like text editor for planning and writing novels" description = "A plain text editor for planning and writing novels"
readme = {file = "setup/description_pypi.md", content-type = "text/markdown"} readme = {file = "setup/description_pypi.md", content-type = "text/markdown"}
license = {text = "GNU General Public License v3"} license = {text = "GNU General Public License v3"}
classifiers = [ classifiers = [
+1 -1
View File
@@ -24,7 +24,7 @@ cat > $HOME/.local/share/applications/novelWriter.desktop <<EOF
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name=novelWriter Name=novelWriter
Comment=A markdown-like text editor for planning and writing novels Comment=A plain text editor for planning and writing novels
Exec=${IMGPATH} %f Exec=${IMGPATH} %f
Icon=${ICONPATH} Icon=${ICONPATH}
Categories=Qt;Office;WordProcessor; Categories=Qt;Office;WordProcessor;
+1 -1
View File
@@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name=novelWriter Name=novelWriter
Comment=A markdown-like text editor for planning and writing novels Comment=A plain text editor for planning and writing novels
Exec=novelwriter %f Exec=novelwriter %f
Icon=novelwriter Icon=novelwriter
Categories=Qt;Office;WordProcessor; Categories=Qt;Office;WordProcessor;
+1 -7
View File
@@ -10,10 +10,4 @@ X-Python3-Version: >= 3.10
Package: novelwriter Package: novelwriter
Architecture: all Architecture: all
Depends: ${misc:Depends}, ${python3:Depends}, python3 (>=3.10), python3-pyqt6 (>= 6.4), python3-pyqt6.qtsvg (>= 6.4), python3-enchant (>= 2.0) Depends: ${misc:Depends}, ${python3:Depends}, python3 (>=3.10), python3-pyqt6 (>= 6.4), python3-pyqt6.qtsvg (>= 6.4), python3-enchant (>= 2.0)
Description: A markdown-like text editor for planning and writing novels Description: A plain text editor for planning and writing novels
novelWriter is a plain text editor designed for writing novels assembled from
many smaller text documents. It uses a minimal formatting syntax inspired by
Markdown, and adds a meta data syntax for comments, synopsis, and
cross-referencing. It's designed to be a simple text editor that allows for
easy organisation of text and notes, using human readable text files as
storage for robustness.
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

+1 -1
View File
@@ -11,7 +11,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>novelWriter</string> <string>novelWriter</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>novelWriter: A markdown-like text editor for planning and writing novels.</string> <string>novelWriter: A plain text editor for planning and writing novels.</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>novelwriter.icns</string> <string>novelwriter.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
+4 -4
View File
@@ -174,7 +174,7 @@ rm lib/python3.*/site-packages/PyQt6/QtWebEngine* || true
rm -r lib/python3.*/site-packages/PyQt6/Qt6/translations/qtwebengine* || true rm -r lib/python3.*/site-packages/PyQt6/Qt6/translations/qtwebengine* || true
rm -r lib/python3.*/site-packages/PyQt6/Qt6/plugins/webview/libqtwebview* || true rm -r lib/python3.*/site-packages/PyQt6/Qt6/plugins/webview/libqtwebview* || true
# Remove unneeded QtQuick/Decaritive components # Remove unneeded QtQuick/Declarative components
rm lib/python3.*/site-packages/PyQt6/QtQml* || true rm lib/python3.*/site-packages/PyQt6/QtQml* || true
rm lib/python3.*/site-packages/PyQt6/QtQuick* || true rm lib/python3.*/site-packages/PyQt6/QtQuick* || true
rm lib/python3.*/site-packages/PyQt6/WebChannel* || true rm lib/python3.*/site-packages/PyQt6/WebChannel* || true
@@ -200,16 +200,16 @@ mkdir -p $RLS_DIR
# --- Create DMG -------------------------------------------------------------------------------- # # --- Create DMG -------------------------------------------------------------------------------- #
# Generate .dmg # Generate .dmg
echo "Packageing DMG ..." echo "Packaging DMG ..."
brew install create-dmg brew install create-dmg
create-dmg --volname "novelWriter $VERSION" --volicon $SRC_DIR/setup/macos/novelwriter.icns \ create-dmg --volname "novelWriter $VERSION" --volicon $SRC_DIR/setup/macos/novelwriter.icns \
--window-pos 200 120 --window-size 800 400 --icon-size 100 \ --window-pos 200 120 --window-size 800 400 --icon-size 100 \
--icon novelWriter.app 200 190 --hide-extension novelWriter.app \ --icon novelWriter.app 200 190 --hide-extension novelWriter.app \
--app-drop-link 600 185 $RLS_DIR/novelWriter-"${VERSION}"-$ARCH.dmg "$BUILD_DIR"/ --app-drop-link 600 185 $RLS_DIR/novelwriter-"${VERSION}"-$ARCH.dmg "$BUILD_DIR"/
pushd $RLS_DIR || exit 1 pushd $RLS_DIR || exit 1
shasum -a 256 novelWriter-"${VERSION}"-$ARCH.dmg | tee novelWriter-"${VERSION}"-$ARCH.dmg.sha256 shasum -a 256 novelwriter-"${VERSION}"-$ARCH.dmg | tee novelwriter-"${VERSION}"-$ARCH.dmg.sha256
popd || exit 1 popd || exit 1
rm -r $CONDA_PATH rm -r $CONDA_PATH
+46 -71
View File
@@ -22,13 +22,16 @@ from __future__ import annotations
import argparse import argparse
import datetime import datetime
import os
import shutil import shutil
import subprocess
import sys import sys
from pathlib import Path
from utils.common import ( from utils.common import (
ROOT_DIR, SETUP_DIR, appdataXml, copyPackageFiles, copySourceCode, ROOT_DIR, SETUP_DIR, appdataXml, copyPackageFiles, copySourceCode,
extractVersion, makeCheckSum, toUpload, writeFile extractVersion, freshFolder, makeCheckSum, removeRedundantQt, systemCall,
toUpload, writeFile
) )
@@ -49,115 +52,87 @@ def appImage(args: argparse.Namespace) -> None:
print("") print("")
print("Build AppImage") print("Build AppImage")
print("==============") print("="*120)
print("")
linuxTag = args.linux_tag mLinux = args.linux
pythonVer = args.python_version mArch = args.arch
pyVer = args.python
# Version Info # Version Info
# ============
pkgVers, _, relDate = extractVersion() pkgVers, _, relDate = extractVersion()
relDate = datetime.datetime.strptime(relDate, "%Y-%m-%d") relDate = datetime.datetime.strptime(relDate, "%Y-%m-%d")
print("")
# Set Up Folder # Set Up Folder
# =============
bldDir = ROOT_DIR / "dist_appimage" bldDir = ROOT_DIR / "dist_appimage"
bldPkg = f"novelwriter_{pkgVers}" bldPkg = f"novelwriter-{pkgVers}-{mArch}"
bldImg = f"{bldPkg}.AppImage"
outDir = bldDir / bldPkg outDir = bldDir / bldPkg
imgDir = bldDir / "appimage" imgDir = bldDir / "appimage"
appDir = bldDir / f"novelWriter-{mArch}"
# Set Up Folders
# ==============
bldDir.mkdir(exist_ok=True) bldDir.mkdir(exist_ok=True)
freshFolder(outDir)
if outDir.exists(): freshFolder(imgDir)
print("Removing old build files ...") freshFolder(appDir)
print("")
shutil.rmtree(outDir)
outDir.mkdir()
if imgDir.exists():
print("Removing old build metadata files ...")
print("")
shutil.rmtree(imgDir)
imgDir.mkdir()
# Remove old AppImages # Remove old AppImages
if images := bldDir.glob("*.AppImage"): if images := bldDir.glob("*.AppImage"):
print("Removing old AppImages") print("Removing old AppImages")
print("")
for image in images: for image in images:
image.unlink() image.unlink()
# Copy novelWriter Source # Copy novelWriter Source
# =======================
print("Copying novelWriter source ...") print("Copying novelWriter source ...")
print("")
copySourceCode(outDir) copySourceCode(outDir)
print("")
print("Copying or generating additional files ...") print("Copying or generating additional files ...")
print("")
copyPackageFiles(outDir) copyPackageFiles(outDir)
# Write Metadata # Write Metadata
# ==============
writeFile(imgDir / "novelwriter.appdata.xml", appdataXml()) writeFile(imgDir / "novelwriter.appdata.xml", appdataXml())
print("Wrote: novelwriter.appdata.xml") writeFile(imgDir / "requirements.txt", str(outDir))
writeFile(imgDir / "entrypoint.sh", ( writeFile(imgDir / "entrypoint.sh", (
'#! /bin/bash \n' # f"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{APPDIR}}/usr/lib/{mArch}-linux-gnu/\n"
'{{ python-executable }} -sE ${APPDIR}/opt/python{{ python-version }}/bin/novelwriter "$@"' '{{ python-executable }} -sE ${APPDIR}/opt/python{{ python-version }}/bin/novelwriter "$@"'
)) ))
print("Wrote: entrypoint.sh")
writeFile(imgDir / "requirements.txt", str(outDir))
print("Wrote: requirements.txt")
shutil.copyfile(SETUP_DIR / "data" / "novelwriter.desktop", imgDir / "novelwriter.desktop") shutil.copyfile(SETUP_DIR / "data" / "novelwriter.desktop", imgDir / "novelwriter.desktop")
print("Copied: novelwriter.desktop") print("Copied: novelwriter.desktop")
shutil.copyfile(SETUP_DIR / "icons" / "novelwriter.svg", imgDir / "novelwriter.svg") shutil.copyfile(SETUP_DIR / "icons" / "novelwriter.png", imgDir / "novelwriter.png")
print("Copied: novelwriter.svg")
shutil.copyfile(
SETUP_DIR / "data" / "hicolor" / "256x256" / "apps" / "novelwriter.png",
imgDir / "novelwriter.png"
)
print("Copied: novelwriter.png") print("Copied: novelwriter.png")
# Build AppImage # Build AppDir
# ============== systemCall([
sys.executable, "-m", "python_appimage", "build", "app", "--no-packaging",
"-l", f"{mLinux}_{mArch}", "-p", pyVer, "appimage"
], cwd=bldDir)
try: # Copy Libraries
subprocess.call([ libPath = Path(f"/usr/lib/{mArch}-linux-gnu")
sys.executable, "-m", "python_appimage", "build", "app", siteDir = appDir / "opt" / f"python{pyVer}" / "lib" / f"python{pyVer}" / "site-packages"
"-l", linuxTag, "-p", pythonVer, "appimage" qt6Lib = siteDir / "PyQt6" / "Qt6" / "lib"
], cwd=bldDir) shutil.copyfile(libPath / "libxcb-cursor.so.0", qt6Lib / "libxcb-cursor.so.0")
except Exception as exc:
print("AppImage build: FAILED")
print("")
print(str(exc))
print("")
sys.exit(1)
bldFile = list(bldDir.glob("*.AppImage"))[0] # Remove Redundant
outFile = bldDir / f"novelWriter-{pkgVers}.AppImage" removeRedundantQt(siteDir)
bldFile.rename(outFile)
shaFile = makeCheckSum(outFile.name, cwd=bldDir)
toUpload(outFile) # Build Image
appToolExec = os.environ.get("APPIMAGE_TOOL_EXEC", "appimagetool")
env = os.environ.copy()
env["ARCH"] = mArch
systemCall([
appToolExec, "--no-appstream", "--updateinformation",
f"gh-releases-zsync|vkbo|novelwriter|latest|novelwriter-*-{mArch}.AppImage.zsync",
str(appDir), bldImg
], cwd=bldDir, env=env)
updFile = bldDir / f"{bldImg}.zsync"
bldFile = bldDir / bldImg
shaFile = makeCheckSum(bldFile.name, cwd=bldDir)
toUpload(bldFile)
toUpload(updFile)
toUpload(shaFile) toUpload(shaFile)
return return
+4 -80
View File
@@ -30,7 +30,10 @@ import zipfile
from pathlib import Path from pathlib import Path
from utils.common import ROOT_DIR, SETUP_DIR, copySourceCode, extractVersion, readFile, writeFile from utils.common import (
ROOT_DIR, SETUP_DIR, copySourceCode, extractVersion, readFile,
removeRedundantQt, writeFile
)
def prepareCode(outDir: Path) -> None: def prepareCode(outDir: Path) -> None:
@@ -103,85 +106,6 @@ def installRequirements(libDir: Path) -> None:
return return
def removeRedundantQt(libDir: Path) -> None:
"""Delete Qt files that are not needed"""
def unlinkIfFound(file: Path) -> None:
if file.is_file():
file.unlink()
print(f"Deleted: {file}")
def deleteFolder(folder: Path) -> None:
if folder.is_dir():
shutil.rmtree(folder)
print(f"Deleted: {folder}")
def unlinkIfPrefix(folder: Path, prefix: tuple[str, ...]) -> None:
if folder.is_dir():
for item in folder.iterdir():
if item.name.startswith(prefix):
if item.is_file():
unlinkIfFound(item)
elif item.is_dir():
deleteFolder(item)
print("Deleting Redundant Files")
print("========================")
print("")
pyQt6Dir = libDir / "PyQt6"
bindDir = libDir / "PyQt6" / "bindings"
qt6Dir = libDir / "PyQt6" / "Qt6"
binDir = libDir / "PyQt6" / "Qt6" / "bin"
plugDir = libDir / "PyQt6" / "Qt6" / "plugins"
qmDir = libDir / "PyQt6" / "Qt6" / "translations"
dictDir = libDir / "enchant" / "data" / "mingw64" / "share" / "enchant" / "hunspell"
for item in dictDir.iterdir():
if not item.name.startswith(("en_GB", "en_US")):
unlinkIfFound(item)
for item in qmDir.iterdir():
if not item.name.startswith("qtbase"):
unlinkIfFound(item)
bulkDel = ("QtQml", "Qt6Qml", "QtQuick", "Qt6Quick")
unlinkIfPrefix(pyQt6Dir, bulkDel)
unlinkIfPrefix(bindDir, bulkDel)
unlinkIfPrefix(binDir, bulkDel)
delQt6 = [
"Qt6Bluetooth", "Qt6DBus", "Qt6Designer", "Qt6Help", "Qt6Multimedia",
"Qt6MultimediaWidgets", "Qt6Network", "Qt6Nfc", "Qt6OpenGL", "Qt6Positioning",
"Qt6PositioningQuick", "Qt6Sensors", "Qt6SerialPort", "Qt6Sql", "Qt6Test",
"Qt6TextToSpeech", "Qt6WebChannel", "Qt6WebSockets", "Qt6Xml",
]
for item in delQt6:
qtItem = item.replace("Qt6", "Qt")
unlinkIfFound(binDir / f"{item}.dll")
unlinkIfFound(pyQt6Dir / f"{qtItem}.pyd")
unlinkIfFound(pyQt6Dir / f"{qtItem}.pyi")
deleteFolder(bindDir / qtItem)
delList = [
binDir / "opengl32sw.dll",
qt6Dir / "qml",
plugDir / "renderers",
plugDir / "sensors",
plugDir / "sqldrivers",
plugDir / "texttospeech",
plugDir / "webview",
]
for item in delList:
unlinkIfFound(item)
deleteFolder(item)
print("Done")
print("")
return
def main(args: argparse.Namespace) -> None: def main(args: argparse.Namespace) -> None:
"""Set up a package with embedded Python and dependencies for """Set up a package with embedded Python and dependencies for
Windows installation. Windows installation.
+95 -8
View File
@@ -22,6 +22,7 @@ from __future__ import annotations
import shutil import shutil
import subprocess import subprocess
import sys
from pathlib import Path from pathlib import Path
@@ -77,16 +78,16 @@ def copySourceCode(dst: Path) -> None:
for item in src.glob("**/*"): for item in src.glob("**/*"):
relSrc = item.relative_to(ROOT_DIR) relSrc = item.relative_to(ROOT_DIR)
if item.suffix in (".pyc", ".pyo"): if item.suffix in (".pyc", ".pyo"):
print(f"Ignore: {relSrc}") print("Ignored:", relSrc)
continue continue
if item.parent.is_dir() and item.parent.name != "__pycache__": if item.parent.is_dir() and item.parent.name != "__pycache__":
dstDir = dst / relSrc.parent dstDir = dst / relSrc.parent
if not dstDir.exists(): if not dstDir.exists():
dstDir.mkdir(parents=True) dstDir.mkdir(parents=True)
print(f"Folder: {dstDir}") print("Created:", dstDir.relative_to(ROOT_DIR))
if item.is_file(): if item.is_file():
shutil.copyfile(item, dst / relSrc) shutil.copyfile(item, dst / relSrc)
print(f"Copied: {dst / relSrc}") print("Copied:", relSrc)
return return
@@ -95,26 +96,23 @@ def copyPackageFiles(dst: Path, setupPy: bool = False) -> None:
copyFiles = ["LICENSE.md", "CREDITS.md", "pyproject.toml"] copyFiles = ["LICENSE.md", "CREDITS.md", "pyproject.toml"]
for copyFile in copyFiles: for copyFile in copyFiles:
shutil.copyfile(copyFile, dst / copyFile) shutil.copyfile(copyFile, dst / copyFile)
print(f"Copied: {copyFile}") print("Copied:", copyFile)
writeFile(dst / "MANIFEST.in", ( writeFile(dst / "MANIFEST.in", (
"include LICENSE.md\n" "include LICENSE.md\n"
"include CREDITS.md\n" "include CREDITS.md\n"
"recursive-include novelwriter/assets *\n" "recursive-include novelwriter/assets *\n"
)) ))
print("Wrote: MANIFEST.in")
if setupPy: if setupPy:
writeFile(dst / "setup.py", ( writeFile(dst / "setup.py", (
"import setuptools\n" "import setuptools\n"
"setuptools.setup()\n" "setuptools.setup()\n"
)) ))
print("Wrote: setup.py")
text = readFile(ROOT_DIR / "pyproject.toml") text = readFile(ROOT_DIR / "pyproject.toml")
text = text.replace("setup/description_pypi.md", "data/description_short.txt") text = text.replace("setup/description_pypi.md", "data/description_short.txt")
writeFile(dst / "pyproject.toml", text) writeFile(dst / "pyproject.toml", text)
print("Wrote: pyproject.toml")
return return
@@ -188,4 +186,93 @@ def readFile(file: Path) -> str:
def writeFile(file: Path, text: str) -> int: def writeFile(file: Path, text: str) -> int:
"""Write string to file.""" """Write string to file."""
return file.write_text(text, encoding="utf-8") result = file.write_text(text, encoding="utf-8")
print("Wrote:", file.relative_to(ROOT_DIR))
return result
def freshFolder(path: Path) -> None:
"""Make sure a folder exists and is empty."""
if path.exists():
print("Removing:", str(path))
shutil.rmtree(path)
path.mkdir()
return
def systemCall(cmd: list, cwd: Path | str | None = None, env: dict | None = None) -> None:
"""Make a system call using subprocess."""
if isinstance(cwd, Path):
cwd = str(cwd)
try:
subprocess.call([str(c) for c in cmd], cwd=cwd, env=env)
except Exception as exc:
print("ERROR:", str(exc))
sys.exit(1)
return
def removeRedundantQt(qtBase: Path) -> None:
"""Delete Qt files that are not needed"""
def unlinkIfFound(file: Path) -> None:
if file.is_file():
file.unlink()
print("Deleted:", file.relative_to(ROOT_DIR))
def deleteFolder(folder: Path) -> None:
if folder.is_dir():
shutil.rmtree(folder)
print("Deleted:", folder.relative_to(ROOT_DIR))
def unlinkIfPrefix(folder: Path, prefix: tuple[str, ...]) -> None:
if folder.is_dir():
for item in folder.iterdir():
if item.name.startswith(prefix):
if item.is_file():
unlinkIfFound(item)
elif item.is_dir():
deleteFolder(item)
print("Deleting redundant files ...")
pyQt6Dir = qtBase / "PyQt6"
bindDir = qtBase / "PyQt6" / "bindings"
qt6Dir = qtBase / "PyQt6" / "Qt6"
binDir = qtBase / "PyQt6" / "Qt6" / "bin"
libDir = qtBase / "PyQt6" / "Qt6" / "lib"
plugDir = qtBase / "PyQt6" / "Qt6" / "plugins"
qmDir = qtBase / "PyQt6" / "Qt6" / "translations"
dictDir = qtBase / "enchant" / "data" / "mingw64" / "share" / "enchant" / "hunspell"
# Prune Dictionaries
if dictDir.exists():
for item in dictDir.iterdir():
if not item.name.startswith(("en_GB", "en_US")):
unlinkIfFound(item)
# Prune Translations
for item in qmDir.iterdir():
if not item.name.startswith("qtbase"):
unlinkIfFound(item)
# Delete Modules
modules = [
"Qt6Qml", "Qt6Quick", "Qt6Bluetooth", "Qt6Nfc",
"Qt6Sensors", "Qt6SerialPort", "Qt6Test",
]
modules.extend([x.replace("Qt6", "Qt") for x in modules])
modules.extend([f"lib{x}" for x in modules])
modules = tuple(modules)
unlinkIfPrefix(pyQt6Dir, modules)
unlinkIfPrefix(bindDir, modules)
unlinkIfPrefix(binDir, modules)
unlinkIfPrefix(libDir, modules)
# Other Files
deleteFolder(qt6Dir / "qml")
deleteFolder(plugDir / "qmlls")
deleteFolder(plugDir / "qmllint")
return