From: Shane Synan Date: Wed, 25 Nov 2020 08:19:17 +0000 (-0500) Subject: build: Set macOS minimum version to Qt min version X-Git-Tag: 0.14-rc1~12 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=528af0d9d853d40c6ab5b2b753cc4644b6ddcdd1 build: Set macOS minimum version to Qt min version Set the macOS Info.plist minimum version to the minimum version supported by Qt for macOS. Determine the minimum macOS version for Qt through querying qmake. Unfortunately, this involves a somewhat roundabout process of a fake project file and searching qmake's output. See https://code.qt.io/cgit/pyside/pyside-setup.git/tree/qtinfo.py?h=5.6 Switch to HFS+ (from APFS) so older macOS versions can parse the app bundle and display the "OS version too old" warning, instead of just warning about a corrupt image file. Credit to freenode/Deas for point this out and providing screenshots! See https://doc.qt.io/qt-5/macos.html And https://doc.qt.io/qt-5/macos-deployment.html --- diff --git a/scripts/build/Info.plist b/scripts/build/Info.plist index b36abf40..c773a3f5 100644 --- a/scripts/build/Info.plist +++ b/scripts/build/Info.plist @@ -34,5 +34,7 @@ © 2005-2020, Quassel IRC Team NSSupportsAutomaticGraphicsSwitching + LSMinimumSystemVersion + %(QT_MACOSX_DEPLOYMENT_TARGET)s diff --git a/scripts/build/macosx_DeployApp.py b/scripts/build/macosx_DeployApp.py index 4ca72b49..edcb13c6 100755 --- a/scripts/build/macosx_DeployApp.py +++ b/scripts/build/macosx_DeployApp.py @@ -19,6 +19,9 @@ import os.path from subprocess import Popen, PIPE +# Handling Qt properties +import macosx_qt + # ============================== # Constants # ============================== @@ -55,40 +58,11 @@ class InstallQt(object): if not skipInstallQtConf: self.installQtConf() - def qtProperty(self, qtProperty): - """ - Query persistent property of Qt via qmake - """ - VALID_PROPERTIES = ['QT_INSTALL_PREFIX', - 'QT_INSTALL_DATA', - 'QT_INSTALL_DOCS', - 'QT_INSTALL_HEADERS', - 'QT_INSTALL_LIBS', - 'QT_INSTALL_BINS', - 'QT_INSTALL_PLUGINS', - 'QT_INSTALL_IMPORTS', - 'QT_INSTALL_TRANSLATIONS', - 'QT_INSTALL_CONFIGURATION', - 'QT_INSTALL_EXAMPLES', - 'QT_INSTALL_DEMOS', - 'QMAKE_MKSPECS', - 'QMAKE_VERSION', - 'QT_VERSION' - ] - if qtProperty not in VALID_PROPERTIES: - return None - - qmakeProcess = Popen('qmake -query %s' % qtProperty, shell=True, stdout=PIPE, stderr=PIPE) - result = qmakeProcess.stdout.read().strip() - qmakeProcess.stdout.close() - qmakeProcess.wait() - return result - def findFrameworkPath(self): - self.sourceFrameworkPath = self.qtProperty('QT_INSTALL_LIBS') + self.sourceFrameworkPath = macosx_qt.qtProperty('QT_INSTALL_LIBS') def findPluginsPath(self): - self.sourcePluginsPath = self.qtProperty('QT_INSTALL_PLUGINS') + self.sourcePluginsPath = macosx_qt.qtProperty('QT_INSTALL_PLUGINS') def findPlugin(self, pluginname): qmakeProcess = Popen('find %s -name %s' % (self.sourcePluginsPath, pluginname), shell=True, stdout=PIPE, stderr=PIPE) diff --git a/scripts/build/macosx_makePackage.sh b/scripts/build/macosx_makePackage.sh index a359ecd1..e9342dd5 100755 --- a/scripts/build/macosx_makePackage.sh +++ b/scripts/build/macosx_makePackage.sh @@ -87,6 +87,14 @@ esac echo "Creating macOS disk image with hdiutil: 'Quassel ${BUILDTYPE} - ${QUASSEL_VERSION}'" +# Modern macOS versions support APFS, however default to HFS+ for now in order +# to ensure old macOS versions can parse the package and display the warning +# about being out of date. This mirrors the approach taken by Qt's macdeployqt +# tool. In the future if this isn't needed, just remove "-fs HFS+" to revert +# to default. +# +# See https://doc.qt.io/qt-5/macos-deployment.html + # hdiutil seems to have a bit of a reputation for failing to create disk images # for various reasons. # @@ -105,7 +113,7 @@ echo "Creating macOS disk image with hdiutil: 'Quassel ${BUILDTYPE} - ${QUASSEL_ # # Option 1: -hdiutil create -srcfolder ${PACKAGETMPDIR} -format UDBZ -volname "Quassel ${BUILDTYPE} - ${QUASSEL_VERSION}" "${WORKINGDIR}${QUASSEL_DMG}" >/dev/null +hdiutil create -srcfolder ${PACKAGETMPDIR} -format UDBZ -fs HFS+ -volname "Quassel ${BUILDTYPE} - ${QUASSEL_VERSION}" "${WORKINGDIR}${QUASSEL_DMG}" >/dev/null # If hdiutil changes over time and fails often, you can try the other option. # @@ -114,7 +122,7 @@ hdiutil create -srcfolder ${PACKAGETMPDIR} -format UDBZ -volname "Quassel ${BUIL #PACKAGESIZE_MARGIN="1.1" #PACKAGESIZE=$(echo "$(du -ms ${PACKAGETMPDIR} | cut -f1) * $PACKAGESIZE_MARGIN" | bc) #echo "PACKAGESIZE: $PACKAGESIZE MB" -#hdiutil create -srcfolder ${PACKAGETMPDIR} -format UDBZ -size ${PACKAGESIZE}M -volname "Quassel ${BUILDTYPE} - ${QUASSEL_VERSION}" "${WORKINGDIR}${QUASSEL_DMG}" >/dev/null +#hdiutil create -srcfolder ${PACKAGETMPDIR} -format UDBZ -fs HFS+ -size ${PACKAGESIZE}M -volname "Quassel ${BUILDTYPE} - ${QUASSEL_VERSION}" "${WORKINGDIR}${QUASSEL_DMG}" >/dev/null # Regardless of choice, clean up the packaging temporary directory diff --git a/scripts/build/macosx_makebundle.py b/scripts/build/macosx_makebundle.py index e313a074..85742a06 100755 --- a/scripts/build/macosx_makebundle.py +++ b/scripts/build/macosx_makebundle.py @@ -18,6 +18,9 @@ import os.path import sys import commands +# Handling Qt properties +import macosx_qt + # ============================== # Constants # ============================== @@ -60,10 +63,20 @@ def createPlist(bundleName, bundleVersion): template = templateFile.read() templateFile.close() + # Get the minimum macOS deployment version + QT_MACOSX_DEPLOYMENT_TARGET = macosx_qt.qtMakespec('QMAKE_MACOSX_DEPLOYMENT_TARGET') + # Keep in sync with QMAKE_MACOSX_DEPLOYMENT_TARGET + # See https://doc.qt.io/qt-5/macos.html + if QT_MACOSX_DEPLOYMENT_TARGET is None: + # Something went wrong + sys.exit("Could not determine 'QMAKE_MACOSX_DEPLOYMENT_TARGET', check build scripts") + print("Qt macOS deployment target (minimum version): %s" % QT_MACOSX_DEPLOYMENT_TARGET) + plistFile = file(CONTENTS_DIR + "Info.plist", 'w') plistFile.write(template % {"BUNDLE_NAME": bundleName, "ICON_FILE": "quassel.icns", - "BUNDLE_VERSION": bundleVersion}) + "BUNDLE_VERSION": bundleVersion, + "QT_MACOSX_DEPLOYMENT_TARGET": QT_MACOSX_DEPLOYMENT_TARGET}) plistFile.close() def convertIconset(): diff --git a/scripts/build/macosx_qt.py b/scripts/build/macosx_qt.py new file mode 100755 index 00000000..3955364e --- /dev/null +++ b/scripts/build/macosx_qt.py @@ -0,0 +1,108 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- + +################################################################################ +# # +# 2008 June 27th by Marcus 'EgS' Eggenberger # +# # +# The author disclaims copyright to this source code. # +# This Python Script is in the PUBLIC DOMAIN. # +# # +################################################################################ + +# ============================== +# Imports +# ============================== +import os +from subprocess import Popen, PIPE + +# ============================== +# Global Functions +# ============================== +def qtProperty(qtProperty): + """ + Query persistent property of Qt via qmake + """ + VALID_PROPERTIES = ['QT_INSTALL_PREFIX', + 'QT_INSTALL_DATA', + 'QT_INSTALL_DOCS', + 'QT_INSTALL_HEADERS', + 'QT_INSTALL_LIBS', + 'QT_INSTALL_BINS', + 'QT_INSTALL_PLUGINS', + 'QT_INSTALL_IMPORTS', + 'QT_INSTALL_TRANSLATIONS', + 'QT_INSTALL_CONFIGURATION', + 'QT_INSTALL_EXAMPLES', + 'QT_INSTALL_DEMOS', + 'QMAKE_MKSPECS', + 'QMAKE_VERSION', + 'QT_VERSION' + ] + if qtProperty not in VALID_PROPERTIES: + return None + + qmakeProcess = Popen('qmake -query %s' % qtProperty, shell=True, stdout=PIPE, stderr=PIPE) + result = qmakeProcess.stdout.read().strip() + qmakeProcess.stdout.close() + qmakeProcess.wait() + return result + +def qtMakespec(qtMakespec): + """ + Query a Makespec value of Qt via qmake + """ + + VALID_PROPERTIES = ['QMAKE_MACOSX_DEPLOYMENT_TARGET', + ] + if qtMakespec not in VALID_PROPERTIES: + return None + + # QMAKE_MACOSX_DEPLOYMENT_TARGET sadly cannot be queried in the traditional way + # + # Inspired by https://code.qt.io/cgit/pyside/pyside-setup.git/tree/qtinfo.py?h=5.6 + # Simplified, no caching, etc, as we're just looking for the macOS version. + # If a cleaner solution is desired, look into license compatibility in + # order to simply copy the above code. + + current_dir = os.getcwd() + qmakeFakeProjectFile = os.path.join(current_dir, "qmake_empty_project.txt") + qmakeStashFile = os.path.join(current_dir, ".qmake.stash") + # Make an empty file + open(qmakeFakeProjectFile, 'a').close() + + qmakeProcess = Popen('qmake -E %s' % qmakeFakeProjectFile, shell=True, stdout=PIPE, stderr=PIPE) + result = qmakeProcess.stdout.read().strip() + qmakeProcess.stdout.close() + qmakeProcess.wait() + + # Clean up temporary files + try: + os.remove(qmakeFakeProjectFile) + except OSError: + pass + try: + os.remove(qmakeStashFile) + except OSError: + pass + + # Result should be like this: + # PROPERTY = VALUE\n + result_list = result.splitlines() + # Clear result so if nothing matches, nothing is returned + result = None + # Search keys + for line in result_list: + if not '=' in line: + # Ignore lines without '=' + continue + + # Find property = value + parts = line.split('=', 1) + prop = parts[0].strip() + value = parts[1].strip() + if (prop == qtMakespec): + result = value + break + + return result