From afcc047ee3e4cfd96272513198b4f46b2f38bfe6 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 12 Jul 2018 21:41:00 +0200 Subject: [PATCH 1/4] Add an option for providing tag and revision to avoid using bzr. --- builders/builder.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/builders/builder.py b/builders/builder.py index 6aec400..9670c69 100644 --- a/builders/builder.py +++ b/builders/builder.py @@ -160,6 +160,8 @@ class Builder(object): parser.add_argument('--skip-translations', action='store_true', default=False, help='Do NOT update the language translation files') parser.add_argument('--debug', action='store_true', default=False, help='Create a debug build') + parser.add_argument('--tag-override', metavar='-bzr', default=None, + help='Override tag and revision, should be in format -bzr') self.add_extra_args(parser) self.args = parser.parse_args() @@ -297,17 +299,20 @@ class Builder(object): """ self._print('Writing version file...') if not self.args.release: - # This is a development build, get the tag and revision - output = self._bzr('tags', self.branch_path, err_msg='Error running bzr tags') - lines = output.splitlines() - if len(lines) == 0: - tag = '0.0.0' - revision = '0' + if self.args.tag_override: + self.version = self.args.tag_override else: - tag, revision = lines[-1].split() - output = self._bzr('log', self.branch_path, ['--line', '-r', '-1'], 'Error running bzr log') - revision = output.split(':')[0] - self.version = '{tag}-bzr{revision}'.format(tag=tag, revision=revision) + # This is a development build, get the tag and revision + output = self._bzr('tags', self.branch_path, err_msg='Error running bzr tags') + lines = output.splitlines() + if len(lines) == 0: + tag = '0.0.0' + revision = '0' + else: + tag, revision = lines[-1].split() + output = self._bzr('log', self.branch_path, ['--line', '-r', '-1'], 'Error running bzr log') + revision = output.split(':')[0] + self.version = '{tag}-bzr{revision}'.format(tag=tag, revision=revision) # Write the version to the version file with open(os.path.join(self.dist_path, '.version'), 'w') as version_file: version_file.write(str(self.version)) From 57caf4e5bbdaea080cf8ad05df147ae258df6738 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 26 Oct 2018 23:08:24 -0700 Subject: [PATCH 2/4] Fix builder script to use new OpenLP run script name. --- builders/builder.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/builders/builder.py b/builders/builder.py index 9670c69..31252bc 100644 --- a/builders/builder.py +++ b/builders/builder.py @@ -218,7 +218,7 @@ class Builder(object): else: self.version = None self.work_path = self.branch_path - self.openlp_script = os.path.abspath(os.path.join(self.work_path, 'openlp-run.py')) + self.openlp_script = os.path.abspath(os.path.join(self.work_path, 'run_openlp.py')) self.source_path = os.path.join(self.work_path, 'openlp') self.manual_path = os.path.join(self.documentation_path, 'manual') self.manual_build_path = os.path.join(self.manual_path, 'build') @@ -269,7 +269,6 @@ class Builder(object): Run PyInstaller on the branch to build an executable. """ self._print('Running PyInstaller...') - copy(os.path.join(self.work_path, 'openlp.py'), self.openlp_script) os.chdir(self.work_path) cmd = [self.python, self.pyinstaller_exe, @@ -428,7 +427,8 @@ class Builder(object): rmtree(self.manual_build_path) os.chdir(self.manual_path) sphinx_build = self.get_sphinx_build() - command = [self.sphinx_exe, '-b', sphinx_build, '-d', 'build/doctrees', 'source', 'build/{}'.format(sphinx_build)] + command = [self.sphinx_exe, '-b', sphinx_build, '-d', 'build/doctrees', 'source', + 'build/{}'.format(sphinx_build)] self._run_command(command, 'Error running Sphinx') self.after_run_sphinx() @@ -477,5 +477,3 @@ class Builder(object): self._print('Done.') raise SystemExit() - - From 499847bbcdc0ac35cf776d71ff467e439154fcae Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sat, 27 Oct 2018 10:35:03 -0700 Subject: [PATCH 3/4] Fix Qt paths so that code signing works --- builders/macosx-builder.py | 114 ++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 9 deletions(-) diff --git a/builders/macosx-builder.py b/builders/macosx-builder.py index 8213434..01afda8 100644 --- a/builders/macosx-builder.py +++ b/builders/macosx-builder.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 ############################################################################### # OpenLP - Open Source Lyrics Projection # @@ -94,15 +94,15 @@ You may need to install chardet via pip:: """ import os -import plistlib -import signal -from shutil import copy, copytree +from pathlib import Path +from shutil import copy, copytree, move, rmtree from macholib.MachO import MachO -from macholib.util import flipwritable, in_system_path +from macholib.util import in_system_path from builder import Builder + class MacOSXBuilder(Builder): """ The :class:`MacosxBuilder` class encapsulates everything that is needed @@ -119,6 +119,99 @@ class MacOSXBuilder(Builder): dir_size += os.path.getsize(filename) return dir_size + def _create_symlink(self, folder): + """ + Create the appropriate symlink in the MacOS folder pointing to the Resources folder. + """ + sibling = Path(str(folder).replace('MacOS', '')) + + # PyQt5/Qt/qml/QtQml/Models.2 + root = str(sibling).partition('Contents')[2].lstrip('/') + # ../../../../ + backward = '../' * len(root.split('/')) + # ../../../../Resources/PyQt5/Qt/qml/QtQml/Models.2 + good_path = f'{backward}Resources/{root}' + + folder.symlink_to(good_path) + + def _fix_qt_dll(self, dll): + """ + Fix the DLL lookup paths to use relative ones for Qt dependencies. + Inspiration: PyInstaller/depend/dylib.py:mac_set_relative_dylib_deps() + Currently one header is pointing to (we are in the Resources folder): + @loader_path/../../../../QtCore (it is referencing to the old MacOS folder) + It will be converted to: + @loader_path/../../../../../../MacOS/QtCore + """ + + def match_func(pth): + """ + Callback function for MachO.rewriteLoadCommands() that is + called on every lookup path setted in the DLL headers. + By returning None for system libraries, it changes nothing. + Else we return a relative path pointing to the good file + in the MacOS folder. + """ + basename = os.path.basename(pth) + if not basename.startswith('Qt'): + return None + return f'@loader_path{good_path}/{basename}' + + # Resources/PyQt5/Qt/qml/QtQuick/Controls.2/Fusion + root = str(dll.parent).partition('Contents')[2][1:] + # /../../../../../../.. + backward = '/..' * len(root.split('/')) + # /../../../../../../../MacOS + good_path = f'{backward}/MacOS' + + # Rewrite Mach headers with corrected @loader_path + dll = MachO(dll) + dll.rewriteLoadCommands(match_func) + with open(dll.filename, 'rb+') as f: + for header in dll.headers: + f.seek(0) + dll.write(f) + f.seek(0, 2) + f.flush() + + def _find_problematic_qt_folders(self, folder): + """ + Recursively yields problematic folders (containing a dot in their name). + """ + for path in folder.iterdir(): + if not path.is_dir() or path.is_symlink(): + # Skip simlinks as they are allowed (even with a dot) + continue + if '.' in path.name: + yield path + else: + yield from self._find_problematic_qt_folders(path) + + def _move_contents_to_resources(self, folder): + """ + Recursively move any non symlink file from a problematic folder to the sibling one in Resources. + """ + for path in folder.iterdir(): + if path.is_symlink(): + continue + if path.is_dir(): + yield from self._move_contents_to_resources(path) + else: + sibling = Path(str(path).replace('MacOS', 'Resources')) + move(path, sibling) + yield sibling + + def _fix_qt_paths(self): + """ + Fix the Qt paths + """ + app_path = Path(self.dist_app_path) / 'Contents' / 'MacOS' + for folder in self._find_problematic_qt_folders(app_path): + for problematic_file in self._move_contents_to_resources(folder): + self._fix_qt_dll(problematic_file) + rmtree(folder) + self._create_symlink(folder) + def _relink_mupdf(self, bin_name): """ Relink mupdf to bundled libraries @@ -181,7 +274,8 @@ class MacOSXBuilder(Builder): """ Copy Info.plist and OpenLP.icns to app bundle. """ - copy(self.icon_path, os.path.join(self.dist_app_path, 'Contents', 'Resources', os.path.basename(self.icon_path))) + copy(self.icon_path, os.path.join(self.dist_app_path, 'Contents', 'Resources', + os.path.basename(self.icon_path))) # Add OpenLP version to Info.plist and put it to app bundle. fr = open(self.bundle_info_path, 'r') fw = open(os.path.join(self.dist_app_path, 'Contents', os.path.basename(self.bundle_info_path)), 'w') @@ -237,9 +331,10 @@ class MacOSXBuilder(Builder): os.chdir(os.path.dirname(self.dmg_settings_path)) self._run_command([self.dmgbuild_exe, '-s', self.dmg_settings_path, '-D', 'size={size}M'.format(size=size), - '-D', 'icon={icon_path}'.format(icon_path=self.icon_path), - '-D', 'app={dist_app_path}'.format(dist_app_path=self.dist_app_path), dmg_title, self.dmg_file], - 'Unable to run dmgbuild') + '-D', 'icon={icon_path}'.format(icon_path=self.icon_path), + '-D', 'app={dist_app_path}'.format(dist_app_path=self.dist_app_path), dmg_title, + self.dmg_file], + 'Unable to run dmgbuild') # Dmg done. self._print('Finished creating dmg file, resulting file: %s' % self.dmg_file) @@ -299,6 +394,7 @@ class MacOSXBuilder(Builder): """ Build the actual DMG """ + self._fix_qt_paths() self._code_sign() self._create_dmg() From 16a8037d44b2b256d5f435a582b1794901d70f1f Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sat, 1 Dec 2018 23:07:08 -0700 Subject: [PATCH 4/4] Use new version number format --- builders/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builders/builder.py b/builders/builder.py index 31252bc..e3cc5ee 100644 --- a/builders/builder.py +++ b/builders/builder.py @@ -311,7 +311,7 @@ class Builder(object): tag, revision = lines[-1].split() output = self._bzr('log', self.branch_path, ['--line', '-r', '-1'], 'Error running bzr log') revision = output.split(':')[0] - self.version = '{tag}-bzr{revision}'.format(tag=tag, revision=revision) + self.version = '{tag}.dev{revision}'.format(tag=tag, revision=revision) # Write the version to the version file with open(os.path.join(self.dist_path, '.version'), 'w') as version_file: version_file.write(str(self.version))