19
19
import subprocess , sys , re , os , shutil , stat , os .path , time
20
20
from string import Template
21
21
from argparse import ArgumentParser
22
+ from typing import List , Optional
22
23
23
24
# This is ported from the original macdeployqt with modifications
24
25
@@ -48,18 +49,18 @@ class FrameworkInfo(object):
48
49
return False
49
50
50
51
def __str__ (self ):
51
- return """ Framework name: %s
52
- Framework directory: %s
53
- Framework path: %s
54
- Binary name: %s
55
- Binary directory: %s
56
- Binary path: %s
57
- Version: %s
58
- Install name: %s
59
- Deployed install name: %s
60
- Source file Path: %s
61
- Deployed Directory (relative to bundle): %s
62
- """ % (self .frameworkName ,
52
+ return """ Framework name: {}
53
+ Framework directory: {}
54
+ Framework path: {}
55
+ Binary name: {}
56
+ Binary directory: {}
57
+ Binary path: {}
58
+ Version: {}
59
+ Install name: {}
60
+ Deployed install name: {}
61
+ Source file Path: {}
62
+ Deployed Directory (relative to bundle): {}
63
+ """ . format (self .frameworkName ,
63
64
self .frameworkDirectory ,
64
65
self .frameworkPath ,
65
66
self .binaryName ,
@@ -85,7 +86,7 @@ class FrameworkInfo(object):
85
86
bundleBinaryDirectory = "Contents/MacOS"
86
87
87
88
@classmethod
88
- def fromOtoolLibraryLine (cls , line ) :
89
+ def fromOtoolLibraryLine (cls , line : str ) -> Optional [ 'FrameworkInfo' ] :
89
90
# Note: line must be trimmed
90
91
if line == "" :
91
92
return None
@@ -146,13 +147,12 @@ class FrameworkInfo(object):
146
147
info .sourceContentsDirectory = os .path .join (info .frameworkPath , "Contents" )
147
148
info .sourceVersionContentsDirectory = os .path .join (info .frameworkPath , "Versions" , info .version , "Contents" )
148
149
info .destinationResourcesDirectory = os .path .join (cls .bundleFrameworkDirectory , info .frameworkName , "Resources" )
149
- info .destinationContentsDirectory = os .path .join (cls .bundleFrameworkDirectory , info .frameworkName , "Contents" )
150
150
info .destinationVersionContentsDirectory = os .path .join (cls .bundleFrameworkDirectory , info .frameworkName , "Versions" , info .version , "Contents" )
151
151
152
152
return info
153
153
154
154
class ApplicationBundleInfo (object ):
155
- def __init__ (self , path ):
155
+ def __init__ (self , path : str ):
156
156
self .path = path
157
157
appName = "Bitcoin-Qt"
158
158
self .binaryPath = os .path .join (path , "Contents" , "MacOS" , appName )
@@ -167,7 +167,7 @@ class DeploymentInfo(object):
167
167
self .pluginPath = None
168
168
self .deployedFrameworks = []
169
169
170
- def detectQtPath (self , frameworkDirectory ):
170
+ def detectQtPath (self , frameworkDirectory : str ):
171
171
parentDir = os .path .dirname (frameworkDirectory )
172
172
if os .path .exists (os .path .join (parentDir , "translations" )):
173
173
# Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x"
@@ -180,9 +180,9 @@ class DeploymentInfo(object):
180
180
if os .path .exists (pluginPath ):
181
181
self .pluginPath = pluginPath
182
182
183
- def usesFramework (self , name ) :
184
- nameDot = "%s." % name
185
- libNameDot = "lib%s." % name
183
+ def usesFramework (self , name : str ) -> bool :
184
+ nameDot = "{}." . format ( name )
185
+ libNameDot = "lib{}." . format ( name )
186
186
for framework in self .deployedFrameworks :
187
187
if framework .endswith (".framework" ):
188
188
if framework .startswith (nameDot ):
@@ -192,7 +192,7 @@ class DeploymentInfo(object):
192
192
return True
193
193
return False
194
194
195
- def getFrameworks (binaryPath , verbose ) :
195
+ def getFrameworks (binaryPath : str , verbose : int ) -> List [ FrameworkInfo ] :
196
196
if verbose >= 3 :
197
197
print ("Inspecting with otool: " + binaryPath )
198
198
otoolbin = os .getenv ("OTOOL" , "otool" )
@@ -202,7 +202,7 @@ def getFrameworks(binaryPath, verbose):
202
202
if verbose >= 1 :
203
203
sys .stderr .write (o_stderr )
204
204
sys .stderr .flush ()
205
- raise RuntimeError ("otool failed with return code %d" % otool .returncode )
205
+ raise RuntimeError ("otool failed with return code {}" . format ( otool .returncode ) )
206
206
207
207
otoolLines = o_stdout .split ("\n " )
208
208
otoolLines .pop (0 ) # First line is the inspected binary
@@ -221,33 +221,33 @@ def getFrameworks(binaryPath, verbose):
221
221
222
222
return libraries
223
223
224
- def runInstallNameTool (action , * args ):
224
+ def runInstallNameTool (action : str , * args ):
225
225
installnametoolbin = os .getenv ("INSTALLNAMETOOL" , "install_name_tool" )
226
226
subprocess .check_call ([installnametoolbin , "-" + action ] + list (args ))
227
227
228
- def changeInstallName (oldName , newName , binaryPath , verbose ):
228
+ def changeInstallName (oldName : str , newName : str , binaryPath : str , verbose : int ):
229
229
if verbose >= 3 :
230
230
print ("Using install_name_tool:" )
231
231
print (" in" , binaryPath )
232
232
print (" change reference" , oldName )
233
233
print (" to" , newName )
234
234
runInstallNameTool ("change" , oldName , newName , binaryPath )
235
235
236
- def changeIdentification (id , binaryPath , verbose ):
236
+ def changeIdentification (id : str , binaryPath : str , verbose : int ):
237
237
if verbose >= 3 :
238
238
print ("Using install_name_tool:" )
239
239
print (" change identification in" , binaryPath )
240
240
print (" to" , id )
241
241
runInstallNameTool ("id" , id , binaryPath )
242
242
243
- def runStrip (binaryPath , verbose ):
243
+ def runStrip (binaryPath : str , verbose : int ):
244
244
stripbin = os .getenv ("STRIP" , "strip" )
245
245
if verbose >= 3 :
246
246
print ("Using strip:" )
247
247
print (" stripped" , binaryPath )
248
248
subprocess .check_call ([stripbin , "-x" , binaryPath ])
249
249
250
- def copyFramework (framework , path , verbose ) :
250
+ def copyFramework (framework : FrameworkInfo , path : str , verbose : int ) -> Optional [ str ] :
251
251
if framework .sourceFilePath .startswith ("Qt" ):
252
252
#standard place for Nokia Qt installer's frameworks
253
253
fromPath = "/Library/Frameworks/" + framework .sourceFilePath
@@ -309,7 +309,7 @@ def copyFramework(framework, path, verbose):
309
309
310
310
return toPath
311
311
312
- def deployFrameworks (frameworks , bundlePath , binaryPath , strip , verbose , deploymentInfo = None ):
312
+ def deployFrameworks (frameworks : List [ FrameworkInfo ] , bundlePath : str , binaryPath : str , strip : bool , verbose : int , deploymentInfo : Optional [ DeploymentInfo ] = None ) -> DeploymentInfo :
313
313
if deploymentInfo is None :
314
314
deploymentInfo = DeploymentInfo ()
315
315
@@ -355,15 +355,15 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym
355
355
356
356
return deploymentInfo
357
357
358
- def deployFrameworksForAppBundle (applicationBundle , strip , verbose ) :
358
+ def deployFrameworksForAppBundle (applicationBundle : ApplicationBundleInfo , strip : bool , verbose : int ) -> DeploymentInfo :
359
359
frameworks = getFrameworks (applicationBundle .binaryPath , verbose )
360
360
if len (frameworks ) == 0 and verbose >= 1 :
361
- print ("Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle .path ))
361
+ print ("Warning: Could not find any external frameworks to deploy in {}." . format (applicationBundle .path ))
362
362
return DeploymentInfo ()
363
363
else :
364
364
return deployFrameworks (frameworks , applicationBundle .path , applicationBundle .binaryPath , strip , verbose )
365
365
366
- def deployPlugins (appBundleInfo , deploymentInfo , strip , verbose ):
366
+ def deployPlugins (appBundleInfo : ApplicationBundleInfo , deploymentInfo : DeploymentInfo , strip : bool , verbose : int ):
367
367
# Lookup available plugins, exclude unneeded
368
368
plugins = []
369
369
if deploymentInfo .pluginPath is None :
@@ -373,10 +373,12 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
373
373
if pluginDirectory == "designer" :
374
374
# Skip designer plugins
375
375
continue
376
- elif pluginDirectory == "phonon" or pluginDirectory == "phonon_backend" :
377
- # Deploy the phonon plugins only if phonon is in use
378
- if not deploymentInfo .usesFramework ("phonon" ):
379
- continue
376
+ elif pluginDirectory == "printsupport" :
377
+ # Skip printsupport plugins
378
+ continue
379
+ elif pluginDirectory == "imageformats" :
380
+ # Skip imageformats plugins
381
+ continue
380
382
elif pluginDirectory == "sqldrivers" :
381
383
# Deploy the sql plugins only if QtSql is in use
382
384
if not deploymentInfo .usesFramework ("QtSql" ):
@@ -409,6 +411,42 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
409
411
# Deploy the mediaservice plugins only if QtMultimediaWidgets is in use
410
412
if not deploymentInfo .usesFramework ("QtMultimediaWidgets" ):
411
413
continue
414
+ elif pluginDirectory == "canbus" :
415
+ # Deploy the canbus plugins only if QtSerialBus is in use
416
+ if not deploymentInfo .usesFramework ("QtSerialBus" ):
417
+ continue
418
+ elif pluginDirectory == "webview" :
419
+ # Deploy the webview plugins only if QtWebView is in use
420
+ if not deploymentInfo .usesFramework ("QtWebView" ):
421
+ continue
422
+ elif pluginDirectory == "gamepads" :
423
+ # Deploy the webview plugins only if QtGamepad is in use
424
+ if not deploymentInfo .usesFramework ("QtGamepad" ):
425
+ continue
426
+ elif pluginDirectory == "geoservices" :
427
+ # Deploy the webview plugins only if QtLocation is in use
428
+ if not deploymentInfo .usesFramework ("QtLocation" ):
429
+ continue
430
+ elif pluginDirectory == "texttospeech" :
431
+ # Deploy the texttospeech plugins only if QtTextToSpeech is in use
432
+ if not deploymentInfo .usesFramework ("QtTextToSpeech" ):
433
+ continue
434
+ elif pluginDirectory == "virtualkeyboard" :
435
+ # Deploy the virtualkeyboard plugins only if QtVirtualKeyboard is in use
436
+ if not deploymentInfo .usesFramework ("QtVirtualKeyboard" ):
437
+ continue
438
+ elif pluginDirectory == "sceneparsers" :
439
+ # Deploy the virtualkeyboard plugins only if Qt3DCore is in use
440
+ if not deploymentInfo .usesFramework ("Qt3DCore" ):
441
+ continue
442
+ elif pluginDirectory == "renderplugins" :
443
+ # Deploy the renderplugins plugins only if Qt3DCore is in use
444
+ if not deploymentInfo .usesFramework ("Qt3DCore" ):
445
+ continue
446
+ elif pluginDirectory == "geometryloaders" :
447
+ # Deploy the geometryloaders plugins only if Qt3DCore is in use
448
+ if not deploymentInfo .usesFramework ("Qt3DCore" ):
449
+ continue
412
450
413
451
for pluginName in filenames :
414
452
pluginPath = os .path .join (pluginDirectory , pluginName )
@@ -431,6 +469,10 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
431
469
# Deploy the accessible qtquick plugin only if QtQuick is in use
432
470
if not deploymentInfo .usesFramework ("QtQuick" ):
433
471
continue
472
+ elif pluginPath == "platforminputcontexts/libqtvirtualkeyboardplugin.dylib" :
473
+ # Deploy the virtualkeyboardplugin plugin only if QtVirtualKeyboard is in use
474
+ if not deploymentInfo .usesFramework ("QtVirtualKeyboard" ):
475
+ continue
434
476
435
477
plugins .append ((pluginDirectory , pluginName ))
436
478
@@ -499,7 +541,7 @@ app_bundle = config.app_bundle[0]
499
541
500
542
if not os .path .exists (app_bundle ):
501
543
if verbose >= 1 :
502
- sys .stderr .write ("Error: Could not find app bundle \" %s \" \n " % (app_bundle ))
544
+ sys .stderr .write ("Error: Could not find app bundle \" {} \" \n " . format (app_bundle ))
503
545
sys .exit (1 )
504
546
505
547
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]:
511
553
translations_dir = config .translations_dir [0 ]
512
554
else :
513
555
if verbose >= 1 :
514
- sys .stderr .write ("Error: Could not find translation dir \" %s \" \n " % (translations_dir ))
556
+ sys .stderr .write ("Error: Could not find translation dir \" {} \" \n " . format (translations_dir ))
515
557
sys .exit (1 )
516
558
# ------------------------------------------------
517
559
@@ -520,7 +562,7 @@ for p in config.add_resources:
520
562
print ("Checking for \" %s\" ..." % p )
521
563
if not os .path .exists (p ):
522
564
if verbose >= 1 :
523
- sys .stderr .write ("Error: Could not find additional resource file \" %s \" \n " % (p ))
565
+ sys .stderr .write ("Error: Could not find additional resource file \" {} \" \n " . format (p ))
524
566
sys .exit (1 )
525
567
526
568
# ------------------------------------------------
@@ -537,17 +579,17 @@ if len(config.fancy) == 1:
537
579
538
580
p = config .fancy [0 ]
539
581
if verbose >= 3 :
540
- print ("Fancy: Loading \" %s \" ..." % p )
582
+ print ("Fancy: Loading \" {} \" ..." . format ( p ) )
541
583
if not os .path .exists (p ):
542
584
if verbose >= 1 :
543
- sys .stderr .write ("Error: Could not find fancy disk image plist at \" %s \" \n " % (p ))
585
+ sys .stderr .write ("Error: Could not find fancy disk image plist at \" {} \" \n " . format (p ))
544
586
sys .exit (1 )
545
587
546
588
try :
547
589
fancy = plistlib .readPlist (p )
548
590
except :
549
591
if verbose >= 1 :
550
- sys .stderr .write ("Error: Could not parse fancy disk image plist at \" %s \" \n " % (p ))
592
+ sys .stderr .write ("Error: Could not parse fancy disk image plist at \" {} \" \n " . format (p ))
551
593
sys .exit (1 )
552
594
553
595
try :
@@ -561,18 +603,18 @@ if len(config.fancy) == 1:
561
603
assert isinstance (value , list ) and len (value ) == 2 and isinstance (value [0 ], int ) and isinstance (value [1 ], int )
562
604
except :
563
605
if verbose >= 1 :
564
- sys .stderr .write ("Error: Bad format of fancy disk image plist at \" %s \" \n " % (p ))
606
+ sys .stderr .write ("Error: Bad format of fancy disk image plist at \" {} \" \n " . format (p ))
565
607
sys .exit (1 )
566
608
567
609
if "background_picture" in fancy :
568
610
bp = fancy ["background_picture" ]
569
611
if verbose >= 3 :
570
- print ("Fancy: Resolving background picture \" %s \" ..." % bp )
612
+ print ("Fancy: Resolving background picture \" {} \" ..." . format ( bp ) )
571
613
if not os .path .exists (bp ):
572
614
bp = os .path .join (os .path .dirname (p ), bp )
573
615
if not os .path .exists (bp ):
574
616
if verbose >= 1 :
575
- sys .stderr .write ("Error: Could not find background picture at \" %s \" or \" %s \" \n " % (fancy ["background_picture" ], bp ))
617
+ sys .stderr .write ("Error: Could not find background picture at \" {} \" or \" {} \" \n " . format (fancy ["background_picture" ], bp ))
576
618
sys .exit (1 )
577
619
else :
578
620
fancy ["background_picture" ] = bp
623
665
config .plugins = False
624
666
except RuntimeError as e :
625
667
if verbose >= 1 :
626
- sys .stderr .write ("Error: %s \n " % str (e ))
668
+ sys .stderr .write ("Error: {} \n " . format ( str (e ) ))
627
669
sys .exit (1 )
628
670
629
671
# ------------------------------------------------
@@ -636,7 +678,7 @@ if config.plugins:
636
678
deployPlugins (applicationBundle , deploymentInfo , config .strip , verbose )
637
679
except RuntimeError as e :
638
680
if verbose >= 1 :
639
- sys .stderr .write ("Error: %s \n " % str (e ))
681
+ sys .stderr .write ("Error: {} \n " . format ( str (e ) ))
640
682
sys .exit (1 )
641
683
642
684
# ------------------------------------------------
@@ -652,14 +694,14 @@ else:
652
694
else :
653
695
sys .stderr .write ("Error: Could not find Qt translation path\n " )
654
696
sys .exit (1 )
655
- add_qt_tr = ["qt_%s .qm" % lng for lng in config .add_qt_tr [0 ].split ("," )]
697
+ add_qt_tr = ["qt_{} .qm" . format ( lng ) for lng in config .add_qt_tr [0 ].split ("," )]
656
698
for lng_file in add_qt_tr :
657
699
p = os .path .join (qt_tr_dir , lng_file )
658
700
if verbose >= 3 :
659
- print ("Checking for \" %s \" ..." % p )
701
+ print ("Checking for \" {} \" ..." . format ( p ) )
660
702
if not os .path .exists (p ):
661
703
if verbose >= 1 :
662
- sys .stderr .write ("Error: Could not find Qt translation file \" %s \" \n " % (lng_file ))
704
+ sys .stderr .write ("Error: Could not find Qt translation file \" {} \" \n " . format (lng_file ))
663
705
sys .exit (1 )
664
706
665
707
# ------------------------------------------------
@@ -700,14 +742,14 @@ if config.sign and 'CODESIGNARGS' not in os.environ:
700
742
print ("You must set the CODESIGNARGS environment variable. Skipping signing." )
701
743
elif config .sign :
702
744
if verbose >= 1 :
703
- print ("Code-signing app bundle %s" % (target , ))
704
- subprocess .check_call ("codesign --force %s %s" % (os .environ ['CODESIGNARGS' ], target ), shell = True )
745
+ print ("Code-signing app bundle {}" . format (target ))
746
+ subprocess .check_call ("codesign --force {} {}" . format (os .environ ['CODESIGNARGS' ], target ), shell = True )
705
747
706
748
# ------------------------------------------------
707
749
708
750
if config .dmg is not None :
709
751
710
- def runHDIUtil (verb , image_basename , ** kwargs ):
752
+ def runHDIUtil (verb : str , image_basename : str , ** kwargs ) -> int :
711
753
hdiutil_args = ["hdiutil" , verb , image_basename + ".dmg" ]
712
754
if "capture_stdout" in kwargs :
713
755
del kwargs ["capture_stdout" ]
@@ -721,7 +763,7 @@ if config.dmg is not None:
721
763
722
764
for key , value in kwargs .items ():
723
765
hdiutil_args .append ("-" + key )
724
- if not value is True :
766
+ if value is not True :
725
767
hdiutil_args .append (str (value ))
726
768
727
769
return run (hdiutil_args , universal_newlines = True )
0 commit comments