1
0

mac build: fix broken symlinks inside .app, due to rm-ed qt parts

probably since qt6 migration many symlinks inside the .app in bundled PyQt were broken:
```
$ cp -r $HOME/electrum/dist/Electrum.app Electrum-ghost3.app
cp: /Users/vagrant/electrum/dist/Electrum.app/Contents/Resources/PyQt6/Qt6/lib/QtMultimediaQuick.framework/QtMultimediaQuick: No such file or directory
cp: /Users/vagrant/electrum/dist/Electrum.app/Contents/Resources/PyQt6/Qt6/lib/QtQuickTimeline.framework/QtQuickTimeline: No such file or directory
cp: /Users/vagrant/electrum/dist/Electrum.app/Contents/Resources/PyQt6/Qt6/lib/QtQuickControls2.framework/QtQuickControls2: No such file or directory
```
We were stripping out lots of datas/binaries from Qt from the mac build artifact, leaving behind dangling symlinks.

Instead of adding more hacks on top of the current hacks to also rm the dangling links, I tried to clean up this blacklisting.

There was no issue re the Windows build, no symlinks there, but I like to keep these two spec files in sync.

-----

Some numbers:
- mac:
  - without any exclusions at all, the mac .dmg is 80 MiB.
  - with these exclusions it is 57 MiB.
- win:
  - (haven't built without exclusions.)
  - with the previous stripping strategy, exes were 68M/68M/50M
  - with these exclusions, exes are 66M/66M/50M
This commit is contained in:
SomberNight
2025-06-11 21:32:39 +00:00
parent 2645456130
commit b6e4ec8f95
2 changed files with 50 additions and 64 deletions

View File

@@ -52,6 +52,28 @@ datas += collect_data_files('bitbox02')
# some deps rely on importlib metadata
datas += copy_metadata('slip10') # from trezor->slip10
# Exclude parts of Qt that we never use. Reduces binary size by tens of MBs. see #4815
excludes = [
"PyQt6.QtBluetooth",
"PyQt6.QtDesigner",
"PyQt6.QtNetwork",
"PyQt6.QtNfc",
"PyQt6.QtPositioning",
"PyQt6.QtQml",
"PyQt6.QtQuick",
"PyQt6.QtQuick3D",
"PyQt6.QtQuickWidgets",
"PyQt6.QtRemoteObjects",
"PyQt6.QtSensors",
"PyQt6.QtSerialPort",
"PyQt6.QtSpatialAudio",
"PyQt6.QtSql",
"PyQt6.QtTest",
"PyQt6.QtTextToSpeech",
"PyQt6.QtWebChannel",
"PyQt6.QtWebSockets",
"PyQt6.QtXml",
]
# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports
a = Analysis([f"{PROJECT_ROOT}/{MAIN_SCRIPT}",
@@ -68,7 +90,9 @@ a = Analysis([f"{PROJECT_ROOT}/{MAIN_SCRIPT}",
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[])
hookspath=[],
excludes=excludes,
)
# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal
@@ -77,38 +101,6 @@ for d in a.datas:
a.datas.remove(d)
break
# Strip out parts of Qt that we never use. Reduces binary size by tens of MBs. see #4815
qt_bins2remove=(
r'pyqt6\qt6\qml',
r'pyqt6\qt6\bin\qt6quick',
r'pyqt6\qt6\bin\qt6qml',
r'pyqt6\qt6\bin\qt6multimediaquick',
r'pyqt6\qt6\bin\qt6pdfquick',
r'pyqt6\qt6\bin\qt6positioning',
r'pyqt6\qt6\bin\qt6spatialaudio',
r'pyqt6\qt6\bin\qt6shadertools',
r'pyqt6\qt6\bin\qt6sensors',
r'pyqt6\qt6\bin\qt6web',
r'pyqt6\qt6\bin\qt6test',
)
print("Removing Qt binaries:", *qt_bins2remove)
for x in a.binaries.copy():
for r in qt_bins2remove:
if x[0].lower().startswith(r):
a.binaries.remove(x)
print('----> Removed x =', x)
qt_data2remove=(
r'pyqt6\qt6\translations\qtwebengine_locales',
r'pyqt6\qt6\qml',
)
print("Removing Qt datas:", *qt_data2remove)
for x in a.datas.copy():
for r in qt_data2remove:
if x[0].lower().startswith(r):
a.datas.remove(x)
print('----> Removed x =', x)
# hotfix for #3171 (pre-Win10 binaries)
a.binaries = [x for x in a.binaries if not x[1].lower().startswith(r'c:\windows')]

View File

@@ -55,6 +55,28 @@ datas += collect_data_files('bitbox02')
# some deps rely on importlib metadata
datas += copy_metadata('slip10') # from trezor->slip10
# Exclude parts of Qt that we never use. Reduces binary size by tens of MBs. see #4815
excludes = [
"PyQt6.QtBluetooth",
"PyQt6.QtDesigner",
"PyQt6.QtNetwork",
"PyQt6.QtNfc",
"PyQt6.QtPositioning",
"PyQt6.QtQml",
"PyQt6.QtQuick",
"PyQt6.QtQuick3D",
"PyQt6.QtQuickWidgets",
"PyQt6.QtRemoteObjects",
"PyQt6.QtSensors",
"PyQt6.QtSerialPort",
"PyQt6.QtSpatialAudio",
"PyQt6.QtSql",
"PyQt6.QtTest",
"PyQt6.QtTextToSpeech",
"PyQt6.QtWebChannel",
"PyQt6.QtWebSockets",
"PyQt6.QtXml",
]
# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports
a = Analysis([f"{PROJECT_ROOT}/{MAIN_SCRIPT}",
@@ -71,7 +93,9 @@ a = Analysis([f"{PROJECT_ROOT}/{MAIN_SCRIPT}",
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[])
hookspath=[],
excludes=excludes,
)
# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal
@@ -80,36 +104,6 @@ for d in a.datas:
a.datas.remove(d)
break
# Strip out parts of Qt that we never use. Reduces binary size by tens of MBs. see #4815
qt_bins2remove=(
'pyqt6/qt6/qml',
'pyqt6/qt6/lib/qtqml',
'pyqt6/qt6/lib/qtquick',
'pyqt6/qt6/lib/qtshadertools',
'pyqt6/qt6/lib/qtspatialaudio',
'pyqt6/qt6/lib/qtmultimediaquick',
'pyqt6/qt6/lib/qtweb',
'pyqt6/qt6/lib/qtpositioning',
'pyqt6/qt6/lib/qtsensors',
'pyqt6/qt6/lib/qtpdfquick',
'pyqt6/qt6/lib/qttest',
)
print("Removing Qt binaries:", *qt_bins2remove)
for x in a.binaries.copy():
for r in qt_bins2remove:
if x[0].lower().startswith(r):
a.binaries.remove(x)
print('----> Removed x =', x)
qt_data2remove=(
'pyqt6/qt6/qml',
)
print("Removing Qt datas:", *qt_data2remove)
for x in a.datas.copy():
for r in qt_data2remove:
if x[0].lower().startswith(r):
a.datas.remove(x)
print('----> Removed x =', x)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)