Switch to py2app

This commit is contained in:
Joey Yakimowich-Payne 2022-11-08 19:55:04 -07:00
commit 4687a12403
3 changed files with 143 additions and 25 deletions

View file

@ -210,17 +210,19 @@ jobs:
- name: Build
run: |
source venv/bin/activate
# python3 buildPy2app.py py2app
pyinstaller -w --noconfirm --hidden-import PySide6 \
--add-data "${{ env.PROJ_DIR }}/resources:." \
--icon "${{ env.PROJ_DIR }}/resources/icon.icns" \
--target-architecture universal2 \
--osx-bundle-identifier "${{ env.BUNDLE_ID }}" \
--hidden-import pkg_resources \
--distpath "${{ env.BUILD_DIR }}/ProjectMac" \
--onefile -n "${{ env.PROJECT_NAME }}" pyinstaller.py
ls -al "${{ env.BUILD_DIR }}/ProjectMac"
cp -r "${{ env.BUILD_DIR }}/ProjectMac/${{ env.PROJECT_NAME }}.app" "${{ env.PROJECT_NAME }}.app"
# py2app works better
python3 buildPy2app.py py2app
# pyinstaller -w --noconfirm --hidden-import PySide6 \
# --add-data "${{ env.PROJ_DIR }}/resources:." \
# --icon "${{ env.PROJ_DIR }}/resources/icon.icns" \
# --target-architecture universal2 \
# --osx-bundle-identifier "${{ env.BUNDLE_ID }}" \
# --hidden-import pkg_resources \
# --distpath "${{ env.BUILD_DIR }}/ProjectMac" \
# --onefile -n "${{ env.PROJECT_NAME }}" pyinstaller.py
ls -al "dist/"
mv "dist/${{ env.PROJECT_NAME }}.app" "${{ env.PROJECT_NAME }}.app"
python3 ci/cleandist.py "${{ env.PROJECT_NAME }}.app"
python3 ci/codesign.py "${{ env.PROJECT_NAME }}.app"
zip -r "${{ env.PROJECT_NAME }}-${{ env.VER }}.zip" "${{ env.PROJECT_NAME }}.app"

View file

@ -2,31 +2,25 @@ from setuptools import setup
from glob import glob
from datetime import datetime
module_name = "project"
name = "Project"
version = ""
main_file = "main.py"
bundle_identifier = "com.project.Project"
from project.info import main_module, name, version, main_file, bundle_identifier, module_name
# Overrides the above
exec(open("info.py").read())
APP = [f'{module_name}/{main_file}']
APP = [f'pyinstaller.py']
DATA_FILES = [
('resources', glob(module_name + '/resources/*.png') + glob(module_name + '/resources/*.rtf') + glob(module_name + '/resources/*.txt')),
('resources', glob(module_name + '/resources/*')),
]
OPTIONS = {
'arch': 'universal2',
'optimize': 2,
'iconfile': module_name + '/resources/icon.icns',
'extra_scripts': module_name + '/info.py',
'includes': {'PySide6.QtCore', 'PySide6.QtUiTools', 'PySide6.QtGui', 'PySide6.QtWidgets', 'certifi', 'cffi', 'pem'},
'excludes': {'tkinter'},
'includes': {'PySide6.QtCore', 'PySide6.QtUiTools', 'PySide6.QtGui', 'PySide6.QtWidgets', 'certifi', },
'excludes': {'tkinter', "unittest"},
'qt_plugins': [
'platforms/libqcocoa.dylib',
'platforms/libqminimal.dylib',
'platforms/libqoffscreen.dylib',
'styles/libqmacstyle.dylib'
],
'argv_emulation': True,
'plist': {
'CFBundleName': name,
'CFBundleShortVersionString': version,

122
ci/cleandist.py Normal file
View file

@ -0,0 +1,122 @@
import sys
import os
import platform
import shutil
from glob import glob
pyver = platform.python_version_tuple()[0] + '.' + platform.python_version_tuple()[1]
# Clean resources
def clean(glob_path: str = "", to_be_kept=None, to_be_deleted=None):
to_be_kept = to_be_kept or []
to_be_deleted = to_be_deleted or []
if to_be_kept and glob_path:
for f in glob(glob_path):
if not any({k in f for k in to_be_kept}):
to_be_deleted.append(f)
for p in to_be_deleted:
if os.path.exists(p):
if os.path.isdir(p):
shutil.rmtree(p, ignore_errors=True)
else:
os.remove(p)
def clean_resources(app_path: str):
PATH = '{app_path}/Contents/Resources/'
to_be_kept = []
to_be_deleted = []
clean(f'{PATH}/qt*', to_be_deleted=to_be_deleted, to_be_kept=to_be_kept)
def clean_pyside6(app_path: str):
# Clean PySide6 folder
PATH = f'{app_path}/Contents/Resources/lib/python{pyver}/PySide6'
shutil.rmtree(f'{PATH}/examples', ignore_errors=True)
shutil.rmtree(f'{PATH}/include', ignore_errors=True)
shutil.rmtree(f'{PATH}/Qt/libexec', ignore_errors=True)
to_be_kept = ['QtCore', 'QtGui', 'QtWidgets']
to_be_deleted = []
for f in glob(f'{PATH}/Qt*'):
if not any({k in f for k in to_be_kept}):
to_be_deleted.append(f)
for a in glob(f'{PATH}/*.app'):
to_be_deleted.append(a)
to_be_deleted.remove(f'{PATH}/Qt')
to_be_deleted.extend([
f'{PATH}/lupdate',
f'{PATH}/qmllint',
f'{PATH}/lrelease',
f'{PATH}/qmlformat',
f'{PATH}/qmlls',
])
clean(to_be_deleted=to_be_deleted)
def clean_qt(app_path: str):
# Clean PySide6/Qt folder
PATH = f'{app_path}/Contents/Resources/lib/python{pyver}/PySide6/Qt'
to_be_deleted = [f'{PATH}/qml', f'{PATH}/translations']
clean(to_be_deleted=to_be_deleted)
def clean_lib(app_path: str):
# Clean PySide6/Qt/lib folder
PATH = f'{app_path}/Contents/Resources/lib/python{pyver}/PySide6/Qt/lib'
to_be_kept = ['QtCore', 'QtDBus', 'QtGui', 'QtWidgets']
to_be_deleted = [f'{PATH}/metatypes']
clean(f'{PATH}/Qt*', to_be_kept=to_be_kept, to_be_deleted=to_be_deleted)
def clean_plugins(app_path: str):
# Clean PySide6/Qt/plugins folder
PATH = f'{app_path}/Contents/Resources/lib/python{pyver}/PySide6/Qt/plugins'
to_be_kept = ['platforms', 'styles']
to_be_deleted = []
clean(f'{PATH}/*', to_be_kept=to_be_kept, to_be_deleted=to_be_deleted)
def symlink_shiboken(app_path: str):
# symlink .so from shiboken6 to PySide6 folder
cwd = os.getcwd()
FROM = f'{app_path}/Contents/Resources/lib/python{pyver}/shiboken6'
TO = f'{app_path}/Contents/Resources/lib/python{pyver}/PySide6'
fn = os.path.basename(glob(f'{FROM}/libshiboken6*.dylib')[0])
os.chdir(TO)
os.symlink(f'../shiboken6/{fn}', f'./{fn}')
os.chdir(cwd)
def main():
app_path = sys.argv[1]
clean_resources(app_path)
clean_pyside6(app_path)
clean_qt(app_path)
clean_lib(app_path)
clean_plugins(app_path)
symlink_shiboken(app_path)
main()