blob: 3c8bf04c9f062c1aa47d3be2d5ec956ff1221e2d [file] [log] [blame]
Shahbaz Youssefi98a35502019-01-08 22:09:39 -05001# Copyright 2019 The ANGLE Project Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Shahbaz Youssefi98a35502019-01-08 22:09:39 -05004"""Top-level presubmit script for code generation.
5
6See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
7for more details on the presubmit API built into depot_tools.
8"""
9
Brian Sheedyc40a21f2019-09-11 17:26:00 -070010import os
11import shutil
12import subprocess
13import tempfile
Shahbaz Youssefi98a35502019-01-08 22:09:39 -050014
Jamie Madill73397e82019-01-09 10:33:16 -050015# Fragment of a regular expression that matches C++ and Objective-C++ implementation files.
16_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
17
Jamie Madill73397e82019-01-09 10:33:16 -050018# Fragment of a regular expression that matches C++ and Objective-C++ header files.
19_HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$'
20
Brian Sheedyc40a21f2019-09-11 17:26:00 -070021_PRIMARY_EXPORT_TARGETS = [
22 '//:libEGL',
23 '//:libGLESv1_CM',
24 '//:libGLESv2',
25 '//:translator',
26]
27
Jamie Madill73397e82019-01-09 10:33:16 -050028
Jamie Madill9e438ee2019-07-05 08:44:23 -040029def _CheckChangeHasBugField(input_api, output_api):
30 """Requires that the changelist have a Bug: field."""
31 bugs = input_api.change.BugsFromDescription()
32 if not bugs:
33 return [
34 output_api.PresubmitError(
35 'If this change has an associated bug, add Bug: angleproject:[bug number].')
36 ]
37 elif not all([' ' not in bug for bug in bugs]):
38 return [
39 output_api.PresubmitError(
40 'Check bug tag formatting. Ensure there are no spaces after the colon.')
41 ]
42 else:
43 return []
44
45
Jamie Madill73397e82019-01-09 10:33:16 -050046def _CheckCodeGeneration(input_api, output_api):
Jamie Madill04e9e552019-04-01 14:40:21 -040047
48 class Msg(output_api.PresubmitError):
Geoff Langd7d42392019-05-06 13:15:35 -040049 """Specialized error message"""
50
51 def __init__(self, message):
52 super(output_api.PresubmitError, self).__init__(
53 message,
Jamie Madill9e438ee2019-07-05 08:44:23 -040054 long_text='Please run scripts/run_code_generation.py to refresh generated hashes.\n'
55 '\n'
56 'If that fails, ensure your ANGLE repositiory is synced to tip-of-tree\n'
57 'and all ANGLE DEPS are fully up-to-date by running gclient sync.\n'
58 '\n'
59 'If you are building ANGLE inside Chromium you must bootstrap ANGLE\n'
60 'before gclient sync. See the DevSetup documentation for more details.\n')
Jamie Madill04e9e552019-04-01 14:40:21 -040061
Shahbaz Youssefi98a35502019-01-08 22:09:39 -050062 code_gen_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
63 'scripts/run_code_generation.py')
64 cmd_name = 'run_code_generation'
65 cmd = [input_api.python_executable, code_gen_path, '--verify-no-dirty']
Geoff Langd7d42392019-05-06 13:15:35 -040066 test_cmd = input_api.Command(name=cmd_name, cmd=cmd, kwargs={}, message=Msg)
Shahbaz Youssefi98a35502019-01-08 22:09:39 -050067 if input_api.verbose:
68 print('Running ' + cmd_name)
69 return input_api.RunTests([test_cmd])
70
Shahbaz Youssefi98a35502019-01-08 22:09:39 -050071
Jamie Madill73397e82019-01-09 10:33:16 -050072# Taken directly from Chromium's PRESUBMIT.py
73def _CheckNewHeaderWithoutGnChange(input_api, output_api):
Geoff Langd7d42392019-05-06 13:15:35 -040074 """Checks that newly added header files have corresponding GN changes.
Jamie Madill73397e82019-01-09 10:33:16 -050075 Note that this is only a heuristic. To be precise, run script:
76 build/check_gn_headers.py.
77 """
78
Geoff Langd7d42392019-05-06 13:15:35 -040079 def headers(f):
80 return input_api.FilterSourceFile(f, white_list=(r'.+%s' % _HEADER_EXTENSIONS,))
Jamie Madill73397e82019-01-09 10:33:16 -050081
Geoff Langd7d42392019-05-06 13:15:35 -040082 new_headers = []
83 for f in input_api.AffectedSourceFiles(headers):
84 if f.Action() != 'A':
85 continue
86 new_headers.append(f.LocalPath())
Jamie Madill73397e82019-01-09 10:33:16 -050087
Geoff Langd7d42392019-05-06 13:15:35 -040088 def gn_files(f):
89 return input_api.FilterSourceFile(f, white_list=(r'.+\.gn',))
Jamie Madill73397e82019-01-09 10:33:16 -050090
Geoff Langd7d42392019-05-06 13:15:35 -040091 all_gn_changed_contents = ''
92 for f in input_api.AffectedSourceFiles(gn_files):
93 for _, line in f.ChangedContents():
94 all_gn_changed_contents += line
Jamie Madill73397e82019-01-09 10:33:16 -050095
Geoff Langd7d42392019-05-06 13:15:35 -040096 problems = []
97 for header in new_headers:
98 basename = input_api.os_path.basename(header)
99 if basename not in all_gn_changed_contents:
100 problems.append(header)
Jamie Madill73397e82019-01-09 10:33:16 -0500101
Geoff Langd7d42392019-05-06 13:15:35 -0400102 if problems:
103 return [
104 output_api.PresubmitPromptWarning(
105 'Missing GN changes for new header files',
106 items=sorted(problems),
107 long_text='Please double check whether newly added header files need '
108 'corresponding changes in gn or gni files.\nThis checking is only a '
109 'heuristic. Run build/check_gn_headers.py to be precise.\n'
110 'Read https://crbug.com/661774 for more info.')
111 ]
112 return []
Jamie Madill73397e82019-01-09 10:33:16 -0500113
114
Brian Sheedyc40a21f2019-09-11 17:26:00 -0700115def _CheckExportValidity(input_api, output_api):
116 outdir = tempfile.mkdtemp()
117 try:
118 try:
119 subprocess.check_output(['gn', 'gen', outdir])
120 except subprocess.CalledProcessError as e:
121 return [
122 output_api.PresubmitError(
123 'Unable to run gn gen for export_targets.py: %s' % e.output)
124 ]
125 export_target_script = os.path.join(input_api.PresubmitLocalPath(), 'scripts',
126 'export_targets.py')
127 try:
128 subprocess.check_output(
129 ['vpython3', export_target_script, outdir] + _PRIMARY_EXPORT_TARGETS,
130 stderr=subprocess.STDOUT)
131 except subprocess.CalledProcessError as e:
132 if input_api.is_committing:
133 return [output_api.PresubmitError('export_targets.py failed: %s' % e.output)]
134 return [
135 output_api.PresubmitPromptWarning(
136 'export_targets.py failed, this may just be due to your local checkout: %s' %
137 e.output)
138 ]
139 return []
140 finally:
141 shutil.rmtree(outdir)
142
143
Jamie Madill73397e82019-01-09 10:33:16 -0500144def CheckChangeOnUpload(input_api, output_api):
145 results = []
146 results.extend(_CheckCodeGeneration(input_api, output_api))
Jamie Madill9e438ee2019-07-05 08:44:23 -0400147 results.extend(_CheckChangeHasBugField(input_api, output_api))
Geoff Langd7d42392019-05-06 13:15:35 -0400148 results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api))
Jamie Madill73397e82019-01-09 10:33:16 -0500149 results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api))
Brian Sheedyc40a21f2019-09-11 17:26:00 -0700150 results.extend(_CheckExportValidity(input_api, output_api))
Jamie Madill9e438ee2019-07-05 08:44:23 -0400151 results.extend(
152 input_api.canned_checks.CheckPatchFormatted(
153 input_api, output_api, result_factory=output_api.PresubmitError))
Jamie Madill73397e82019-01-09 10:33:16 -0500154 return results
155
Shahbaz Youssefi98a35502019-01-08 22:09:39 -0500156
157def CheckChangeOnCommit(input_api, output_api):
Jamie Madill73397e82019-01-09 10:33:16 -0500158 results = []
Jamie Madill04e9e552019-04-01 14:40:21 -0400159 results.extend(_CheckCodeGeneration(input_api, output_api))
Jamie Madill9e438ee2019-07-05 08:44:23 -0400160 results.extend(
161 input_api.canned_checks.CheckPatchFormatted(
162 input_api, output_api, result_factory=output_api.PresubmitError))
163 results.extend(_CheckChangeHasBugField(input_api, output_api))
Brian Sheedyc40a21f2019-09-11 17:26:00 -0700164 results.extend(_CheckExportValidity(input_api, output_api))
Geoff Langd7d42392019-05-06 13:15:35 -0400165 results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api))
Jamie Madill73397e82019-01-09 10:33:16 -0500166 return results