Merge #16477: build: skip deploying plugins we dont use in macdeployqtplus

1ac7b7f66b scripts: filter more qt plugins we don't use in macdeployqtplus (fanquake)
57cdd0697d scripts: misc cleanups in macdeployqtplus (fanquake)
51729a4dfa scripts: use format() in macdeployqtplus (fanquake)
1c37e81694 scripts: add type annotations to macdeployqtplus (fanquake)

Pull request description:

  I frequently run `make deploy` while testing on macOS to get a properly light themed .app. With a brew installed Qt, this currently results in a pretty bloated executable:

  | branch | .app size | .dmg size | `make deploy` time |
  | ------- | --------- | --------- | --------------------- |
  | master (febf3a856b) | 235mb | 86mb | 38s |
  | This PR (da98f6d470d236c027b7eb8b5f5552fdca04e803) | 51mb | 21mb | 22s |

  Similar change to dd367ff8c9.

  ```diff
                           'QtGui.framework'],
    'pluginPath': '/usr/local/opt/qt/plugins',
    'qtPath': '/usr/local/opt/qt'}
  -[('platforminputcontexts', 'libqtvirtualkeyboardplugin.dylib'),
  - ('geoservices', 'libqtgeoservices_esri.dylib'),
  - ('geoservices', 'libqtgeoservices_mapboxgl.dylib'),
  - ('geoservices', 'libqtgeoservices_nokia.dylib'),
  - ('geoservices', 'libqtgeoservices_itemsoverlay.dylib'),
  - ('geoservices', 'libqtgeoservices_osm.dylib'),
  - ('geoservices', 'libqtgeoservices_mapbox.dylib'),
  - ('sceneparsers', 'libgltfsceneexport.dylib'),
  - ('sceneparsers', 'libgltfsceneimport.dylib'),
  - ('platforms', 'libqwebgl.dylib'),
  +[('platforms', 'libqwebgl.dylib'),
    ('platforms', 'libqoffscreen.dylib'),
    ('platforms', 'libqminimal.dylib'),
    ('platforms', 'libqcocoa.dylib'),
    ('platformthemes', 'libqxdgdesktopportal.dylib'),
  - ('printsupport', 'libcocoaprintersupport.dylib'),
  - ('webview', 'libqtwebview_webengine.dylib'),
  - ('webview', 'libqtwebview_darwin.dylib'),
  - ('geometryloaders', 'libdefaultgeometryloader.dylib'),
  - ('geometryloaders', 'libgltfgeometryloader.dylib'),
    ('styles', 'libqmacstyle.dylib'),
  - ('canbus', 'libqttinycanbus.dylib'),
  - ('canbus', 'libqtpassthrucanbus.dylib'),
  - ('canbus', 'libqtvirtualcanbus.dylib'),
  - ('canbus', 'libqtpeakcanbus.dylib'),
    ('bearer', 'libqgenericbearer.dylib'),
  - ('imageformats', 'libqgif.dylib'),
  - ('imageformats', 'libqwbmp.dylib'),
  - ('imageformats', 'libqwebp.dylib'),
  - ('imageformats', 'libqico.dylib'),
  - ('imageformats', 'libqmacheif.dylib'),
  - ('imageformats', 'libqjpeg.dylib'),
  - ('imageformats', 'libqtiff.dylib'),
  - ('imageformats', 'libqicns.dylib'),
  - ('imageformats', 'libqtga.dylib'),
  - ('imageformats', 'libqmacjp2.dylib'),
  - ('texttospeech', 'libqtexttospeech_speechosx.dylib'),
  - ('generic', 'libqtuiotouchplugin.dylib'),
  - ('renderplugins', 'libscene2d.dylib'),
  - ('gamepads', 'libdarwingamepad.dylib'),
  - ('virtualkeyboard', 'libqtvirtualkeyboard_thai.dylib'),
  - ('virtualkeyboard', 'libqtvirtualkeyboard_openwnn.dylib'),
  - ('virtualkeyboard', 'libqtvirtualkeyboard_hangul.dylib'),
  - ('virtualkeyboard', 'libqtvirtualkeyboard_pinyin.dylib'),
  - ('virtualkeyboard', 'libqtvirtualkeyboard_tcime.dylib')]
  + ('generic', 'libqtuiotouchplugin.dylib')]
  ```

ACKs for top commit:
  laanwj:
    ACK 1ac7b7f66b (purely Python code review and the fact that this passes travis, cannot run this on a mac)
  dongcarl:
    tested ACK 1ac7b7f66b

Tree-SHA512: 5974eeaf7229bb5bde2b283c1331ec57ee87f624db146401f6b77dee4ee5502e0bd669958a46205f10398a371f8e6c91ddacb9f0e1943f9f7d042fb6de7957a8
This commit is contained in:
fanquake 2019-09-10 10:41:11 +10:00
commit 59681beb89
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1

View file

@ -19,6 +19,7 @@
import subprocess, sys, re, os, shutil, stat, os.path, time import subprocess, sys, re, os, shutil, stat, os.path, time
from string import Template from string import Template
from argparse import ArgumentParser from argparse import ArgumentParser
from typing import List, Optional
# This is ported from the original macdeployqt with modifications # This is ported from the original macdeployqt with modifications
@ -48,18 +49,18 @@ class FrameworkInfo(object):
return False return False
def __str__(self): def __str__(self):
return """ Framework name: %s return """ Framework name: {}
Framework directory: %s Framework directory: {}
Framework path: %s Framework path: {}
Binary name: %s Binary name: {}
Binary directory: %s Binary directory: {}
Binary path: %s Binary path: {}
Version: %s Version: {}
Install name: %s Install name: {}
Deployed install name: %s Deployed install name: {}
Source file Path: %s Source file Path: {}
Deployed Directory (relative to bundle): %s Deployed Directory (relative to bundle): {}
""" % (self.frameworkName, """.format(self.frameworkName,
self.frameworkDirectory, self.frameworkDirectory,
self.frameworkPath, self.frameworkPath,
self.binaryName, self.binaryName,
@ -85,7 +86,7 @@ class FrameworkInfo(object):
bundleBinaryDirectory = "Contents/MacOS" bundleBinaryDirectory = "Contents/MacOS"
@classmethod @classmethod
def fromOtoolLibraryLine(cls, line): def fromOtoolLibraryLine(cls, line: str) -> Optional['FrameworkInfo']:
# Note: line must be trimmed # Note: line must be trimmed
if line == "": if line == "":
return None return None
@ -146,13 +147,12 @@ class FrameworkInfo(object):
info.sourceContentsDirectory = os.path.join(info.frameworkPath, "Contents") info.sourceContentsDirectory = os.path.join(info.frameworkPath, "Contents")
info.sourceVersionContentsDirectory = os.path.join(info.frameworkPath, "Versions", info.version, "Contents") info.sourceVersionContentsDirectory = os.path.join(info.frameworkPath, "Versions", info.version, "Contents")
info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources") info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources")
info.destinationContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Contents")
info.destinationVersionContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Versions", info.version, "Contents") info.destinationVersionContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Versions", info.version, "Contents")
return info return info
class ApplicationBundleInfo(object): class ApplicationBundleInfo(object):
def __init__(self, path): def __init__(self, path: str):
self.path = path self.path = path
appName = "Bitcoin-Qt" appName = "Bitcoin-Qt"
self.binaryPath = os.path.join(path, "Contents", "MacOS", appName) self.binaryPath = os.path.join(path, "Contents", "MacOS", appName)
@ -167,7 +167,7 @@ class DeploymentInfo(object):
self.pluginPath = None self.pluginPath = None
self.deployedFrameworks = [] self.deployedFrameworks = []
def detectQtPath(self, frameworkDirectory): def detectQtPath(self, frameworkDirectory: str):
parentDir = os.path.dirname(frameworkDirectory) parentDir = os.path.dirname(frameworkDirectory)
if os.path.exists(os.path.join(parentDir, "translations")): if os.path.exists(os.path.join(parentDir, "translations")):
# Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x" # Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x"
@ -180,9 +180,9 @@ class DeploymentInfo(object):
if os.path.exists(pluginPath): if os.path.exists(pluginPath):
self.pluginPath = pluginPath self.pluginPath = pluginPath
def usesFramework(self, name): def usesFramework(self, name: str) -> bool:
nameDot = "%s." % name nameDot = "{}.".format(name)
libNameDot = "lib%s." % name libNameDot = "lib{}.".format(name)
for framework in self.deployedFrameworks: for framework in self.deployedFrameworks:
if framework.endswith(".framework"): if framework.endswith(".framework"):
if framework.startswith(nameDot): if framework.startswith(nameDot):
@ -192,7 +192,7 @@ class DeploymentInfo(object):
return True return True
return False return False
def getFrameworks(binaryPath, verbose): def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
if verbose >= 3: if verbose >= 3:
print("Inspecting with otool: " + binaryPath) print("Inspecting with otool: " + binaryPath)
otoolbin=os.getenv("OTOOL", "otool") otoolbin=os.getenv("OTOOL", "otool")
@ -202,7 +202,7 @@ def getFrameworks(binaryPath, verbose):
if verbose >= 1: if verbose >= 1:
sys.stderr.write(o_stderr) sys.stderr.write(o_stderr)
sys.stderr.flush() sys.stderr.flush()
raise RuntimeError("otool failed with return code %d" % otool.returncode) raise RuntimeError("otool failed with return code {}".format(otool.returncode))
otoolLines = o_stdout.split("\n") otoolLines = o_stdout.split("\n")
otoolLines.pop(0) # First line is the inspected binary otoolLines.pop(0) # First line is the inspected binary
@ -221,11 +221,11 @@ def getFrameworks(binaryPath, verbose):
return libraries return libraries
def runInstallNameTool(action, *args): def runInstallNameTool(action: str, *args):
installnametoolbin=os.getenv("INSTALLNAMETOOL", "install_name_tool") installnametoolbin=os.getenv("INSTALLNAMETOOL", "install_name_tool")
subprocess.check_call([installnametoolbin, "-"+action] + list(args)) subprocess.check_call([installnametoolbin, "-"+action] + list(args))
def changeInstallName(oldName, newName, binaryPath, verbose): def changeInstallName(oldName: str, newName: str, binaryPath: str, verbose: int):
if verbose >= 3: if verbose >= 3:
print("Using install_name_tool:") print("Using install_name_tool:")
print(" in", binaryPath) print(" in", binaryPath)
@ -233,21 +233,21 @@ def changeInstallName(oldName, newName, binaryPath, verbose):
print(" to", newName) print(" to", newName)
runInstallNameTool("change", oldName, newName, binaryPath) runInstallNameTool("change", oldName, newName, binaryPath)
def changeIdentification(id, binaryPath, verbose): def changeIdentification(id: str, binaryPath: str, verbose: int):
if verbose >= 3: if verbose >= 3:
print("Using install_name_tool:") print("Using install_name_tool:")
print(" change identification in", binaryPath) print(" change identification in", binaryPath)
print(" to", id) print(" to", id)
runInstallNameTool("id", id, binaryPath) runInstallNameTool("id", id, binaryPath)
def runStrip(binaryPath, verbose): def runStrip(binaryPath: str, verbose: int):
stripbin=os.getenv("STRIP", "strip") stripbin=os.getenv("STRIP", "strip")
if verbose >= 3: if verbose >= 3:
print("Using strip:") print("Using strip:")
print(" stripped", binaryPath) print(" stripped", binaryPath)
subprocess.check_call([stripbin, "-x", binaryPath]) subprocess.check_call([stripbin, "-x", binaryPath])
def copyFramework(framework, path, verbose): def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional[str]:
if framework.sourceFilePath.startswith("Qt"): if framework.sourceFilePath.startswith("Qt"):
#standard place for Nokia Qt installer's frameworks #standard place for Nokia Qt installer's frameworks
fromPath = "/Library/Frameworks/" + framework.sourceFilePath fromPath = "/Library/Frameworks/" + framework.sourceFilePath
@ -309,7 +309,7 @@ def copyFramework(framework, path, verbose):
return toPath return toPath
def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploymentInfo=None): def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPath: str, strip: bool, verbose: int, deploymentInfo: Optional[DeploymentInfo] = None) -> DeploymentInfo:
if deploymentInfo is None: if deploymentInfo is None:
deploymentInfo = DeploymentInfo() deploymentInfo = DeploymentInfo()
@ -355,15 +355,15 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym
return deploymentInfo return deploymentInfo
def deployFrameworksForAppBundle(applicationBundle, strip, verbose): def deployFrameworksForAppBundle(applicationBundle: ApplicationBundleInfo, strip: bool, verbose: int) -> DeploymentInfo:
frameworks = getFrameworks(applicationBundle.binaryPath, verbose) frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
if len(frameworks) == 0 and verbose >= 1: if len(frameworks) == 0 and verbose >= 1:
print("Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path)) print("Warning: Could not find any external frameworks to deploy in {}.".format(applicationBundle.path))
return DeploymentInfo() return DeploymentInfo()
else: else:
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose) return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: DeploymentInfo, strip: bool, verbose: int):
# Lookup available plugins, exclude unneeded # Lookup available plugins, exclude unneeded
plugins = [] plugins = []
if deploymentInfo.pluginPath is None: if deploymentInfo.pluginPath is None:
@ -373,9 +373,11 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
if pluginDirectory == "designer": if pluginDirectory == "designer":
# Skip designer plugins # Skip designer plugins
continue continue
elif pluginDirectory == "phonon" or pluginDirectory == "phonon_backend": elif pluginDirectory == "printsupport":
# Deploy the phonon plugins only if phonon is in use # Skip printsupport plugins
if not deploymentInfo.usesFramework("phonon"): continue
elif pluginDirectory == "imageformats":
# Skip imageformats plugins
continue continue
elif pluginDirectory == "sqldrivers": elif pluginDirectory == "sqldrivers":
# Deploy the sql plugins only if QtSql is in use # Deploy the sql plugins only if QtSql is in use
@ -409,6 +411,42 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
# Deploy the mediaservice plugins only if QtMultimediaWidgets is in use # Deploy the mediaservice plugins only if QtMultimediaWidgets is in use
if not deploymentInfo.usesFramework("QtMultimediaWidgets"): if not deploymentInfo.usesFramework("QtMultimediaWidgets"):
continue continue
elif pluginDirectory == "canbus":
# Deploy the canbus plugins only if QtSerialBus is in use
if not deploymentInfo.usesFramework("QtSerialBus"):
continue
elif pluginDirectory == "webview":
# Deploy the webview plugins only if QtWebView is in use
if not deploymentInfo.usesFramework("QtWebView"):
continue
elif pluginDirectory == "gamepads":
# Deploy the webview plugins only if QtGamepad is in use
if not deploymentInfo.usesFramework("QtGamepad"):
continue
elif pluginDirectory == "geoservices":
# Deploy the webview plugins only if QtLocation is in use
if not deploymentInfo.usesFramework("QtLocation"):
continue
elif pluginDirectory == "texttospeech":
# Deploy the texttospeech plugins only if QtTextToSpeech is in use
if not deploymentInfo.usesFramework("QtTextToSpeech"):
continue
elif pluginDirectory == "virtualkeyboard":
# Deploy the virtualkeyboard plugins only if QtVirtualKeyboard is in use
if not deploymentInfo.usesFramework("QtVirtualKeyboard"):
continue
elif pluginDirectory == "sceneparsers":
# Deploy the virtualkeyboard plugins only if Qt3DCore is in use
if not deploymentInfo.usesFramework("Qt3DCore"):
continue
elif pluginDirectory == "renderplugins":
# Deploy the renderplugins plugins only if Qt3DCore is in use
if not deploymentInfo.usesFramework("Qt3DCore"):
continue
elif pluginDirectory == "geometryloaders":
# Deploy the geometryloaders plugins only if Qt3DCore is in use
if not deploymentInfo.usesFramework("Qt3DCore"):
continue
for pluginName in filenames: for pluginName in filenames:
pluginPath = os.path.join(pluginDirectory, pluginName) pluginPath = os.path.join(pluginDirectory, pluginName)
@ -431,6 +469,10 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
# Deploy the accessible qtquick plugin only if QtQuick is in use # Deploy the accessible qtquick plugin only if QtQuick is in use
if not deploymentInfo.usesFramework("QtQuick"): if not deploymentInfo.usesFramework("QtQuick"):
continue continue
elif pluginPath == "platforminputcontexts/libqtvirtualkeyboardplugin.dylib":
# Deploy the virtualkeyboardplugin plugin only if QtVirtualKeyboard is in use
if not deploymentInfo.usesFramework("QtVirtualKeyboard"):
continue
plugins.append((pluginDirectory, pluginName)) plugins.append((pluginDirectory, pluginName))
@ -499,7 +541,7 @@ app_bundle = config.app_bundle[0]
if not os.path.exists(app_bundle): if not os.path.exists(app_bundle):
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not find app bundle \"%s\"\n" % (app_bundle)) sys.stderr.write("Error: Could not find app bundle \"{}\"\n".format(app_bundle))
sys.exit(1) sys.exit(1)
app_bundle_name = os.path.splitext(os.path.basename(app_bundle))[0] app_bundle_name = os.path.splitext(os.path.basename(app_bundle))[0]
@ -511,7 +553,7 @@ if config.translations_dir and config.translations_dir[0]:
translations_dir = config.translations_dir[0] translations_dir = config.translations_dir[0]
else: else:
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not find translation dir \"%s\"\n" % (translations_dir)) sys.stderr.write("Error: Could not find translation dir \"{}\"\n".format(translations_dir))
sys.exit(1) sys.exit(1)
# ------------------------------------------------ # ------------------------------------------------
@ -520,7 +562,7 @@ for p in config.add_resources:
print("Checking for \"%s\"..." % p) print("Checking for \"%s\"..." % p)
if not os.path.exists(p): if not os.path.exists(p):
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not find additional resource file \"%s\"\n" % (p)) sys.stderr.write("Error: Could not find additional resource file \"{}\"\n".format(p))
sys.exit(1) sys.exit(1)
# ------------------------------------------------ # ------------------------------------------------
@ -537,17 +579,17 @@ if len(config.fancy) == 1:
p = config.fancy[0] p = config.fancy[0]
if verbose >= 3: if verbose >= 3:
print("Fancy: Loading \"%s\"..." % p) print("Fancy: Loading \"{}\"...".format(p))
if not os.path.exists(p): if not os.path.exists(p):
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not find fancy disk image plist at \"%s\"\n" % (p)) sys.stderr.write("Error: Could not find fancy disk image plist at \"{}\"\n".format(p))
sys.exit(1) sys.exit(1)
try: try:
fancy = plistlib.readPlist(p) fancy = plistlib.readPlist(p)
except: except:
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not parse fancy disk image plist at \"%s\"\n" % (p)) sys.stderr.write("Error: Could not parse fancy disk image plist at \"{}\"\n".format(p))
sys.exit(1) sys.exit(1)
try: try:
@ -561,18 +603,18 @@ if len(config.fancy) == 1:
assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int) assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int)
except: except:
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Bad format of fancy disk image plist at \"%s\"\n" % (p)) sys.stderr.write("Error: Bad format of fancy disk image plist at \"{}\"\n".format(p))
sys.exit(1) sys.exit(1)
if "background_picture" in fancy: if "background_picture" in fancy:
bp = fancy["background_picture"] bp = fancy["background_picture"]
if verbose >= 3: if verbose >= 3:
print("Fancy: Resolving background picture \"%s\"..." % bp) print("Fancy: Resolving background picture \"{}\"...".format(bp))
if not os.path.exists(bp): if not os.path.exists(bp):
bp = os.path.join(os.path.dirname(p), bp) bp = os.path.join(os.path.dirname(p), bp)
if not os.path.exists(bp): if not os.path.exists(bp):
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not find background picture at \"%s\" or \"%s\"\n" % (fancy["background_picture"], bp)) sys.stderr.write("Error: Could not find background picture at \"{}\" or \"{}\"\n".format(fancy["background_picture"], bp))
sys.exit(1) sys.exit(1)
else: else:
fancy["background_picture"] = bp fancy["background_picture"] = bp
@ -623,7 +665,7 @@ try:
config.plugins = False config.plugins = False
except RuntimeError as e: except RuntimeError as e:
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: %s\n" % str(e)) sys.stderr.write("Error: {}\n".format(str(e)))
sys.exit(1) sys.exit(1)
# ------------------------------------------------ # ------------------------------------------------
@ -636,7 +678,7 @@ if config.plugins:
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose) deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
except RuntimeError as e: except RuntimeError as e:
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: %s\n" % str(e)) sys.stderr.write("Error: {}\n".format(str(e)))
sys.exit(1) sys.exit(1)
# ------------------------------------------------ # ------------------------------------------------
@ -652,14 +694,14 @@ else:
else: else:
sys.stderr.write("Error: Could not find Qt translation path\n") sys.stderr.write("Error: Could not find Qt translation path\n")
sys.exit(1) sys.exit(1)
add_qt_tr = ["qt_%s.qm" % lng for lng in config.add_qt_tr[0].split(",")] add_qt_tr = ["qt_{}.qm".format(lng) for lng in config.add_qt_tr[0].split(",")]
for lng_file in add_qt_tr: for lng_file in add_qt_tr:
p = os.path.join(qt_tr_dir, lng_file) p = os.path.join(qt_tr_dir, lng_file)
if verbose >= 3: if verbose >= 3:
print("Checking for \"%s\"..." % p) print("Checking for \"{}\"...".format(p))
if not os.path.exists(p): if not os.path.exists(p):
if verbose >= 1: if verbose >= 1:
sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file)) sys.stderr.write("Error: Could not find Qt translation file \"{}\"\n".format(lng_file))
sys.exit(1) sys.exit(1)
# ------------------------------------------------ # ------------------------------------------------
@ -700,14 +742,14 @@ if config.sign and 'CODESIGNARGS' not in os.environ:
print("You must set the CODESIGNARGS environment variable. Skipping signing.") print("You must set the CODESIGNARGS environment variable. Skipping signing.")
elif config.sign: elif config.sign:
if verbose >= 1: if verbose >= 1:
print("Code-signing app bundle %s"%(target,)) print("Code-signing app bundle {}".format(target))
subprocess.check_call("codesign --force %s %s"%(os.environ['CODESIGNARGS'], target), shell=True) subprocess.check_call("codesign --force {} {}".format(os.environ['CODESIGNARGS'], target), shell=True)
# ------------------------------------------------ # ------------------------------------------------
if config.dmg is not None: if config.dmg is not None:
def runHDIUtil(verb, image_basename, **kwargs): def runHDIUtil(verb: str, image_basename: str, **kwargs) -> int:
hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"] hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"]
if "capture_stdout" in kwargs: if "capture_stdout" in kwargs:
del kwargs["capture_stdout"] del kwargs["capture_stdout"]
@ -721,7 +763,7 @@ if config.dmg is not None:
for key, value in kwargs.items(): for key, value in kwargs.items():
hdiutil_args.append("-" + key) hdiutil_args.append("-" + key)
if not value is True: if value is not True:
hdiutil_args.append(str(value)) hdiutil_args.append(str(value))
return run(hdiutil_args, universal_newlines=True) return run(hdiutil_args, universal_newlines=True)