Shahbaz Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 1 | # 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 Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 4 | """Top-level presubmit script for code generation. |
| 5 | |
| 6 | See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
| 7 | for more details on the presubmit API built into depot_tools. |
| 8 | """ |
| 9 | |
Brian Sheedy | cc4d833 | 2019-09-11 17:26:00 -0700 | [diff] [blame] | 10 | import os |
| 11 | import shutil |
| 12 | import subprocess |
| 13 | import sys |
| 14 | import tempfile |
Shahbaz Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 15 | |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 16 | # Fragment of a regular expression that matches C++ and Objective-C++ implementation files. |
| 17 | _IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$' |
| 18 | |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 19 | # Fragment of a regular expression that matches C++ and Objective-C++ header files. |
| 20 | _HEADER_EXTENSIONS = r'\.(h|hpp|hxx)$' |
| 21 | |
Brian Sheedy | cc4d833 | 2019-09-11 17:26:00 -0700 | [diff] [blame] | 22 | _PRIMARY_EXPORT_TARGETS = [ |
| 23 | '//:libEGL', |
| 24 | '//:libGLESv1_CM', |
| 25 | '//:libGLESv2', |
| 26 | '//:translator', |
| 27 | ] |
| 28 | |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 29 | |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 30 | def _CheckChangeHasBugField(input_api, output_api): |
| 31 | """Requires that the changelist have a Bug: field.""" |
| 32 | bugs = input_api.change.BugsFromDescription() |
| 33 | if not bugs: |
| 34 | return [ |
Alexis Hetu | 4210e49 | 2019-10-10 14:22:03 -0400 | [diff] [blame] | 35 | output_api.PresubmitError('Please ensure that your description contains:\n' |
| 36 | '"Bug: angleproject:[bug number]"\n' |
| 37 | 'directly above the Change-Id tag.') |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 38 | ] |
| 39 | elif not all([' ' not in bug for bug in bugs]): |
| 40 | return [ |
| 41 | output_api.PresubmitError( |
| 42 | 'Check bug tag formatting. Ensure there are no spaces after the colon.') |
| 43 | ] |
| 44 | else: |
| 45 | return [] |
| 46 | |
| 47 | |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 48 | def _CheckCodeGeneration(input_api, output_api): |
Jamie Madill | 04e9e55 | 2019-04-01 14:40:21 -0400 | [diff] [blame] | 49 | |
| 50 | class Msg(output_api.PresubmitError): |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 51 | """Specialized error message""" |
| 52 | |
| 53 | def __init__(self, message): |
| 54 | super(output_api.PresubmitError, self).__init__( |
| 55 | message, |
Jamie Madill | 8dfc2b0 | 2019-11-25 15:12:58 -0500 | [diff] [blame] | 56 | long_text='Please ensure your ANGLE repositiory is synced to tip-of-tree\n' |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 57 | 'and all ANGLE DEPS are fully up-to-date by running gclient sync.\n' |
| 58 | '\n' |
Jamie Madill | 8dfc2b0 | 2019-11-25 15:12:58 -0500 | [diff] [blame] | 59 | 'If that fails, run scripts/run_code_generation.py to refresh generated hashes.\n' |
| 60 | '\n' |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 61 | 'If you are building ANGLE inside Chromium you must bootstrap ANGLE\n' |
| 62 | 'before gclient sync. See the DevSetup documentation for more details.\n') |
Jamie Madill | 04e9e55 | 2019-04-01 14:40:21 -0400 | [diff] [blame] | 63 | |
Shahbaz Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 64 | code_gen_path = input_api.os_path.join(input_api.PresubmitLocalPath(), |
| 65 | 'scripts/run_code_generation.py') |
| 66 | cmd_name = 'run_code_generation' |
| 67 | cmd = [input_api.python_executable, code_gen_path, '--verify-no-dirty'] |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 68 | test_cmd = input_api.Command(name=cmd_name, cmd=cmd, kwargs={}, message=Msg) |
Shahbaz Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 69 | if input_api.verbose: |
| 70 | print('Running ' + cmd_name) |
| 71 | return input_api.RunTests([test_cmd]) |
| 72 | |
Shahbaz Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 73 | |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 74 | # Taken directly from Chromium's PRESUBMIT.py |
| 75 | def _CheckNewHeaderWithoutGnChange(input_api, output_api): |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 76 | """Checks that newly added header files have corresponding GN changes. |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 77 | Note that this is only a heuristic. To be precise, run script: |
| 78 | build/check_gn_headers.py. |
| 79 | """ |
| 80 | |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 81 | def headers(f): |
| 82 | return input_api.FilterSourceFile(f, white_list=(r'.+%s' % _HEADER_EXTENSIONS,)) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 83 | |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 84 | new_headers = [] |
| 85 | for f in input_api.AffectedSourceFiles(headers): |
| 86 | if f.Action() != 'A': |
| 87 | continue |
| 88 | new_headers.append(f.LocalPath()) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 89 | |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 90 | def gn_files(f): |
| 91 | return input_api.FilterSourceFile(f, white_list=(r'.+\.gn',)) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 92 | |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 93 | all_gn_changed_contents = '' |
| 94 | for f in input_api.AffectedSourceFiles(gn_files): |
| 95 | for _, line in f.ChangedContents(): |
| 96 | all_gn_changed_contents += line |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 97 | |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 98 | problems = [] |
| 99 | for header in new_headers: |
| 100 | basename = input_api.os_path.basename(header) |
| 101 | if basename not in all_gn_changed_contents: |
| 102 | problems.append(header) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 103 | |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 104 | if problems: |
| 105 | return [ |
| 106 | output_api.PresubmitPromptWarning( |
| 107 | 'Missing GN changes for new header files', |
| 108 | items=sorted(problems), |
| 109 | long_text='Please double check whether newly added header files need ' |
| 110 | 'corresponding changes in gn or gni files.\nThis checking is only a ' |
| 111 | 'heuristic. Run build/check_gn_headers.py to be precise.\n' |
| 112 | 'Read https://crbug.com/661774 for more info.') |
| 113 | ] |
| 114 | return [] |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 115 | |
| 116 | |
Brian Sheedy | cc4d833 | 2019-09-11 17:26:00 -0700 | [diff] [blame] | 117 | def _CheckExportValidity(input_api, output_api): |
| 118 | outdir = tempfile.mkdtemp() |
| 119 | # shell=True is necessary on Windows, as otherwise subprocess fails to find |
| 120 | # either 'gn' or 'vpython3' even if they are findable via PATH. |
| 121 | use_shell = input_api.is_windows |
| 122 | try: |
| 123 | try: |
| 124 | subprocess.check_output(['gn', 'gen', outdir], shell=use_shell) |
| 125 | except subprocess.CalledProcessError as e: |
| 126 | return [ |
| 127 | output_api.PresubmitError( |
| 128 | 'Unable to run gn gen for export_targets.py: %s' % e.output) |
| 129 | ] |
| 130 | export_target_script = os.path.join(input_api.PresubmitLocalPath(), 'scripts', |
| 131 | 'export_targets.py') |
| 132 | try: |
| 133 | subprocess.check_output( |
| 134 | ['vpython3', export_target_script, outdir] + _PRIMARY_EXPORT_TARGETS, |
| 135 | stderr=subprocess.STDOUT, |
| 136 | shell=use_shell) |
| 137 | except subprocess.CalledProcessError as e: |
| 138 | if input_api.is_committing: |
| 139 | return [output_api.PresubmitError('export_targets.py failed: %s' % e.output)] |
| 140 | return [ |
| 141 | output_api.PresubmitPromptWarning( |
| 142 | 'export_targets.py failed, this may just be due to your local checkout: %s' % |
| 143 | e.output) |
| 144 | ] |
| 145 | return [] |
| 146 | finally: |
| 147 | shutil.rmtree(outdir) |
| 148 | |
| 149 | |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 150 | def CheckChangeOnUpload(input_api, output_api): |
| 151 | results = [] |
| 152 | results.extend(_CheckCodeGeneration(input_api, output_api)) |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 153 | results.extend(_CheckChangeHasBugField(input_api, output_api)) |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 154 | results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api)) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 155 | results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api)) |
Brian Sheedy | cc4d833 | 2019-09-11 17:26:00 -0700 | [diff] [blame] | 156 | results.extend(_CheckExportValidity(input_api, output_api)) |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 157 | results.extend( |
| 158 | input_api.canned_checks.CheckPatchFormatted( |
| 159 | input_api, output_api, result_factory=output_api.PresubmitError)) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 160 | return results |
| 161 | |
Shahbaz Youssefi | 98a3550 | 2019-01-08 22:09:39 -0500 | [diff] [blame] | 162 | |
| 163 | def CheckChangeOnCommit(input_api, output_api): |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 164 | results = [] |
Jamie Madill | 04e9e55 | 2019-04-01 14:40:21 -0400 | [diff] [blame] | 165 | results.extend(_CheckCodeGeneration(input_api, output_api)) |
Jamie Madill | 9e438ee | 2019-07-05 08:44:23 -0400 | [diff] [blame] | 166 | results.extend( |
| 167 | input_api.canned_checks.CheckPatchFormatted( |
| 168 | input_api, output_api, result_factory=output_api.PresubmitError)) |
| 169 | results.extend(_CheckChangeHasBugField(input_api, output_api)) |
Brian Sheedy | cc4d833 | 2019-09-11 17:26:00 -0700 | [diff] [blame] | 170 | results.extend(_CheckExportValidity(input_api, output_api)) |
Geoff Lang | d7d4239 | 2019-05-06 13:15:35 -0400 | [diff] [blame] | 171 | results.extend(input_api.canned_checks.CheckChangeHasDescription(input_api, output_api)) |
Jamie Madill | 73397e8 | 2019-01-09 10:33:16 -0500 | [diff] [blame] | 172 | return results |