Port macdeployqtplus to OSX 10.8

Use 'osascript' to run AppleScript, instead of using (broken-in-10.8)
python appscript package.

And added support for code-signing the .app bundle, to make OSX's
GateKeeper happy.
This commit is contained in:
Gavin Andresen 2013-01-14 11:52:15 -05:00
parent 2c7847349d
commit 33b377a016
2 changed files with 77 additions and 24 deletions

View File

@ -18,6 +18,7 @@
# #
import subprocess, sys, re, os, shutil, stat, os.path import subprocess, sys, re, os, shutil, stat, os.path
from string import Template
from time import sleep from time import sleep
from argparse import ArgumentParser from argparse import ArgumentParser
@ -429,12 +430,17 @@ ap = ArgumentParser(description="""Improved version of macdeployqt.
Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file. Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file.
Note, that the "dist" folder will be deleted before deploying on each run. Note, that the "dist" folder will be deleted before deploying on each run.
Optionally, Qt translation files (.qm) and additional resources can be added to the bundle.""") Optionally, Qt translation files (.qm) and additional resources can be added to the bundle.
Also optionally signs the .app bundle; set the CODESIGNARGS environment variable to pass arguments
to the codesign tool.
E.g. CODESIGNARGS='--sign "Developer ID Application: ..." --keychain /encrypted/foo.keychain'""")
ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed") ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed")
ap.add_argument("-verbose", type=int, nargs=1, default=[1], metavar="<0-3>", help="0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug") ap.add_argument("-verbose", type=int, nargs=1, default=[1], metavar="<0-3>", help="0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug")
ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment") ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment")
ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries") ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries")
ap.add_argument("-sign", dest="sign", action="store_true", default=False, help="sign .app bundle with codesign tool")
ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image; if basename is not specified, a camel-cased version of the app name is used") ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image; if basename is not specified, a camel-cased version of the app name is used")
ap.add_argument("-fancy", nargs=1, metavar="plist", default=[], help="make a fancy looking disk image using the given plist file with instructions; requires -dmg to work") ap.add_argument("-fancy", nargs=1, metavar="plist", default=[], help="make a fancy looking disk image using the given plist file with instructions; requires -dmg to work")
ap.add_argument("-add-qt-tr", nargs=1, metavar="languages", default=[], help="add Qt translation files to the bundle's ressources; the language list must be separated with commas, not with whitespace") ap.add_argument("-add-qt-tr", nargs=1, metavar="languages", default=[], help="add Qt translation files to the bundle's ressources; the language list must be separated with commas, not with whitespace")
@ -635,6 +641,15 @@ for p in config.add_resources:
# ------------------------------------------------ # ------------------------------------------------
if config.sign and 'CODESIGNARGS' not in os.environ:
print "You must set the CODESIGNARGS environment variable. Skipping signing."
elif config.sign:
if verbose >= 1:
print "Code-signing app bundle %s"%(target,)
subprocess.check_call("codesign --force %s %s"%(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, image_basename, **kwargs):
hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"] hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"]
@ -713,30 +728,67 @@ if config.dmg is not None:
if fancy.get("applications_symlink", False): if fancy.get("applications_symlink", False):
os.symlink("/Applications", os.path.join(disk_root, "Applications")) os.symlink("/Applications", os.path.join(disk_root, "Applications"))
finder = appscript.app("Finder") # The Python appscript package broke with OSX 10.8 and isn't being fixed.
disk = finder.disks[disk_name] # So we now build up an AppleScript string and use the osascript command
disk.open() # to make the .dmg file pretty:
window = disk.container_window appscript = Template( """
window.current_view.set(appscript.k.icon_view) on run argv
window.toolbar_visible.set(False) tell application "Finder"
window.statusbar_visible.set(False) tell disk "$disk"
if fancy.has_key("window_bounds"): open
window.bounds.set(fancy["window_bounds"]) set current view of container window to icon view
view_options = window.icon_view_options set toolbar visible of container window to false
view_options.arrangement.set(appscript.k.not_arranged) set statusbar visible of container window to false
if fancy.has_key("icon_size"): set the bounds of container window to {$window_bounds}
view_options.icon_size.set(fancy["icon_size"]) set theViewOptions to the icon view options of container window
if bg_path is not None: set arrangement of theViewOptions to not arranged
view_options.background_picture.set(disk.files[os.path.basename(bg_path)]) set icon size of theViewOptions to $icon_size
$background_commands
$items_positions
close -- close/reopen works around a bug...
open
update without registering applications
delay 5
eject
end tell
end tell
end run
""")
itemscript = Template('set position of item "${item}" of container window to {${position}}')
items_positions = []
if fancy.has_key("items_position"): if fancy.has_key("items_position"):
for name, position in fancy["items_position"].iteritems(): for name, position in fancy["items_position"].iteritems():
window.items[name].position.set(position) params = { "item" : name, "position" : ",".join([str(p) for p in position]) }
disk.close() items_positions.append(itemscript.substitute(params))
params = {
"disk" : "Bitcoin-Qt",
"window_bounds" : "300,300,800,620",
"icon_size" : "96",
"background_commands" : "",
"items_positions" : "\n ".join(items_positions)
}
if fancy.has_key("window_bounds"):
params["window.bounds"] = ",".join([str(p) for p in fancy["window_bounds"]])
if fancy.has_key("icon_size"):
params["icon_size"] = str(fancy["icon_size"])
if bg_path is not None: if bg_path is not None:
subprocess.call(["SetFile", "-a", "V", bg_path]) # Set background file, then call SetFile to make it invisible.
# disk.update(registering_applications=False) # (note: making it invisible first makes set background picture fail)
sleep(2) bgscript = Template("""set background picture of theViewOptions to file "$bgpic"
disk.eject() do shell script "SetFile -a V /Volumes/$disk/$bgpic" """)
params["background_commands"] = bgscript.substitute({"bgpic" : os.path.basename(bg_path), "disk" : params["disk"]})
s = appscript.substitute(params)
if verbose >= 2:
print("Running AppleScript:")
print(s)
p = subprocess.Popen(['osascript', '-'], stdin=subprocess.PIPE)
p.communicate(input=s)
if p.returncode:
print("Error running osascript.")
if verbose >= 2: if verbose >= 2:
print "+ Finalizing .dmg disk image +" print "+ Finalizing .dmg disk image +"

View File

@ -83,7 +83,8 @@
make make
export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files
T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale) T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale)
python2.7 contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist export CODESIGNARGS='--sign "Developer ID Application: BITCOIN FOUNDATION, INC., THE"'
python2.7 contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -sign -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist
Build output expected: Build output expected:
Bitcoin-Qt.dmg Bitcoin-Qt.dmg