openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #30696
[Merge] lp:~raoul-snyman/openlp/new-dmg-build into lp:openlp/packaging
Raoul Snyman has proposed merging lp:~raoul-snyman/openlp/new-dmg-build into lp:openlp/packaging.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~raoul-snyman/openlp/new-dmg-build/+merge/310581
Update the macOS build system to use dmgbuild instead of manually running hdiutil and AppleScript.
--
Your team OpenLP Core is requested to review the proposed merge of lp:~raoul-snyman/openlp/new-dmg-build into lp:openlp/packaging.
=== modified file '.bzrignore'
--- .bzrignore 2014-06-14 03:40:58 +0000
+++ .bzrignore 2016-11-10 20:35:43 +0000
@@ -34,3 +34,4 @@
*.dll
*.DS_Store
config.ini
+*.dmg
=== removed file 'osx/DmgImageInstallBackground.png'
Binary files osx/DmgImageInstallBackground.png 2012-06-24 22:35:37 +0000 and osx/DmgImageInstallBackground.png 1970-01-01 00:00:00 +0000 differ
=== removed file 'osx/applescript-adjust-dmg-view.master'
--- osx/applescript-adjust-dmg-view.master 2016-05-03 20:04:45 +0000
+++ osx/applescript-adjust-dmg-view.master 1970-01-01 00:00:00 +0000
@@ -1,32 +0,0 @@
-on run
- -- wait for virus scanner
- delay 2
-
- tell application "Finder"
- tell disk "%(dmg_name)s"
- open
- set current view of container window to icon view
- set toolbar visible of container window to false
- set statusbar visible of container window to false
- set the bounds of container window to {400, 100, 1100, 500}
- set theViewOptions to the icon view options of container window
- set arrangement of theViewOptions to not arranged
- set icon size of theViewOptions to 128
- set background picture of theViewOptions to file ".background:installer-background.png"
- set position of item "%(app_name)s" of container window to {160, 200}
- set position of item "Applications" of container window to {550, 200}
- set position of item ".background" of container window to {100, 500}
- set position of item ".DS_Store" of container window to {200, 500}
- set position of item ".fseventsd" of container window to {300, 500}
- set position of item ".Trashes" of container window to {400, 500}
- set position of item ".VolumeIcon.icns" of container window to {500, 500}
- delay 5
- close
- open
- update without registering applications
- -- wait until the virus scan completes
- delay 2
- -- eject
- end tell
- end tell
-end run
=== modified file 'osx/config.ini.default'
--- osx/config.ini.default 2016-05-03 20:04:45 +0000
+++ osx/config.ini.default 2016-11-10 20:35:43 +0000
@@ -2,9 +2,7 @@
sphinx = sphinx-build-3.4
pyinstaller = %(projects)s/../pyinstaller/pyinstaller.py
lrelease = /opt/local/libexec/qt5/bin/lrelease
-diskutil = diskutil
-hdiutil = hdiutil
-osascript = osascript
+dmgbuild = dmgbuild
mudrawbin = mudraw
mutoolbin = mutool
@@ -12,10 +10,9 @@
branch = %(projects)s/trunk
documentation = %(projects)s/documentation
app_icon = %(here)s/OpenLP.icns
-dmg_icon = %(here)s/openlp-dmg.icns
bundle_info = %(here)s/Info.plist
hooks = %(here)s/../pyinstaller-hooks
-dmg_background = %(here)s/DmgImageInstallBackground.png
+dmg_settings = %(here)s/dmg-settings.py
[transifex]
username =
=== added file 'osx/dmg-background-new-with-icons.png'
Binary files osx/dmg-background-new-with-icons.png 1970-01-01 00:00:00 +0000 and osx/dmg-background-new-with-icons.png 2016-11-10 20:35:43 +0000 differ
=== added file 'osx/dmg-background-new.png'
Binary files osx/dmg-background-new.png 1970-01-01 00:00:00 +0000 and osx/dmg-background-new.png 2016-11-10 20:35:43 +0000 differ
=== added file 'osx/dmg-background.png'
Binary files osx/dmg-background.png 1970-01-01 00:00:00 +0000 and osx/dmg-background.png 2016-11-10 20:35:43 +0000 differ
=== added file 'osx/dmg-settings-new.py'
--- osx/dmg-settings-new.py 1970-01-01 00:00:00 +0000
+++ osx/dmg-settings-new.py 2016-11-10 20:35:43 +0000
@@ -0,0 +1,27 @@
+import os
+
+# This is the settings file for building the DMG. Run dmgbuild like so:
+# $ dmgbuild -s dmg-settings.py -D size=<size>,app=<path/to/OpenLP.app> "OpenLP" OpenLP-{version}.dmg
+
+HERE = os.getcwd()
+
+format = 'UDBZ'
+size = '600M'
+files = [defines.get('app', '/Applications/OpenLP.app')]
+symlinks = { 'Applications': '/Applications' }
+badge_icon = os.path.join(HERE, 'openlp-logo-new.icns')
+icon_locations = {
+ 'OpenLP.app': (160, 200),
+ 'Applications': (550, 200)
+}
+background = os.path.join(HERE, 'dmg-background-new.png')
+window_rect = ((100, 100), (700, 457))
+default_view = 'icon-view'
+show_icon_preview = False
+arrange_by = None
+scroll_position = (0, 0)
+grid_offset = (0, 0)
+grid_spacing = 100
+label_pos = 'bottom' # or 'right'
+text_size = 16
+icon_size = 128
=== added file 'osx/dmg-settings.py'
--- osx/dmg-settings.py 1970-01-01 00:00:00 +0000
+++ osx/dmg-settings.py 2016-11-10 20:35:43 +0000
@@ -0,0 +1,27 @@
+import os
+
+# This is the settings file for building the DMG. Run dmgbuild like so:
+# $ dmgbuild -s dmg-settings.py -D size=<size>,app=<path/to/OpenLP.app> "OpenLP" OpenLP-{version}.dmg
+
+HERE = os.getcwd()
+
+format = 'UDZO'
+size = defines.get('size', '600M')
+files = [defines.get('app', '/Applications/OpenLP.app')]
+symlinks = { 'Applications': '/Applications' }
+badge_icon = defines.get('icon', 'OpenLP.icns')
+icon_locations = {
+ 'OpenLP.app': (160, 200),
+ 'Applications': (550, 200)
+}
+background = os.path.join(HERE, 'dmg-background.png')
+window_rect = ((100, 100), (700, 460))
+default_view = 'icon-view'
+show_icon_preview = False
+arrange_by = None
+scroll_position = (0, 0)
+grid_offset = (0, 0)
+grid_spacing = 100
+label_pos = 'bottom' # or 'right'
+text_size = 16
+icon_size = 128
=== modified file 'osx/macosx-builder.py'
--- osx/macosx-builder.py 2016-05-03 20:04:45 +0000
+++ osx/macosx-builder.py 2016-11-10 20:35:43 +0000
@@ -27,9 +27,9 @@
This script is used to build the Mac OS X app bundle and pack it into dmg file.
For this script to work out of the box, it depends on a number of things:
-Python 3.3/3.4
+Python 3.4
-PyQt4
+PyQt5
You should already have this installed, OpenLP doesn't work without it. The
version the script expects is the packaged one available from River Bank
Computing.
@@ -111,6 +111,8 @@
"""
Return absolute path to a command found on system PATH.
"""
+ if command.startswith('/'):
+ return command
for path in os.environ["PATH"].split(os.pathsep):
if os.access(os.path.join(path, command), os.X_OK):
return "%s/%s" % (path, command)
@@ -237,11 +239,12 @@
self.sphinx = _which(self.config.get('executables', 'sphinx'))
self.pyinstaller = os.path.abspath(self.config.get('executables', 'pyinstaller'))
self.lrelease = self.config.get('executables', 'lrelease')
- self.diskutil = _which(self.config.get('executables', 'diskutil'))
- self.hdiutil = self.config.get('executables', 'hdiutil')
- self.osascript = _which(self.config.get('executables', 'osascript'))
+ self.dmgbuild = _which(self.config.get('executables', 'dmgbuild'))
self.mudraw_bin = _which(self.config.get('executables', 'mudrawbin'))
self.mutool_bin = _which(self.config.get('executables', 'mutoolbin'))
+ if self.mutool_bin:
+ self.mutool_lib = os.path.abspath(
+ os.path.join(os.path.dirname(self.mutool_bin), '..', 'lib', 'libjbig2dec.0.dylib'))
def setup_paths(self):
"""
@@ -264,9 +267,7 @@
self.openlp_script = os.path.abspath(os.path.join(self.work_path, 'openlp.py'))
self.hooks_path = os.path.abspath(os.path.join(self.work_path, self.config.get('paths', 'hooks')))
self.app_icon = os.path.abspath(self.config.get('paths', 'app_icon'))
- self.dmg_icon = os.path.abspath(self.config.get('paths', 'dmg_icon'))
self.bundle_info = os.path.abspath(self.config.get('paths', 'bundle_info'))
- self.dmg_background_img = os.path.abspath(self.config.get('paths', 'dmg_background'))
self.i18n_utils = os.path.join(self.work_path, 'scripts', 'translation_utils.py')
self.source_path = os.path.join(self.work_path, 'openlp')
self.manual_path = os.path.join(self.docs_path, 'manual')
@@ -275,12 +276,13 @@
self.build_path = os.path.join(self.work_path, 'build')
self.dist_app_path = os.path.join(self.work_path, 'dist', 'OpenLP.app')
self.dist_path = os.path.join(self.work_path, 'dist', 'OpenLP.app', 'Contents', 'MacOS')
+ self.dmg_settings = os.path.abspath(self.config.get('paths', 'dmg_settings'))
# Path to Qt translation files.
from PyQt5.QtCore import QCoreApplication
qt_plug_dir = str(list(QCoreApplication.libraryPaths())[0])
- self.qt_translat_path = os.path.join(os.path.dirname(qt_plug_dir), 'translations')
+ self.qt_translations_path = os.path.join(os.path.dirname(qt_plug_dir), 'translations')
def update_code(self):
"""
@@ -453,11 +455,12 @@
copy(os.path.join(self.script_path, 'LICENSE.txt'), os.path.join(self.dist_path, 'LICENSE.txt'))
self._print_verbose('... mudraw')
if self.mudraw_bin and os.path.isfile(self.mudraw_bin):
- copy(os.path.join(self.mudraw_bin), os.path.join(self.dist_path, 'mudraw'))
+ copy(self.mudraw_bin, os.path.join(self.dist_path, 'mudraw'))
self.relink_mudraw()
elif self.mutool_bin and os.path.isfile(self.mutool_bin):
- copy(os.path.join(self.mutool_bin), os.path.join(self.dist_path, 'mutool'))
+ copy(self.mutool_bin, os.path.join(self.dist_path, 'mutool'))
self.relink_mutool()
+ copy(self.mutool_lib, os.path.join(self.dist_path, 'libjbig2dec.0.dylib'))
else:
self._print('... WARNING: mudraw and mutool not found')
@@ -564,10 +567,10 @@
if code != 0:
raise Exception('Error running lconvert on %s' % source_path)
self._print('Copying qm files...')
- source = self.qt_translat_path
+ source = self.qt_translations_path
files = os.listdir(source)
for filename in files:
- if filename.startswith('qt_') and filename.endswith('.qm') and len(filename) == 8:
+ if filename.startswith('qt_') and filename.endswith('.qm'):
self._print_verbose('... %s', filename)
copy(os.path.join(source, filename), os.path.join(self.dist_path, 'i18n', filename))
@@ -625,86 +628,26 @@
# Release version does not contain revision in .dmg name.
if self.args.devel:
dmg_name = 'OpenLP-' + str(self.version_string) + '.dmg'
+ dmg_title = 'OpenLP {version}'.format(version=self.version_string)
else:
dmg_name = 'OpenLP-' + str(self.version_tag) + '.dmg'
+ dmg_title = 'OpenLP {version}'.format(version=self.version_tag)
- dmg_file = os.path.join(self.work_path, 'build', dmg_name)
+ self.dmg_file = os.path.join(self.work_path, 'dist', dmg_name)
# Remove dmg if it exists.
- if os.path.exists(dmg_file):
- os.remove(dmg_file)
+ if os.path.exists(self.dmg_file):
+ os.remove(self.dmg_file)
# Create empty dmg file.
size = self._get_directory_size(self.dist_app_path) # in bytes.
size = size / (1000 * 1000) # Convert to megabytes.
size += 10 # Additional space in .dmg for other files.
- self._print('... dmg disk size: %s' % size)
- self._run_command([self.hdiutil, 'create', dmg_file, '-ov', '-megabytes', str(size), '-fs', 'HFS+', '-volname',
- 'OpenLP'], 'Could not create dmg file.')
-
- # Mount empty dmg file.
- old_mounts = self._get_mountpoints()
- self._print('... mounting the dmg file: %s' % dmg_file)
- self._run_command([self.hdiutil, 'attach', dmg_file], 'Could not mount dmg file, cannot continue.')
- new_mounts = self._get_mountpoints()
- # Get the mount point from difference between paths
- # after mounting and before mounting the dmg file.
- dmg_volume_path = list(set(new_mounts) - set(old_mounts))[0]
-
- # Copy OpenLP.app and other files to .dmg
- # TODO more reliable way to determine dmg_volume_path
- self._print('... Copying the app to the dmg: ' + dmg_volume_path)
- self._run_command(['cp', '-R', self.dist_app_path, dmg_volume_path],
- 'Could not copy app bundle, dmg creation failed.')
-
- # Set icon for dmg file.
- # http://endrift.com/blog/2010/06/14/dmg-files-volume-icons-cli/
- self._print('... Setting the dmg icon.')
- dmg_icon = os.path.join(dmg_volume_path, '.VolumeIcon.icns')
- self._run_command(['cp', self.dmg_icon, dmg_icon], 'Could not copy the dmg icon file, dmg creation failed.')
- # Set proper dmg icon attributes.
- self._run_command(['SetFile', '-c', 'icnC', dmg_icon], 'Could not set dmg icon attributes.')
- # Ensures dmg icon will be used while mounted.
- self._run_command(['SetFile', '-a', 'C', dmg_volume_path], 'Could not set dmg icon attributes.')
-
- # Create symlink in dmg pointing to the /Applications directory on OS X.
- self._print('... Creating symlink to /Applications.')
- os.symlink('/Applications', os.path.join(dmg_volume_path, 'Applications'))
-
- # Set dmg background. Requires running Mac OS X gui.
- # TODO: better formatting and code refactoring
- if not self.args.devel:
- self._print('... Setting the background image.')
-
- os.mkdir(os.path.join(dmg_volume_path, '.background'))
- self._run_command(['cp', self.dmg_background_img, os.path.join(dmg_volume_path,
- '.background/installer-background.png')],
- 'Could not copy the background image, dmg creation failed.')
-
- self.adjust_dmg_view(os.path.basename(dmg_volume_path))
-
- # Unmount dmg file.
- self._print('... unmounting the dmg.')
- # Sometimes it could happen that OSX Finder is blocking umount.
- # We need to find this process and kill it.
- try:
- output = subprocess.check_output(['fuser', dmg_volume_path]).strip()
- if output:
- blocking_proc_pid = int(output.split()[0])
- os.kill(int(blocking_proc_pid), signal.SIGKILL)
- except Exception as e:
- print(str(e))
- self._print('... failed to kill process using %s' % dmg_volume_path)
- # Unmount dmg file.
- self._run_command([self.hdiutil, 'detach', dmg_volume_path],
- 'Could not unmount the dmg file, dmg creation failed.')
-
- # Compress dmg file.
- self._print('... compressing the dmg file')
- compressed_dmg = os.path.join(self.work_path, 'dist', os.path.basename(dmg_file)) # Put dmg to 'dist' dir.
- # Remove dmg if it exists.
- if os.path.exists(compressed_dmg):
- os.remove(compressed_dmg)
- self._run_command([self.hdiutil, 'convert', dmg_file, '-format', 'UDZO', '-imagekey', 'zlib-level=9', '-o',
- compressed_dmg], 'Could not compress the dmg file, dmg creation failed.')
+
+ self._print('... %s' % self.script_path)
+ os.chdir(self.script_path)
+ self._run_command([self.dmgbuild, '-s', self.dmg_settings, '-D', 'size={size}M'.format(size=size),
+ '-D', 'icon={icon_path}'.format(icon_path=self.app_icon),
+ '-D', 'app={dist_app_path}'.format(dist_app_path=self.dist_app_path), dmg_title, self.dmg_file],
+ 'Unable to run dmgbuild')
# Jenkins integration.
# Continuous integration server needs to know the filename of dmg.
@@ -713,40 +656,25 @@
fpath = os.path.join(self.branch_path, 'openlp.properties')
self._print('... writing property file for jenkins: %s' % fpath)
f = open(fpath, 'w')
- f.write('OPENLP_DMGNAME=' + os.path.basename(dmg_file) + '\n')
+ f.write('OPENLP_DMGNAME=' + os.path.basename(self.dmg_file) + '\n')
f.close()
# Dmg done.
- self._print('Finished creating dmg file, resulting file: %s' % compressed_dmg)
-
- self.dmg_file = compressed_dmg
-
- def adjust_dmg_view(self, dmg_volume_name):
- try:
- master_script = os.path.join(self.script_path, 'applescript-adjust-dmg-view.master')
- apple_script = os.path.join(self.script_path, 'adjust-dmg-view.applescript')
- with open(master_script) as r, open(apple_script, 'w') as w:
- apple_script = r.read() % {'dmg_name': dmg_volume_name, 'app_name': 'OpenLP.app'}
- w.write(apple_script)
- p = Popen([self.osascript, apple_script])
- result = p.returncode
- if (result != 0):
- self._print('Adjusting dmg view failed (non-zero exit code).')
- except (IOError, OSError):
- self._print('Adjusting dmg view failed.')
+ self._print('Finished creating dmg file, resulting file: %s' % self.dmg_file)
def main(self):
"""
The main function to run the Mac OS X builder.
"""
self._print_verbose('OpenLP main script: ......%s', self.openlp_script)
- self._print_verbose('Script path: .............%s', os.path.split(os.path.abspath(__file__))[0])
+ self._print_verbose('Script path: .............%s', self.script_path)
self._print_verbose('Branch path: .............%s', self.branch_path)
self._print_verbose('Source path: .............%s', self.source_path)
self._print_verbose('"dist.app" path: .........%s', self.dist_app_path)
self._print_verbose('"dist" path: .............%s', self.dist_path)
self._print_verbose('"hooks" path: ............%s', self.hooks_path)
self._print_verbose('PyInstaller: .............%s', self.pyinstaller)
+ self._print_verbose('dmgbuild: ................%s', self.dmgbuild)
self._print_verbose('Documentation branch path:%s', self.docs_path)
if self.mudraw_bin:
self._print_verbose('mudraw binary ............%s', self.mudraw_bin)
=== removed file 'osx/openlp-dmg.icns'
Binary files osx/openlp-dmg.icns 2016-05-03 20:04:45 +0000 and osx/openlp-dmg.icns 1970-01-01 00:00:00 +0000 differ
=== removed file 'osx/openlp-dmg.png'
Binary files osx/openlp-dmg.png 2016-05-03 20:04:45 +0000 and osx/openlp-dmg.png 1970-01-01 00:00:00 +0000 differ
=== added file 'osx/openlp-logo-new.icns'
Binary files osx/openlp-logo-new.icns 1970-01-01 00:00:00 +0000 and osx/openlp-logo-new.icns 2016-11-10 20:35:43 +0000 differ
=== removed file 'osx/openlp-logo-new.png.icns'
Binary files osx/openlp-logo-new.png.icns 2016-05-03 20:04:45 +0000 and osx/openlp-logo-new.png.icns 1970-01-01 00:00:00 +0000 differ
=== removed file 'osx/openlp-new-dmg.png'
Binary files osx/openlp-new-dmg.png 2016-05-03 20:04:45 +0000 and osx/openlp-new-dmg.png 1970-01-01 00:00:00 +0000 differ
=== removed file 'osx/openlp-new-dmg.png.icns'
Binary files osx/openlp-new-dmg.png.icns 2016-05-03 20:04:45 +0000 and osx/openlp-new-dmg.png.icns 1970-01-01 00:00:00 +0000 differ
Follow ups