aboutsummaryrefslogtreecommitdiffstats
path: root/build/scripts/run_javac.py
blob: c35546e0fefded64803bdd1c1eb0aaa8acda5831 (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import sys
import subprocess
import optparse
import re


def parse_args():
    parser = optparse.OptionParser()
    parser.disable_interspersed_args()
    parser.add_option('--sources-list')
    parser.add_option('--verbose', default=False, action='store_true')
    parser.add_option('--remove-notes', default=False, action='store_true')
    parser.add_option('--ignore-errors', default=False, action='store_true')
    parser.add_option('--kotlin', default=False, action='store_true')
    return parser.parse_args()


COLORING = {
    r'^(?P<path>.*):(?P<line>\d*): error: (?P<msg>.*)': lambda m: '[[unimp]]{path}[[rst]]:[[alt2]]{line}[[rst]]: [[c:light-red]]error[[rst]]: [[bad]]{msg}[[rst]]'.format(
        path=m.group('path'),
        line=m.group('line'),
        msg=m.group('msg'),
    ),
    r'^(?P<path>.*):(?P<line>\d*): warning: (?P<msg>.*)': lambda m: '[[unimp]]{path}[[rst]]:[[alt2]]{line}[[rst]]: [[c:light-yellow]]warning[[rst]]: {msg}'.format(
        path=m.group('path'),
        line=m.group('line'),
        msg=m.group('msg'),
    ),
    r'^warning: ': lambda m: '[[c:light-yellow]]warning[[rst]]: ',
    r'^error: (?P<msg>.*)': lambda m: '[[c:light-red]]error[[rst]]: [[bad]]{msg}[[rst]]'.format(msg=m.group('msg')),
    r'^Note: ': lambda m: '[[c:light-cyan]]Note[[rst]]: ',
}


def colorize(err):
    for regex, sub in COLORING.iteritems():
        err = re.sub(regex, sub, err, flags=re.MULTILINE)
    return err


def remove_notes(err):
    return '\n'.join([line for line in err.split('\n') if not line.startswith('Note:')])


def find_javac(cmd):
    if not cmd:
        return None
    if cmd[0].endswith('javac') or cmd[0].endswith('javac.exe'):
        return cmd[0]
    if len(cmd) > 2 and cmd[1].endswith('build_java_with_error_prone.py'):
        for javas in ('java', 'javac'):
            if cmd[2].endswith(javas) or cmd[2].endswith(javas + '.exe'):
                return cmd[2]
    return None


# temporary, for jdk8/jdk9+ compatibility
def fix_cmd(cmd):
    if not cmd:
        return cmd
    javac = find_javac(cmd)
    if not javac:
        return cmd
    p = subprocess.Popen([javac, '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    out, err = out.strip(), err.strip()
    for prefix in ('javac 1.8', 'java version "1.8'):
        for raw_out in ((out or ''), (err or '')):
            for line in raw_out.split('\n'):
                if line.startswith(prefix):
                    res = []
                    i = 0
                    while i < len(cmd):
                        for option in ('--add-exports', '--add-modules'):
                            if cmd[i] == option:
                                i += 1
                                break
                            elif cmd[i].startswith(option + '='):
                                break
                        else:
                            res.append(cmd[i])
                        i += 1
                    return res
    return cmd


def main():
    opts, cmd = parse_args()

    with open(opts.sources_list) as f:
        input_files = f.read().strip().split()

    if opts.kotlin:
        input_files = [i for i in input_files if i.endswith('.kt')]

    if not input_files:
        if opts.verbose:
            sys.stderr.write('No files to compile, javac is not launched.\n')

    else:
        p = subprocess.Popen(fix_cmd(cmd), stderr=subprocess.PIPE)
        _, err = p.communicate()
        rc = p.wait()

        if opts.remove_notes:
            err = remove_notes(err)

        try:
            err = colorize(err)

        except Exception:
            pass

        if opts.ignore_errors and rc:
            sys.stderr.write('error: javac actually failed with exit code {}\n'.format(rc))
            rc = 0
        sys.stderr.write(err)
        sys.exit(rc)


if __name__ == '__main__':
    main()