1#!/usr/local/bin/python3.8
2# vim:fileencoding=utf-8
3# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
4
5import os
6import re
7import shlex
8import shutil
9import subprocess
10import sys
11import tempfile
12from contextlib import suppress
13
14from bypy.constants import (
15    LIBDIR, PREFIX, PYTHON, SRC as KITTY_DIR, ismacos, worker_env
16)
17from bypy.utils import run_shell, walk
18
19
20def read_src_file(name):
21    with open(os.path.join(KITTY_DIR, 'kitty', name), 'rb') as f:
22        return f.read().decode('utf-8')
23
24
25def initialize_constants():
26    kitty_constants = {}
27    src = read_src_file('constants.py')
28    nv = re.search(r'Version\((\d+), (\d+), (\d+)\)', src)
29    kitty_constants['version'] = '%s.%s.%s' % (nv.group(1), nv.group(2), nv.group(3))
30    kitty_constants['appname'] = re.search(
31            r'appname: str\s+=\s+(u{0,1})[\'"]([^\'"]+)[\'"]', src
32    ).group(2)
33    kitty_constants['cacerts_url'] = 'https://curl.haxx.se/ca/cacert.pem'
34    return kitty_constants
35
36
37def run(*args, **extra_env):
38    env = os.environ.copy()
39    env.update(worker_env)
40    env.update(extra_env)
41    env['SW'] = PREFIX
42    env['LD_LIBRARY_PATH'] = LIBDIR
43    if ismacos:
44        env['PKGCONFIG_EXE'] = os.path.join(PREFIX, 'bin', 'pkg-config')
45    cwd = env.pop('cwd', KITTY_DIR)
46    print(' '.join(map(shlex.quote, args)), flush=True)
47    return subprocess.call(list(args), env=env, cwd=cwd)
48
49
50SETUP_CMD = [PYTHON, 'setup.py', '--build-universal-binary']
51
52
53def build_frozen_launcher(extra_include_dirs):
54    inc_dirs = [f'--extra-include-dirs={x}' for x in extra_include_dirs]
55    cmd = SETUP_CMD + ['--prefix', build_frozen_launcher.prefix] + inc_dirs + ['build-frozen-launcher']
56    if run(*cmd, cwd=build_frozen_launcher.writeable_src_dir) != 0:
57        print('Building of frozen kitty launcher failed', file=sys.stderr)
58        os.chdir(KITTY_DIR)
59        run_shell()
60        raise SystemExit('Building of kitty launcher failed')
61    return build_frozen_launcher.writeable_src_dir
62
63
64def run_tests(kitty_exe):
65    with tempfile.TemporaryDirectory() as tdir:
66        env = {
67            'KITTY_CONFIG_DIRECTORY': os.path.join(tdir, 'conf'),
68            'KITTY_CACHE_DIRECTORY': os.path.join(tdir, 'cache')
69        }
70        [os.mkdir(x) for x in env.values()]
71        cmd = [kitty_exe, '+runpy', 'from kitty_tests.main import run_tests; run_tests()']
72        print(*map(shlex.quote, cmd), flush=True)
73        if subprocess.call(cmd, env=env) != 0:
74            print('Checking of kitty build failed', file=sys.stderr)
75            os.chdir(os.path.dirname(kitty_exe))
76            run_shell()
77            raise SystemExit('Checking of kitty build failed')
78
79
80def sanitize_source_folder(path: str) -> None:
81    for q in walk(path):
82        if os.path.splitext(q)[1] not in ('.py', '.glsl', '.ttf', '.otf'):
83            os.unlink(q)
84
85
86def build_c_extensions(ext_dir, args):
87    writeable_src_dir = os.path.join(ext_dir, 'src')
88    build_frozen_launcher.writeable_src_dir = writeable_src_dir
89    shutil.copytree(
90        KITTY_DIR, writeable_src_dir, symlinks=True,
91        ignore=shutil.ignore_patterns('b', 'build', 'dist', '*_commands.json', '*.o', '*.so', '*.dylib', '*.pyd'))
92
93    with suppress(FileNotFoundError):
94        os.unlink(os.path.join(writeable_src_dir, 'kitty', 'launcher', 'kitty'))
95
96    cmd = SETUP_CMD + ['macos-freeze' if ismacos else 'linux-freeze']
97    if args.dont_strip:
98        cmd.append('--debug')
99    dest = kitty_constants['appname'] + ('.app' if ismacos else '')
100    dest = build_frozen_launcher.prefix = os.path.join(ext_dir, dest)
101    cmd += ['--prefix', dest, '--full']
102    if run(*cmd, cwd=writeable_src_dir) != 0:
103        print('Building of kitty package failed', file=sys.stderr)
104        os.chdir(writeable_src_dir)
105        run_shell()
106        raise SystemExit('Building of kitty package failed')
107    return ext_dir
108
109
110if __name__ == 'program':
111    kitty_constants = initialize_constants()
112