Merge lp:~raoul-snyman/openlp/fix-macos-codesign into lp:openlp/packaging

Proposed by Raoul Snyman
Status: Merged
Merged at revision: 40
Proposed branch: lp:~raoul-snyman/openlp/fix-macos-codesign
Merge into: lp:openlp/packaging
Diff against target: 174 lines (+106/-10)
2 files modified
builders/builder.py (+1/-1)
builders/macosx-builder.py (+105/-9)
To merge this branch: bzr merge lp:~raoul-snyman/openlp/fix-macos-codesign
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Review via email: mp+359972@code.launchpad.net

Commit message

macOS codesigning fails on Apps with periods in file names. Incorporated fixes from PyInstaller's wiki and also updated the version number to match our new versioning scheme.

Description of the change

macOS codesigning fails on Apps with periods in file names. Incorporated fixes from PyInstaller's wiki and also updated the version number to match our new versioning scheme.

To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'builders/builder.py'
--- builders/builder.py 2018-10-27 06:08:24 +0000
+++ builders/builder.py 2018-12-02 06:11:42 +0000
@@ -311,7 +311,7 @@
311 tag, revision = lines[-1].split()311 tag, revision = lines[-1].split()
312 output = self._bzr('log', self.branch_path, ['--line', '-r', '-1'], 'Error running bzr log')312 output = self._bzr('log', self.branch_path, ['--line', '-r', '-1'], 'Error running bzr log')
313 revision = output.split(':')[0]313 revision = output.split(':')[0]
314 self.version = '{tag}-bzr{revision}'.format(tag=tag, revision=revision)314 self.version = '{tag}.dev{revision}'.format(tag=tag, revision=revision)
315 # Write the version to the version file315 # Write the version to the version file
316 with open(os.path.join(self.dist_path, '.version'), 'w') as version_file:316 with open(os.path.join(self.dist_path, '.version'), 'w') as version_file:
317 version_file.write(str(self.version))317 version_file.write(str(self.version))
318318
=== modified file 'builders/macosx-builder.py'
--- builders/macosx-builder.py 2016-12-06 20:51:27 +0000
+++ builders/macosx-builder.py 2018-12-02 06:11:42 +0000
@@ -1,5 +1,5 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=42# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
33
4###############################################################################4###############################################################################
5# OpenLP - Open Source Lyrics Projection #5# OpenLP - Open Source Lyrics Projection #
@@ -94,15 +94,15 @@
94"""94"""
9595
96import os96import os
97import plistlib97from pathlib import Path
98import signal98from shutil import copy, copytree, move, rmtree
99from shutil import copy, copytree
10099
101from macholib.MachO import MachO100from macholib.MachO import MachO
102from macholib.util import flipwritable, in_system_path101from macholib.util import in_system_path
103102
104from builder import Builder103from builder import Builder
105104
105
106class MacOSXBuilder(Builder):106class MacOSXBuilder(Builder):
107 """107 """
108 The :class:`MacosxBuilder` class encapsulates everything that is needed108 The :class:`MacosxBuilder` class encapsulates everything that is needed
@@ -119,6 +119,99 @@
119 dir_size += os.path.getsize(filename)119 dir_size += os.path.getsize(filename)
120 return dir_size120 return dir_size
121121
122 def _create_symlink(self, folder):
123 """
124 Create the appropriate symlink in the MacOS folder pointing to the Resources folder.
125 """
126 sibling = Path(str(folder).replace('MacOS', ''))
127
128 # PyQt5/Qt/qml/QtQml/Models.2
129 root = str(sibling).partition('Contents')[2].lstrip('/')
130 # ../../../../
131 backward = '../' * len(root.split('/'))
132 # ../../../../Resources/PyQt5/Qt/qml/QtQml/Models.2
133 good_path = f'{backward}Resources/{root}'
134
135 folder.symlink_to(good_path)
136
137 def _fix_qt_dll(self, dll):
138 """
139 Fix the DLL lookup paths to use relative ones for Qt dependencies.
140 Inspiration: PyInstaller/depend/dylib.py:mac_set_relative_dylib_deps()
141 Currently one header is pointing to (we are in the Resources folder):
142 @loader_path/../../../../QtCore (it is referencing to the old MacOS folder)
143 It will be converted to:
144 @loader_path/../../../../../../MacOS/QtCore
145 """
146
147 def match_func(pth):
148 """
149 Callback function for MachO.rewriteLoadCommands() that is
150 called on every lookup path setted in the DLL headers.
151 By returning None for system libraries, it changes nothing.
152 Else we return a relative path pointing to the good file
153 in the MacOS folder.
154 """
155 basename = os.path.basename(pth)
156 if not basename.startswith('Qt'):
157 return None
158 return f'@loader_path{good_path}/{basename}'
159
160 # Resources/PyQt5/Qt/qml/QtQuick/Controls.2/Fusion
161 root = str(dll.parent).partition('Contents')[2][1:]
162 # /../../../../../../..
163 backward = '/..' * len(root.split('/'))
164 # /../../../../../../../MacOS
165 good_path = f'{backward}/MacOS'
166
167 # Rewrite Mach headers with corrected @loader_path
168 dll = MachO(dll)
169 dll.rewriteLoadCommands(match_func)
170 with open(dll.filename, 'rb+') as f:
171 for header in dll.headers:
172 f.seek(0)
173 dll.write(f)
174 f.seek(0, 2)
175 f.flush()
176
177 def _find_problematic_qt_folders(self, folder):
178 """
179 Recursively yields problematic folders (containing a dot in their name).
180 """
181 for path in folder.iterdir():
182 if not path.is_dir() or path.is_symlink():
183 # Skip simlinks as they are allowed (even with a dot)
184 continue
185 if '.' in path.name:
186 yield path
187 else:
188 yield from self._find_problematic_qt_folders(path)
189
190 def _move_contents_to_resources(self, folder):
191 """
192 Recursively move any non symlink file from a problematic folder to the sibling one in Resources.
193 """
194 for path in folder.iterdir():
195 if path.is_symlink():
196 continue
197 if path.is_dir():
198 yield from self._move_contents_to_resources(path)
199 else:
200 sibling = Path(str(path).replace('MacOS', 'Resources'))
201 move(path, sibling)
202 yield sibling
203
204 def _fix_qt_paths(self):
205 """
206 Fix the Qt paths
207 """
208 app_path = Path(self.dist_app_path) / 'Contents' / 'MacOS'
209 for folder in self._find_problematic_qt_folders(app_path):
210 for problematic_file in self._move_contents_to_resources(folder):
211 self._fix_qt_dll(problematic_file)
212 rmtree(folder)
213 self._create_symlink(folder)
214
122 def _relink_mupdf(self, bin_name):215 def _relink_mupdf(self, bin_name):
123 """216 """
124 Relink mupdf to bundled libraries217 Relink mupdf to bundled libraries
@@ -181,7 +274,8 @@
181 """274 """
182 Copy Info.plist and OpenLP.icns to app bundle.275 Copy Info.plist and OpenLP.icns to app bundle.
183 """276 """
184 copy(self.icon_path, os.path.join(self.dist_app_path, 'Contents', 'Resources', os.path.basename(self.icon_path)))277 copy(self.icon_path, os.path.join(self.dist_app_path, 'Contents', 'Resources',
278 os.path.basename(self.icon_path)))
185 # Add OpenLP version to Info.plist and put it to app bundle.279 # Add OpenLP version to Info.plist and put it to app bundle.
186 fr = open(self.bundle_info_path, 'r')280 fr = open(self.bundle_info_path, 'r')
187 fw = open(os.path.join(self.dist_app_path, 'Contents', os.path.basename(self.bundle_info_path)), 'w')281 fw = open(os.path.join(self.dist_app_path, 'Contents', os.path.basename(self.bundle_info_path)), 'w')
@@ -237,9 +331,10 @@
237331
238 os.chdir(os.path.dirname(self.dmg_settings_path))332 os.chdir(os.path.dirname(self.dmg_settings_path))
239 self._run_command([self.dmgbuild_exe, '-s', self.dmg_settings_path, '-D', 'size={size}M'.format(size=size),333 self._run_command([self.dmgbuild_exe, '-s', self.dmg_settings_path, '-D', 'size={size}M'.format(size=size),
240 '-D', 'icon={icon_path}'.format(icon_path=self.icon_path),334 '-D', 'icon={icon_path}'.format(icon_path=self.icon_path),
241 '-D', 'app={dist_app_path}'.format(dist_app_path=self.dist_app_path), dmg_title, self.dmg_file],335 '-D', 'app={dist_app_path}'.format(dist_app_path=self.dist_app_path), dmg_title,
242 'Unable to run dmgbuild')336 self.dmg_file],
337 'Unable to run dmgbuild')
243338
244 # Dmg done.339 # Dmg done.
245 self._print('Finished creating dmg file, resulting file: %s' % self.dmg_file)340 self._print('Finished creating dmg file, resulting file: %s' % self.dmg_file)
@@ -299,6 +394,7 @@
299 """394 """
300 Build the actual DMG395 Build the actual DMG
301 """396 """
397 self._fix_qt_paths()
302 self._code_sign()398 self._code_sign()
303 self._create_dmg()399 self._create_dmg()
304400

Subscribers

People subscribed via source and target branches