diff --git a/.gitignore b/.gitignore index 66826bbde8..e496f23c08 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ deluge/ui/web/js/extjs/ext-extensions*.js osx/app RELEASE-VERSION .venv* +/packaging/osx/app +/packaging/osx/py2app-build +*.app +/py2app-build diff --git a/MANIFEST.in b/MANIFEST.in index d2d970fe61..11a920d658 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -23,7 +23,7 @@ recursive-exclude deluge/tests *.pyc graft deluge/ui/data recursive-exclude deluge/ui/data *.desktop *.xml -graft deluge/ui/gtkui/glade +graft deluge/ui/gtk3/glade include deluge/ui/web/index.html include deluge/ui/web/css/*.css diff --git a/packaging/osx/deluge-macports.bundle b/packaging/osx/deluge-macports.bundle new file mode 100644 index 0000000000..e323de7b1c --- /dev/null +++ b/packaging/osx/deluge-macports.bundle @@ -0,0 +1,51 @@ + + + + /opt/local + ${env:PY2APP_PREFIX} + ${env:DELUGEDIR} + ${env:PY2APP_PREFIX}/Resources/lib/python${env:PY2APP_PYTHON_VERSION} + app + gtk+-3.0 + ${project}/deluge-launcher + + ${project}/Info.plist + ${prefix:py2app}/MacOS/deluge-gtk + ${prefix:py2app}/MacOS/deluged + ${prefix:py2app}/MacOS/deluge-web + ${prefix:py2app}/MacOS/deluge-console + + ${prefix:py2app}/Frameworks/Python.framework/Versions/${env:PY2APP_PYTHON_VERSION}/Python + ${prefix:py2app}/MacOS/python + + + ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so + ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so + ${prefix:py2app}/Resources/include + ${prefix}/share/glib-2.0/schemas/gschemas.compiled + ${prefix:py2app}/Resources/*.so + ${prefix:py2app}/Resources/*.py* + ${prefix:py2app}/Resources/*.sh + ${prefix:py2app}/Frameworks/*.dylib + ${prefix}/lib/libgtkmacintegration-gtk3.2.dylib + ${prefix:py2app}/Resources/lib/python*.zip + ${prefix:py2app}/Resources/lib/python${env:PY2APP_PYTHON_VERSION} + ${prefix}/share/gir-1.0/*.gir + + ${prefix}/share/themes/McOS-MJV-Dark + ${prefix}/share/themes/McOS-MJV + ${prefix}/share/themes/Mac + Adwaita + hicolor + + ${project}/deluge.icns + ${project}/torrent.icns + + ${project}/deluge-launcher + ${project}/deluge-launcher + ${project}/deluge-launcher + ${prefix}/share/locale + ${prefix}/share/locale + ${prefix}/share/locale + ${prefix:deluge}/deluge/i18n + diff --git a/packaging/osx/gtkrc b/packaging/osx/gtkrc deleted file mode 100644 index a77430b685..0000000000 --- a/packaging/osx/gtkrc +++ /dev/null @@ -1,10 +0,0 @@ -gtk-theme-name = "Clearlooks" -gtk-enable-mnemonics = 0 - -# Workaround for non-ascii display issue details -# here: http://bugs.gramps-project.org/view.php?id=5474 -style "user-font" -{ - font_name="Arial Unicode MS" -} -widget_class "*" style "user-font" diff --git a/packaging/osx/make-app b/packaging/osx/make-app.sh similarity index 98% rename from packaging/osx/make-app rename to packaging/osx/make-app.sh index 9489f6c0dd..4585be09de 100644 --- a/packaging/osx/make-app +++ b/packaging/osx/make-app.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -o errexit APPDIR="./app/Deluge.app" RSCDIR="${APPDIR}/Contents/Resources" diff --git a/packaging/osx/make-macports-app.sh b/packaging/osx/make-macports-app.sh new file mode 100755 index 0000000000..b9b3ed665a --- /dev/null +++ b/packaging/osx/make-macports-app.sh @@ -0,0 +1,153 @@ +#!/bin/bash +set -o errexit + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "${SOURCE}" ] + do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "${SOURCE}" )" && pwd )" + SOURCE="$(readlink "${SOURCE}")" + [[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located + done +CURRDIR="$( cd -P "$( dirname "$SOURCE" )" && cd ../.. && pwd )" + +if [ -z "${BUILDDIR}" ]; then +export BUILDDIR="${CURRDIR}/py2app-build/" +fi + + +APPDIR="./app/Deluge.app" +RSCDIR="${APPDIR}/Contents/Resources" +LIBDIR="${RSCDIR}/lib" +VERSION=$(cat ../../RELEASE-VERSION) +YEAR=$(date +'%Y') + +export DELUGEDIR=$(cd ../../ && pwd) + +echo "DELUGEDIR: ${DELUGEDIR}" + +if [ -z "${PY2APP_PREFIX}" ]; then +export PY2APP_PREFIX="${BUILDDIR}/app/deluge.app/Contents/" +fi + + +function msg() { echo "==> $1"; } + +echo "*** Packaging Deluge.app to $APPDIR..." + +msg "Clearing build dir" +rm -fr $BUILDDIR + +msg "Clearing app dir" +rm -fr $APPDIR + +pushd ../../ +python3 setup.py clean --all +find ./ \( -name '__pycache__' -or -name 'build' \) -type d -ls -depth -delete +msg "Running build" +msg "Creating app skeleton" +python3 setup.py py2app --verbose --dist-dir "${BUILDDIR}/app" --no-strip --graph --xref --use-faulthandler --verbose-interpreter +msg "Creating Wheel" +python3 setup.py bdist_wheel --dist-dir "${BUILDDIR}/wheel" +rm -fv "${BUILDDIR}/app/deluge.app/Contents/MacOS/deluge" +python3 setup.py install_scripts --install-dir "${BUILDDIR}/app/deluge.app/Contents/MacOS/" +popd + +export PY2APP_PYTHON_VERSION=$("${PY2APP_PREFIX}/MacOS/python" --version | sed 's|Python ||' | cut -f 1,2 -d '.') + +SITEPACKAGES="/opt/local/Library/Frameworks/Python.framework/Versions/${PY2APP_PYTHON_VERSION}/lib/python${PY2APP_PYTHON_VERSION}/site-packages" + +msg "Create Info.plist for Deluge $version" +sed -e s/%VERSION%/$VERSION/ -e s/%YEAR%/$YEAR/ Info.plist.in > Info.plist + +msg "Calling gtk-mac-bundler to create the skeleton" +gtk-mac-bundler deluge-macports.bundle + +msg "Unzip site-packages and make python softlink without version number" +pushd ${LIBDIR} || exit 1 +ln -sf "./python${PY2APP_PYTHON_VERSION}" "./python" +unzip -nq python*.zip -d "./python/" +rm python*.zip +popd + +msg "Replacing deluge by its wheel..." +rm -fr "${LIBDIR}/python/deluge" +deluge_wheel="${BUILDDIR}/wheel/deluge*.whl" +unzip -nq ${deluge_wheel} -d "${LIBDIR}/python/" + +msg "Will now try to fix dependencies manually because gtk-mac-bundler sucks at that" +msg "First, let's fix the Python executable." + +install_name_tool -change "@executable_path/../Frameworks/Python.framework/Versions/${PY2APP_PYTHON_VERSION}/Python" "@rpath/libpython${PY2APP_PYTHON_VERSION}.dylib" "${APPDIR}/Contents/MacOS/python" + +msg "Generating charset.alias..." + +/opt/local/share/gettext/intl/config.charset $(uname -m)-apple-$(uname -s)-$(uname -r) > "${LIBDIR}/charset.alias" + +msg "Getting list of files to fix..." + +FILES=$( + find "${APPDIR}" -type f \ + | xargs file \ + | grep ' Mach-O '|awk -F ':' '{print $1}' +) +OLDPATH='\/opt\/local\/lib\/libgcc\/|\/opt\/local\/lib\/|@executable_path\/..\/Frameworks\/' +msg "Replacing pathnames and @executable_path/../Frameworks/ with @rpath/..." + +for file in $FILES +do + set -x + chmod 755 "${file}" + install_name_tool -id "@rpath/$(basename ${file})" "${file}" + ( install_name_tool -delete_rpath /opt/local/lib "${file}" 2>/dev/null || true) + ( install_name_tool -delete_rpath @executable_path/../Frameworks "${file}" 2>/dev/null || true) + ( install_name_tool -delete_rpath /opt/local/lib/libgcc "${file}" 2>/dev/null || true) + { set +x; } 2>/dev/null + otool -L "${file}" \ + | grep -E "\t${OLDPATH}" \ + | sed -E "s/${OLDPATH}//" \ + | awk -v fname="$file" -v old_path_1="/opt/local/lib/libgcc/" -v old_path_2="/opt/local/lib/" -v old_path_3="@executable_path/../Frameworks/" '{ \ + print "set -x\n\ + install_name_tool -change "old_path_1 $1" @rpath/"$1\ + " -change "old_path_2 $1" @rpath/"$1\ + " -change "old_path_3 $1" @rpath/"$1" "fname"\n\ + { set +x; } 2>/dev/null"\ + }' \ + | bash + install_name_tool -add_rpath @executable_path/../Resources/lib "${file}" +done + +msg "Copying distribution info for dependencies..." +# Ideally either py2app or gtk-mac-bundler would take care of this but I guess that's too much to ask. +# Maybe we can remove this eventually if they get their shit together. +cp -Rv "${SITEPACKAGES}"/zope.interface-*.egg-info \ + "${SITEPACKAGES}"/setproctitle-*.egg-info \ + "${SITEPACKAGES}"/six-*.egg-info \ + "${SITEPACKAGES}"/chardet*.egg-info \ + "${SITEPACKAGES}"/Mako*.egg-info \ + "${SITEPACKAGES}"/Pillow*.egg-info \ + "${SITEPACKAGES}"/pyxdg-*.egg-info \ + "${SITEPACKAGES}"/pycairo-*.egg-info \ + "${SITEPACKAGES}"/PyGObject-*.egg-info \ + "${SITEPACKAGES}"/pyOpenSSL-*.egg-info \ + "${SITEPACKAGES}"/rencode-*.egg-info \ + "${SITEPACKAGES}"/pyasn1-*.egg-info \ + "${SITEPACKAGES}"/pyasn1_modules-*.egg-info \ + "${SITEPACKAGES}"/pyasn1-*.egg-info \ + "${SITEPACKAGES}"/Twisted-*.egg-info \ + "${SITEPACKAGES}"/setuptools-*.egg-info \ + "${SITEPACKAGES}"/MarkupSafe-*.egg-info \ + "${SITEPACKAGES}"/cryptography-*.egg-info \ + "${SITEPACKAGES}"/idna-*.egg-info \ + "${SITEPACKAGES}"/service_identity-*.egg-info \ + "${SITEPACKAGES}"/attrs-*.egg-info \ + "${SITEPACKAGES}"/PyHamcrest-*.egg-info \ + "${SITEPACKAGES}"/hyperlink-*.egg-info \ + "${SITEPACKAGES}"/Automat-*.egg-info \ + "${SITEPACKAGES}"/incremental-*.egg-info \ + "${SITEPACKAGES}"/constantly-*.egg-info \ + "${SITEPACKAGES}"/asn1crypto-*.egg-info \ + "${SITEPACKAGES}"/pycparser-*.egg-info \ + "${SITEPACKAGES}"/cffi-*.egg-info \ + "${LIBDIR}/python${PY2APP_PYTHON_VERSION}/" + +echo "*** Packaging done:$(du -hs ${APPDIR} | cut -f 1)" diff --git a/setup.cfg b/setup.cfg index e52fa07cd2..75049603e7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,15 +15,14 @@ builder = spelling [py2app] app = ['deluge/ui/ui_entry.py'] arch = x86_64 -# arch = i386 iconfile = packaging/osx/deluge.icns site-packages = false -includes = glib, gio, cairo, pango, pangocairo, atk, gobject, gtk.keysyms, - twisted.internet, twisted.internet.utils, twisted.protocols, - zope.interface, mako.cache, email.mime, libtorrent, gtkosx_application, - HTMLParser +includes = gi, gi.repository, cairo, twisted.internet.*, twisted.web.*, twisted.python, twisted.trial, twisted.application, + rencode, zope.interface, mako, mimetypes, libtorrent, OpenSSL, gi.repository.GdkPixbuf, + six, gettext, html.parser, urllib.parse, setproctitle, pygame.mixer_music, numpy.array + GeoIP, PIL.Image, chardet, xdg, pyasn1, pyasn1_modules, service_identity frameworks = CoreFoundation, Foundation, AppKit - +packages = gi [isort] known_standard_library = future_builtins known_third_party = diff --git a/setup.py b/setup.py index 184a29a25d..9b96dbaa74 100755 --- a/setup.py +++ b/setup.py @@ -534,7 +534,7 @@ def run(self): ] _package_data['deluge.ui.gtk3'] = ['glade/*.ui'] -setup_requires = ['setuptools', 'wheel'] +setup_requires = ['setuptools', 'wheel', 'py2app'] install_requires = [ 'twisted[tls]>=17.1', # Add pyasn1 for setuptools workaround: @@ -542,6 +542,7 @@ def run(self): 'pyasn1', 'rencode', 'pyopenssl', + 'pygobject', 'pyxdg', 'pillow', 'mako',