macOS: Notarize the kitty application

This required the kitty package to be moved from Frameworks to
Resources, because Apple cant codesign .pyc files and its notarization
requires everything in Frameworks to be signed. Hopefully that does not
break anything. Also removed the kitty-deref-symlink since it is not
needed anyway and was only present for backwards compatibility.

Fixes #2040
This commit is contained in:
Kovid Goyal 2020-06-05 22:52:30 +05:30
parent 408508247d
commit 1326532850
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 65 additions and 6 deletions

View File

@ -13,6 +13,10 @@ import tempfile
import zipfile import zipfile
from bypy.constants import PREFIX, PYTHON, SW, python_major_minor_version from bypy.constants import PREFIX, PYTHON, SW, python_major_minor_version
from bypy.macos_sign import (
codesign, create_entitlements_file, make_certificate_useable, notarize_app,
verify_signature
)
from bypy.utils import current_dir, py_compile, run_shell, timeit, walk from bypy.utils import current_dir, py_compile, run_shell, timeit, walk
iv = globals()['init_env'] iv = globals()['init_env']
@ -76,8 +80,54 @@ def strip_files(files, argv_max=(256 * 1024)):
flipwritable(*args) flipwritable(*args)
def files_in(folder):
for record in os.walk(folder):
for f in record[-1]:
yield os.path.join(record[0], f)
def expand_dirs(items, exclude=lambda x: x.endswith('.so')):
items = set(items)
dirs = set(x for x in items if os.path.isdir(x))
items.difference_update(dirs)
for x in dirs:
items.update({y for y in files_in(x) if not exclude(y)})
return items
def do_sign(app_dir):
with current_dir(os.path.join(app_dir, 'Contents')):
# Sign all .so files
so_files = {x for x in files_in('.') if x.endswith('.so')}
codesign(so_files)
# Sign everything else in Frameworks
with current_dir('Frameworks'):
fw = set(glob.glob('*.framework'))
codesign(fw)
items = set(os.listdir('.')) - fw
codesign(expand_dirs(items))
# Now sign the main app
codesign(app_dir)
verify_signature(app_dir)
def sign_app(app_dir, notarize): def sign_app(app_dir, notarize):
pass # Copied from iTerm2: https://github.com/gnachman/iTerm2/blob/master/iTerm2.entitlements
create_entitlements_file({
'com.apple.security.automation.apple-events': True,
'com.apple.security.cs.allow-jit': True,
'com.apple.security.device.audio-input': True,
'com.apple.security.device.camera': True,
'com.apple.security.personal-information.addressbook': True,
'com.apple.security.personal-information.calendars': True,
'com.apple.security.personal-information.location': True,
'com.apple.security.personal-information.photos-library': True,
})
with make_certificate_useable():
do_sign(app_dir)
if notarize:
notarize_app(app_dir)
class Freeze(object): class Freeze(object):
@ -111,6 +161,7 @@ class Freeze(object):
self.add_stdlib() self.add_stdlib()
self.add_misc_libraries() self.add_misc_libraries()
self.compile_py_modules() self.compile_py_modules()
self.fix_dependencies_in_kitty()
if not self.dont_strip: if not self.dont_strip:
self.strip_files() self.strip_files()
# self.run_shell() # self.run_shell()
@ -248,6 +299,12 @@ class Freeze(object):
if f.endswith('.so'): if f.endswith('.so'):
self.fix_dependencies_in_lib(f) self.fix_dependencies_in_lib(f)
@flush
def fix_dependencies_in_kitty(self):
for f in walk(join(self.resources_dir, 'kitty')):
if f.endswith('.so'):
self.fix_dependencies_in_lib(f)
@flush @flush
def postprocess_package(self, src_path, dest_path): def postprocess_package(self, src_path, dest_path):
pass pass
@ -334,8 +391,8 @@ class Freeze(object):
print('\nCompiling Python modules') print('\nCompiling Python modules')
self.remove_bytecode(join(self.resources_dir, 'Python')) self.remove_bytecode(join(self.resources_dir, 'Python'))
py_compile(join(self.resources_dir, 'Python')) py_compile(join(self.resources_dir, 'Python'))
self.remove_bytecode(join(self.frameworks_dir, 'kitty')) self.remove_bytecode(join(self.resources_dir, 'kitty'))
py_compile(join(self.frameworks_dir, 'kitty')) py_compile(join(self.resources_dir, 'kitty'))
@flush @flush
def makedmg(self, d, volname, internet_enable=True, format='ULFO'): def makedmg(self, d, volname, internet_enable=True, format='ULFO'):

View File

@ -36,6 +36,8 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- X11: Recompile keymaps on XkbNewKeyboardNotify events (:iss:`2726`) - X11: Recompile keymaps on XkbNewKeyboardNotify events (:iss:`2726`)
- macOS: Notarize the kitty application (:iss:`2040`)
0.17.4 [2020-05-09] 0.17.4 [2020-05-09]
-------------------- --------------------

View File

@ -737,7 +737,7 @@ def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 's
elif bundle_type == 'source': elif bundle_type == 'source':
cppflags.append('-DFROM_SOURCE') cppflags.append('-DFROM_SOURCE')
if bundle_type.startswith('macos-'): if bundle_type.startswith('macos-'):
klp = '../Frameworks/kitty' klp = '../Resources/kitty'
elif bundle_type.startswith('linux-'): elif bundle_type.startswith('linux-'):
klp = '../{}/kitty'.format(args.libdir_name.strip('/')) klp = '../{}/kitty'.format(args.libdir_name.strip('/'))
elif bundle_type == 'source': elif bundle_type == 'source':
@ -942,9 +942,9 @@ def create_macos_bundle_gunk(dest: str) -> None:
os.rename(ddir / 'share', ddir / 'Contents/Resources') os.rename(ddir / 'share', ddir / 'Contents/Resources')
os.rename(ddir / 'bin', ddir / 'Contents/MacOS') os.rename(ddir / 'bin', ddir / 'Contents/MacOS')
os.rename(ddir / 'lib', ddir / 'Contents/Frameworks') os.rename(ddir / 'lib', ddir / 'Contents/Frameworks')
os.symlink('kitty', ddir / 'Contents/MacOS/kitty-deref-symlink') os.rename(ddir / 'Contents/Frameworks/kitty', ddir / 'Contents/Resources/kitty')
launcher = ddir / 'Contents/MacOS/kitty' launcher = ddir / 'Contents/MacOS/kitty'
in_src_launcher = ddir / 'Contents/Frameworks/kitty/kitty/launcher/kitty' in_src_launcher = ddir / 'Contents/Resources/kitty/kitty/launcher/kitty'
if os.path.exists(in_src_launcher): if os.path.exists(in_src_launcher):
os.remove(in_src_launcher) os.remove(in_src_launcher)
os.makedirs(os.path.dirname(in_src_launcher), exist_ok=True) os.makedirs(os.path.dirname(in_src_launcher), exist_ok=True)