Browse Source

Use dmgbuild instead of all the manual nonsense

merge-requests/1/merge
Raoul Snyman 6 years ago
parent
commit
6c48676954
  1. 1
      .bzrignore
  2. BIN
      osx/DmgImageInstallBackground.png
  3. 32
      osx/applescript-adjust-dmg-view.master
  4. 7
      osx/config.ini.default
  5. BIN
      osx/dmg-background-new-with-icons.png
  6. BIN
      osx/dmg-background-new.png
  7. BIN
      osx/dmg-background.png
  8. 27
      osx/dmg-settings-new.py
  9. 27
      osx/dmg-settings.py
  10. 126
      osx/macosx-builder.py
  11. BIN
      osx/openlp-dmg.icns
  12. BIN
      osx/openlp-dmg.png
  13. 0
      osx/openlp-logo-new.icns
  14. BIN
      osx/openlp-new-dmg.png
  15. BIN
      osx/openlp-new-dmg.png.icns

1
.bzrignore

@ -34,3 +34,4 @@ __pycache__
*.dll
*.DS_Store
config.ini
*.dmg

BIN
osx/DmgImageInstallBackground.png

Binary file not shown.

Before

Width: 700  |  Height: 400  |  Size: 48 KiB

32
osx/applescript-adjust-dmg-view.master

@ -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

7
osx/config.ini.default

@ -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 @@ mutoolbin = mutool
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 =

BIN
osx/dmg-background-new-with-icons.png

Binary file not shown.

After

Width: 700  |  Height: 417  |  Size: 80 KiB

BIN
osx/dmg-background-new.png

Binary file not shown.

After

Width: 700  |  Height: 417  |  Size: 68 KiB

BIN
osx/dmg-background.png

Binary file not shown.

After

Width: 700  |  Height: 420  |  Size: 49 KiB

27
osx/dmg-settings-new.py

@ -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

27
osx/dmg-settings.py

@ -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

126
osx/macosx-builder.py

@ -27,9 +27,9 @@ Mac OS X Build Script
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 @@ def _which(command):
"""
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,9 +239,7 @@ class MacosxBuilder(object):
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'))
@ -264,9 +264,7 @@ class MacosxBuilder(object):
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 +273,13 @@ class MacosxBuilder(object):
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):
"""
@ -564,10 +563,10 @@ class MacosxBuilder(object):
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 +624,26 @@ class MacosxBuilder(object):
# 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 +652,25 @@ class MacosxBuilder(object):
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)

BIN
osx/openlp-dmg.icns

Binary file not shown.

BIN
osx/openlp-dmg.png

Binary file not shown.

Before

Width: 512  |  Height: 512  |  Size: 101 KiB

0
osx/openlp-logo-new.png.icns → osx/openlp-logo-new.icns

BIN
osx/openlp-new-dmg.png

Binary file not shown.

Before

Width: 512  |  Height: 512  |  Size: 87 KiB

BIN
osx/openlp-new-dmg.png.icns

Binary file not shown.
Loading…
Cancel
Save