summaryrefslogtreecommitdiffstats
path: root/build/scripts/with_kapt_args.py
blob: fec95fc7cd98f1445b487d654fd65cc77590763b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import sys
import os
import subprocess
import platform
import argparse
import re
import struct
import base64


def parse_args(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('--ap-classpath', nargs='*', type=str, dest='classpath')
    parser.add_argument('--ap-options', nargs='*', type=str, dest='ap_options')
    cmd_start = args.index('--')
    return parser.parse_args(args[:cmd_start]), args[cmd_start + 1 :]


def get_ap_classpath(directory):
    jar_re = re.compile(r'.*(?<!-sources)\.jar')
    found_jars = [
        os.path.join(address, name)
        for address, dirs, files in os.walk(directory)
        for name in files
        if jar_re.match(name)
    ]
    if len(found_jars) != 1:
        raise Exception("found %d JAR files in directory %s" % (len(found_jars), directory))
    arg = 'plugin:org.jetbrains.kotlin.kapt3:apclasspath=' + found_jars[0]
    return '-P', arg


def get_ap_options(ap_options):
    if not ap_options:
        return []
    # Format of apoptions https://kotlinlang.org/docs/kapt.html#ap-javac-options-encoding
    # ObjectOutputStream https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/io/ObjectOutputStream.java

    kvs = bytes()  # all key-values
    for ap_option in ap_options:
        try:
            k, v = ap_option.split('=', 1)
        except ValueError:
            import logging

            logging.error("Expect key=value format at '" + ap_option + "' in KAPT_ANNOTATION_PROCESSOR_OPTIONS")
            continue
        k = bytes(k.encode('UTF-8'))  # UTF-8 supported
        kvs += struct.pack(">H", len(k))
        kvs += k
        v = bytes(v.encode('UTF-8'))  # UTF-8 supported
        kvs += struct.pack(">H", len(v))
        kvs += v

    s = struct.pack(">H", 0xACED)  # STREAM_MAGIC
    s += struct.pack(">H", 0x0005)  # STREAM_VERSION
    data_len = 4 + len(kvs)  # sizeof(ui32) options count + length of all key-values
    if data_len < 256:
        s += struct.pack("B", 0x77)  # TC_BLOCKDATA
        s += struct.pack("B", data_len)
    else:
        s += struct.pack("B", 0x7A)  # TC_BLOCKDATALONG
        s += struct.pack(">I", data_len)
    s += struct.pack(">I", len(ap_options))  # count of options
    s += kvs  # key-values of all options

    arg = 'plugin:org.jetbrains.kotlin.kapt3:apoptions=' + base64.b64encode(s).decode('utf-8')
    return '-P', arg


def create_extra_args(args):
    cp_opts = [arg for d in args.classpath for arg in get_ap_classpath(d)] + [
        arg for arg in get_ap_options(args.ap_options)
    ]
    return cp_opts


if __name__ == '__main__':
    args, cmd = parse_args(sys.argv[1:])
    res = cmd + create_extra_args(args)
    if platform.system() == 'Windows':
        sys.exit(subprocess.Popen(res).wait())
    else:
        os.execv(res[0], res)