skia2/PRESUBMIT.py

542 lines
20 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Top-level presubmit script for Skia.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""
import fnmatch
import os
import re
import subprocess
import sys
import traceback
RELEASE_NOTES_FILE_NAME = 'RELEASE_NOTES.txt'
GOLD_TRYBOT_URL = 'https://gold.skia.org/search?issue='
SERVICE_ACCOUNT_SUFFIX = [
'@%s.iam.gserviceaccount.com' % project for project in [
'skia-buildbots.google.com', 'skia-swarming-bots', 'skia-public',
'skia-corp.google.com', 'chops-service-accounts']]
2022-05-06 12:30:28 +00:00
USE_PYTHON3 = True
def _CheckChangeHasEol(input_api, output_api, source_file_filter=None):
"""Checks that files end with at least one \n (LF)."""
eof_files = []
for f in input_api.AffectedSourceFiles(source_file_filter):
contents = input_api.ReadFile(f, 'rb')
# Check that the file ends in at least one newline character.
if len(contents) > 1 and contents[-1:] != '\n':
eof_files.append(f.LocalPath())
if eof_files:
return [output_api.PresubmitPromptWarning(
'These files should end in a newline character:',
items=eof_files)]
return []
def _JsonChecks(input_api, output_api):
"""Run checks on any modified json files."""
failing_files = []
for affected_file in input_api.AffectedFiles(None):
affected_file_path = affected_file.LocalPath()
is_json = affected_file_path.endswith('.json')
is_metadata = (affected_file_path.startswith('site/') and
affected_file_path.endswith('/METADATA'))
if is_json or is_metadata:
try:
input_api.json.load(open(affected_file_path, 'r'))
except ValueError:
failing_files.append(affected_file_path)
results = []
if failing_files:
results.append(
output_api.PresubmitError(
'The following files contain invalid json:\n%s\n\n' %
'\n'.join(failing_files)))
return results
def _IfDefChecks(input_api, output_api):
"""Ensures if/ifdef are not before includes. See skbug/3362 for details."""
comment_block_start_pattern = re.compile('^\s*\/\*.*$')
comment_block_middle_pattern = re.compile('^\s+\*.*')
comment_block_end_pattern = re.compile('^\s+\*\/.*$')
single_line_comment_pattern = re.compile('^\s*//.*$')
def is_comment(line):
return (comment_block_start_pattern.match(line) or
comment_block_middle_pattern.match(line) or
comment_block_end_pattern.match(line) or
single_line_comment_pattern.match(line))
empty_line_pattern = re.compile('^\s*$')
def is_empty_line(line):
return empty_line_pattern.match(line)
failing_files = []
for affected_file in input_api.AffectedSourceFiles(None):
affected_file_path = affected_file.LocalPath()
if affected_file_path.endswith('.cpp') or affected_file_path.endswith('.h'):
f = open(affected_file_path)
for line in f:
if is_comment(line) or is_empty_line(line):
continue
# The below will be the first real line after comments and newlines.
if line.startswith('#if 0 '):
pass
elif line.startswith('#if ') or line.startswith('#ifdef '):
failing_files.append(affected_file_path)
break
results = []
if failing_files:
results.append(
output_api.PresubmitError(
'The following files have #if or #ifdef before includes:\n%s\n\n'
'See https://bug.skia.org/3362 for why this should be fixed.' %
'\n'.join(failing_files)))
return results
def _CopyrightChecks(input_api, output_api, source_file_filter=None):
results = []
year_pattern = r'\d{4}'
year_range_pattern = r'%s(-%s)?' % (year_pattern, year_pattern)
years_pattern = r'%s(,%s)*,?' % (year_range_pattern, year_range_pattern)
copyright_pattern = (
r'Copyright (\([cC]\) )?%s \w+' % years_pattern)
for affected_file in input_api.AffectedSourceFiles(source_file_filter):
if ('third_party/' in affected_file.LocalPath() or
[bazel] Add RBE support using hermetic Linux Clang toolchain A new RBE worker-pool called gce_linux was created in conjunction with this CL. See https://docs.google.com/document/d/14xMZCKews69SSTfULhE8HDUzT5XvPwZ4CvRufEvcZ74/edit# for some details on that. Note: everything under bazel/rbe/gce_linux was autogenerated and can be ignored from manual review. It basically specifies what files are on the RBE image that are necessary for running Bazel. Testing it out can be done by authenticating for RBE gcloud auth application-default login --no-browser Then, run make -C bazel rbe_known_good_builds to test it out. On my 4 core laptop with an empty local cache, but a warm remote cache, the build took <2 min instead of the 10+ minutes it would have [1]. The folder structure in //bazel/rbe is meant to let us have multiple remote configurations there, e.g. //bazel/rbe/gce_windows. Suggested Review Order: - bazel/rbe/README.md - bazel/rbe/gce_linux_container/Dockerfile to see the bare-bones RBE image. - bazel/rbe/BUILD.bazel to see a custom platform defined. It is nearly identical to the autogenerated one in bazel/rbe/gce_linux/config/BUILD, with one extra field to force the gce_linux pool to be used. - .bazelrc to see the settings needed to make --config=linux-rbe work. The naming convention was inspired by SkCMS's setup [2], and allows us to have some common RBE settings (i.e. config:remote) and some specialized ones for the given host machine (e.g. config:linux-rbe) A very important, but subtle configuration, is on line 86 of .bazelrc where we say to use our hermetic toolchain and not whatever C++ compiler and headers are on the host machine (aka the RBE container). - toolchain/build_toolchain.bzl to see some additional dependencies needed in the toolchain (to run IWYU) which I had installed locally but didn't realize were important. - third_party/BUILD.bazel to see an example of how failing to specify all files can result in something that works locally, but fails remotely. --execution_log_json_file=/tmp/execlog.json helped debug these issues. - All other files. [1] http://go/scrcast/NjM1ODE4MDI0NzM3MTc3Nnw3ODViZmFkMi1iOA [2] https://skia.googlesource.com/skcms/+/30c8e303800c256febb03a09fdcda7f75d119b1b/.bazelrc#20 Change-Id: Ia0a9e6a06c1a13071949ab402dc5d897df6b12e1 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/524359 Reviewed-by: Leandro Lovisolo <lovisolo@google.com>
2022-03-25 18:59:33 +00:00
'tests/sksl/' in affected_file.LocalPath() or
'bazel/rbe/' in affected_file.LocalPath()):
continue
contents = input_api.ReadFile(affected_file, 'rb')
if not re.search(copyright_pattern, contents):
results.append(output_api.PresubmitError(
'%s is missing a correct copyright header.' % affected_file))
return results
def _InfraTests(input_api, output_api):
"""Run the infra tests."""
results = []
if not any(f.LocalPath().startswith('infra')
for f in input_api.AffectedFiles()):
return results
cmd = ['python3', os.path.join('infra', 'bots', 'infra_tests.py')]
try:
subprocess.check_output(cmd)
except subprocess.CalledProcessError as e:
results.append(output_api.PresubmitError(
'`%s` failed:\n%s' % (' '.join(cmd), e.output)))
return results
def _CheckGNFormatted(input_api, output_api):
"""Make sure any .gn files we're changing have been formatted."""
files = []
for f in input_api.AffectedFiles(include_deletes=False):
if (f.LocalPath().endswith('.gn') or
f.LocalPath().endswith('.gni')):
files.append(f)
if not files:
return []
cmd = ['python3', os.path.join('bin', 'fetch-gn')]
try:
subprocess.check_output(cmd)
except subprocess.CalledProcessError as e:
return [output_api.PresubmitError(
'`%s` failed:\n%s' % (' '.join(cmd), e.output))]
results = []
for f in files:
gn = 'gn.exe' if 'win32' in sys.platform else 'gn'
gn = os.path.join(input_api.PresubmitLocalPath(), 'bin', gn)
cmd = [gn, 'format', '--dry-run', f.LocalPath()]
try:
subprocess.check_output(cmd)
except subprocess.CalledProcessError:
fix = 'bin/gn format ' + f.LocalPath()
results.append(output_api.PresubmitError(
'`%s` failed, try\n\t%s' % (' '.join(cmd), fix)))
return results
def _CheckGitConflictMarkers(input_api, output_api):
pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
results = []
for f in input_api.AffectedFiles():
for line_num, line in f.ChangedContents():
if f.LocalPath().endswith('.md'):
# First-level headers in markdown look a lot like version control
# conflict markers. http://daringfireball.net/projects/markdown/basics
continue
if pattern.match(line):
results.append(
output_api.PresubmitError(
'Git conflict markers found in %s:%d %s' % (
f.LocalPath(), line_num, line)))
return results
def _CheckIncludesFormatted(input_api, output_api):
"""Make sure #includes in files we're changing have been formatted."""
files = [str(f) for f in input_api.AffectedFiles() if f.Action() != 'D']
cmd = ['python3',
'tools/rewrite_includes.py',
'--dry-run'] + files
if 0 != subprocess.call(cmd):
return [output_api.PresubmitError('`%s` failed' % ' '.join(cmd))]
return []
class _WarningsAsErrors():
def __init__(self, output_api):
self.output_api = output_api
self.old_warning = None
def __enter__(self):
self.old_warning = self.output_api.PresubmitPromptWarning
self.output_api.PresubmitPromptWarning = self.output_api.PresubmitError
return self.output_api
def __exit__(self, ex_type, ex_value, ex_traceback):
self.output_api.PresubmitPromptWarning = self.old_warning
def _CheckDEPSValid(input_api, output_api):
"""Ensure that DEPS contains valid entries."""
results = []
script = os.path.join('infra', 'bots', 'check_deps.py')
relevant_files = ('DEPS', script)
for f in input_api.AffectedFiles():
if f.LocalPath() in relevant_files:
break
else:
return results
cmd = ['python3', script]
try:
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
results.append(output_api.PresubmitError(e.output))
return results
def _RegenerateAllExamplesCPP(input_api, output_api):
"""Regenerates all_examples.cpp if an example was added or deleted."""
if not any(f.LocalPath().startswith('docs/examples/')
for f in input_api.AffectedFiles()):
return []
command_str = 'tools/fiddle/make_all_examples_cpp.py'
cmd = ['python3', command_str]
if 0 != subprocess.call(cmd):
return [output_api.PresubmitError('`%s` failed' % ' '.join(cmd))]
results = []
git_diff_output = input_api.subprocess.check_output(
['git', 'diff', '--no-ext-diff'])
if git_diff_output:
results += [output_api.PresubmitError(
'Diffs found after running "%s":\n\n%s\n'
'Please commit or discard the above changes.' % (
command_str,
git_diff_output,
)
)]
return results
def _CheckBazelBUILDFiles(input_api, output_api):
"""Makes sure our BUILD.bazel files are compatible with G3."""
results = []
for affected_file in input_api.AffectedFiles(include_deletes=False):
affected_file_path = affected_file.LocalPath()
is_bazel = affected_file_path.endswith('BUILD.bazel')
[infra] Add BazelBuild task to build CanvasKit on the CI with Bazel For additional context, see "Codifying Certain Build Options" and "Building on the CI" in the design doc go/skia-bazel Suggested review order: - builder_name_schema.json to see the three required and one optional part of BazelBuild jobs. - jobs.json to see one new BazelBuild job added. In an ideal world, this job would have been named BazelBuild-//modules/canvaskit:canvaskit_wasm-debug-linux_x64 but Buildbucket (?) requires jobs match the regex ^[a-zA-Z0-9\\-_.\\(\\) ]{1,128}$ so we use spaces instead of slashes or colons. - gen_tasks_logic.go; noting the makeBazelLabel function expands most of the spaces to / and the last one to a colon to make a single-target label. If there are three dots, then it is a multi-target label, and we do not need to add a colon. - bazel_build.go; This is a very simple task driver, and I do not anticipate getting too much more complex. The place where we decide which args to augment a build with depend on the host platform and thus should be set in gen_tasks_logic.go. - bazel/buildrc to see some initial configurations set, one of which, "debug", is used by the new job. The "release" version of CanvasKit probably works on 3.1.10 which had a bugfix, but we are still on 3.1.9 - .bazelrc to see a rename of the linux-rbe config to linux_rbe (our configs should have no dashes if we want to specify them verbatim in our Job names). It also imports the Skia-specified build configs from //bazel/buildrc and supports the user-specified //bazel/user/buildrc file if it exists. - All other files in any order. Change-Id: Ib954dd6045100eadcbbf4ffee0888f6fbce65fa7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/537797 Reviewed-by: Eric Boren <borenet@google.com> Reviewed-by: Jorge Betancourt <jmbetancourt@google.com>
2022-05-06 17:20:12 +00:00
# This list lines up with the one in autoroller_lib.py (see G3).
excluded_paths = ["infra/", "bazel/rbe/", "bazel/external/", "bazel/common_config_settings/",
[bazel] Add "skia_internal" target that exposes private API for tests/tools. Organization v3.5, if we are keeping track :) This splits the "srcs" filegroup into "srcs" and "private_hdrs", and renames "hdrs" to "public_hdrs". To assist with the split, I created the macro split_srcs_and_hdrs. Rather than keep two separate lists of header and source files, I figured it would be easiest, at least for the common case, to keep one list of files and then have a for loop split them apart. I've tried to be consistent with having the list of files be named with a _FILES suffix - maybe we can use this as a marker to generate .gni files in the future? Suggested review order: - //bazel/macros.bzl. Note this needs a corresponding G3 change (http://cl/452279799) as well. The exports_files_legacy change is the better approach to something I manually handled yesterday when fixing the G3 roll. - //BUILD.bazel to see the new target skia_internal and the previous skia_core renamed to skia_public. - //src/core/BUILD.bazel to see a typical usage of split_srcs_and_hdrs. - //include/... to see the change to public_hdrs and private_hdrs - //src/... to see many more usages of split_srcs_and_hdrs - //tools/... to see changes to skia_internal where appropriate. - Everything else. Note that //modules/... might also need to be built with skia_internal instead of skia_public, but we can fix that up later, if necessary. Change-Id: Ie1cc969455d97b029b2d77faa222c4a9bad70671 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/545716 Reviewed-by: Ben Wagner <bungeman@google.com> Reviewed-by: Leandro Lovisolo <lovisolo@google.com>
2022-06-01 18:45:46 +00:00
"modules/canvaskit/go/", "experimental/"]
[infra] Add BazelBuild task to build CanvasKit on the CI with Bazel For additional context, see "Codifying Certain Build Options" and "Building on the CI" in the design doc go/skia-bazel Suggested review order: - builder_name_schema.json to see the three required and one optional part of BazelBuild jobs. - jobs.json to see one new BazelBuild job added. In an ideal world, this job would have been named BazelBuild-//modules/canvaskit:canvaskit_wasm-debug-linux_x64 but Buildbucket (?) requires jobs match the regex ^[a-zA-Z0-9\\-_.\\(\\) ]{1,128}$ so we use spaces instead of slashes or colons. - gen_tasks_logic.go; noting the makeBazelLabel function expands most of the spaces to / and the last one to a colon to make a single-target label. If there are three dots, then it is a multi-target label, and we do not need to add a colon. - bazel_build.go; This is a very simple task driver, and I do not anticipate getting too much more complex. The place where we decide which args to augment a build with depend on the host platform and thus should be set in gen_tasks_logic.go. - bazel/buildrc to see some initial configurations set, one of which, "debug", is used by the new job. The "release" version of CanvasKit probably works on 3.1.10 which had a bugfix, but we are still on 3.1.9 - .bazelrc to see a rename of the linux-rbe config to linux_rbe (our configs should have no dashes if we want to specify them verbatim in our Job names). It also imports the Skia-specified build configs from //bazel/buildrc and supports the user-specified //bazel/user/buildrc file if it exists. - All other files in any order. Change-Id: Ib954dd6045100eadcbbf4ffee0888f6fbce65fa7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/537797 Reviewed-by: Eric Boren <borenet@google.com> Reviewed-by: Jorge Betancourt <jmbetancourt@google.com>
2022-05-06 17:20:12 +00:00
is_excluded = any(affected_file_path.startswith(n) for n in excluded_paths)
if is_bazel and not is_excluded:
with open(affected_file_path, 'r') as file:
contents = file.read()
[bazel] Add "skia_internal" target that exposes private API for tests/tools. Organization v3.5, if we are keeping track :) This splits the "srcs" filegroup into "srcs" and "private_hdrs", and renames "hdrs" to "public_hdrs". To assist with the split, I created the macro split_srcs_and_hdrs. Rather than keep two separate lists of header and source files, I figured it would be easiest, at least for the common case, to keep one list of files and then have a for loop split them apart. I've tried to be consistent with having the list of files be named with a _FILES suffix - maybe we can use this as a marker to generate .gni files in the future? Suggested review order: - //bazel/macros.bzl. Note this needs a corresponding G3 change (http://cl/452279799) as well. The exports_files_legacy change is the better approach to something I manually handled yesterday when fixing the G3 roll. - //BUILD.bazel to see the new target skia_internal and the previous skia_core renamed to skia_public. - //src/core/BUILD.bazel to see a typical usage of split_srcs_and_hdrs. - //include/... to see the change to public_hdrs and private_hdrs - //src/... to see many more usages of split_srcs_and_hdrs - //tools/... to see changes to skia_internal where appropriate. - Everything else. Note that //modules/... might also need to be built with skia_internal instead of skia_public, but we can fix that up later, if necessary. Change-Id: Ie1cc969455d97b029b2d77faa222c4a9bad70671 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/545716 Reviewed-by: Ben Wagner <bungeman@google.com> Reviewed-by: Leandro Lovisolo <lovisolo@google.com>
2022-06-01 18:45:46 +00:00
if 'exports_files_legacy(' not in contents:
results.append(output_api.PresubmitError(
('%s needs to call exports_files_legacy() to support legacy G3 ' +
'rules.\nPut this near the top of the file, beneath ' +
'licenses(["notice"]).') % affected_file_path
))
if 'licenses(["notice"])' not in contents:
results.append(output_api.PresubmitError(
('%s needs to have\nlicenses(["notice"])\nimmediately after ' +
'the load() calls to comply with G3 policies.') % affected_file_path
))
if 'cc_library(' in contents and '"cc_library"' not in contents:
results.append(output_api.PresubmitError(
('%s needs load cc_library from macros.bzl instead of using the ' +
'native one. This allows us to build differently for G3.\n' +
'Add "cc_library" to load("//bazel:macros.bzl", ...)')
% affected_file_path
))
return results
def _CheckPublicBzl(input_api, output_api):
"""Reminds devs to add/remove files from public.bzl."""
results = []
public_bzl = ''
with open('public.bzl', 'r', encoding='utf-8') as f:
public_bzl = f.read().strip()
for affected_file in input_api.AffectedFiles(include_deletes=True):
# action is A for newly added, D for newly deleted, M for modified
action = affected_file.Action()
affected_file_path = affected_file.LocalPath()
if ((affected_file_path.startswith("include") or affected_file_path.startswith("src")) and
(affected_file_path.endswith(".cpp") or affected_file_path.endswith(".h"))):
affected_file_path = '"' + affected_file_path + '"'
if action == "D" and affected_file_path in public_bzl:
results.append(output_api.PresubmitError(
"Need to delete %s from public.bzl (or rename it)" % affected_file_path))
elif action == "A" and affected_file_path not in public_bzl:
results.append(output_api.PresubmitPromptWarning(
"You may need to add %s to public.bzl" % affected_file_path))
return results
[bazel] Add in hierarchical filegroup Bazel rules. The primary goal of this organization structure is to keep our top level BUILD.bazel file short, with as little logic as feasible. The logic required to control which files to include, which third_party deps are needed, what system libraries should be linked again, etc, should be in the BUILD.bazel file best should be as close to the affected files as feasible. In essence, we use filegroup() rules to bubble up the files needed to build Skia (all as one big cc_library call) and cc_library rules to bubble up the other components needed to build. For example, //src/ports/SkFontHost_FreeType.cpp needs FreeType, but only if we are compiling Skia with that type of font support. With the new organization structure in this CL, //src/ports/BUILD.bazel should have the logic that determines if the cpp file should be included in the build of Skia and if it is, that the Skia build should depend on //third_party:freetype2 Another example is //src/gpu/ganesh/BUILD.bazel, which chooses which of the dawn, gl, vulkan, etc backend sources, and the associated dependencies to include in the build. It does not specify what those are, but delegates to the BUILD.bazel files in the subdirectories housing the backend-specific code. The structure guidelines for BUILD.bazel files are as follows: - Have a filegroup() called "hdrs" (for public headers) or "srcs" (for private headers and all .cpp files) that is visible to the parent directory. This should list the files from the containing directory to include in the build. See //include/core/BUILD.bazel and //src/effects/BUILD.bazel as examples. - filegroup() rules can list a child directory's "hdrs" or "srcs" in their "srcs" attributes, but should not contain select statements pertaining to child directory files. See //include/gpu/BUILD.bazel and //src/gpu/ganesh/BUILD.bazel as examples. - May have a cc_library() called "deps". This can specify dependencies, cc_opts, and linkopts, but not srcs or hdrs. [1] See //src/codec/BUILD.bazel as an example. These should be visible to the parent directory. - "hdrs", "srcs", and "deps" for the primary Skia build (currently called "skia_core") should bubble up through //include/BUILD.bazel and //src/BUILD.bazel, one directory at a time. This CL demonstrates a very basic build of Skia with many features turned off (CPU only, no fonts, no codecs). Follow-on CLs will add to these rules as more targets are supported. See bazel/Makefile for the builds that work with just this CL. Suggested Review Order: - //BUILD.bazel to see the very small skia_core rule which delegates all the logic down stack. Note that it has a dependency on //bazel:defines_from_flags which will set all the defines listed there when compiling all the .cpp and .h files in skia_core *and* anything that depends on skia_core, but *not* //src:deps. - //include/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. Note that the filegroups in //include/private/... are called "srcs" to be similar to how Bazel wants "private headers" to be in the "srcs" of cc_library, cc_binary, etc. and only public headers are to be in "hdrs" [2]. - //src/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. //src/gpu/ganesh/... will be filled in for dawn, vulkan, and GL in the next CL. - //PRESUBMIT.py, which adds a check that runs buildifier [3] on modified BUILD.bazel files to make sure they stay consistently formatted. - //bazel/... to see the new option I added to make sksl opt-in or opt-out, so one could build Skia with sksl, but not with a gpu backend. - Misc .h and .cpp files, whose includes were removed if unnecessary or #ifdef'd out to make the minimal build work without GPU or SkSL includes. - //bazel/Makefile to see the builds that work with this CL. [1] Setting srcs or hdrs is error-prone at best, because those files will be compiled with a different set of defines than the rest of skia_core, because they wouldn't depend on //bazel:defines_from_flags. [2] https://bazel.build/reference/be/c-cpp#cc_library.hdrs [3] https://github.com/bazelbuild/buildtools/releases Change-Id: I5e0e3ae01ad42d672506d5aad1239f2512188191 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/543977 Reviewed-by: Leandro Lovisolo <lovisolo@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
2022-05-27 17:56:03 +00:00
def _RunCommandAndCheckGitDiff(output_api, command):
"""Run an arbitrary command. Fail if it produces any diffs."""
command_str = ' '.join(command)
results = []
try:
output = subprocess.check_output(
command,
stderr=subprocess.STDOUT, encoding='utf-8')
except subprocess.CalledProcessError as e:
results += [output_api.PresubmitError(
'Command "%s" returned non-zero exit code %d. Output: \n\n%s' % (
command_str,
e.returncode,
e.output,
)
)]
git_diff_output = subprocess.check_output(
['git', 'diff', '--no-ext-diff'], encoding='utf-8')
if git_diff_output:
results += [output_api.PresubmitError(
'Diffs found after running "%s":\n\n%s\n'
'Please commit or discard the above changes.' % (
command_str,
git_diff_output,
)
)]
return results
def _CheckBuildifier(input_api, output_api):
"""Runs Buildifier and fails on linting errors, or if it produces any diffs.
This check only runs if the affected files include any WORKSPACE, BUILD,
BUILD.bazel or *.bzl files.
"""
files = []
for affected_file in input_api.AffectedFiles(include_deletes=False):
affected_file_path = affected_file.LocalPath()
if affected_file_path.endswith('BUILD.bazel') or affected_file_path.endswith('.bzl'):
if not affected_file_path.endswith('public.bzl'):
files.append(affected_file_path)
[bazel] Add in hierarchical filegroup Bazel rules. The primary goal of this organization structure is to keep our top level BUILD.bazel file short, with as little logic as feasible. The logic required to control which files to include, which third_party deps are needed, what system libraries should be linked again, etc, should be in the BUILD.bazel file best should be as close to the affected files as feasible. In essence, we use filegroup() rules to bubble up the files needed to build Skia (all as one big cc_library call) and cc_library rules to bubble up the other components needed to build. For example, //src/ports/SkFontHost_FreeType.cpp needs FreeType, but only if we are compiling Skia with that type of font support. With the new organization structure in this CL, //src/ports/BUILD.bazel should have the logic that determines if the cpp file should be included in the build of Skia and if it is, that the Skia build should depend on //third_party:freetype2 Another example is //src/gpu/ganesh/BUILD.bazel, which chooses which of the dawn, gl, vulkan, etc backend sources, and the associated dependencies to include in the build. It does not specify what those are, but delegates to the BUILD.bazel files in the subdirectories housing the backend-specific code. The structure guidelines for BUILD.bazel files are as follows: - Have a filegroup() called "hdrs" (for public headers) or "srcs" (for private headers and all .cpp files) that is visible to the parent directory. This should list the files from the containing directory to include in the build. See //include/core/BUILD.bazel and //src/effects/BUILD.bazel as examples. - filegroup() rules can list a child directory's "hdrs" or "srcs" in their "srcs" attributes, but should not contain select statements pertaining to child directory files. See //include/gpu/BUILD.bazel and //src/gpu/ganesh/BUILD.bazel as examples. - May have a cc_library() called "deps". This can specify dependencies, cc_opts, and linkopts, but not srcs or hdrs. [1] See //src/codec/BUILD.bazel as an example. These should be visible to the parent directory. - "hdrs", "srcs", and "deps" for the primary Skia build (currently called "skia_core") should bubble up through //include/BUILD.bazel and //src/BUILD.bazel, one directory at a time. This CL demonstrates a very basic build of Skia with many features turned off (CPU only, no fonts, no codecs). Follow-on CLs will add to these rules as more targets are supported. See bazel/Makefile for the builds that work with just this CL. Suggested Review Order: - //BUILD.bazel to see the very small skia_core rule which delegates all the logic down stack. Note that it has a dependency on //bazel:defines_from_flags which will set all the defines listed there when compiling all the .cpp and .h files in skia_core *and* anything that depends on skia_core, but *not* //src:deps. - //include/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. Note that the filegroups in //include/private/... are called "srcs" to be similar to how Bazel wants "private headers" to be in the "srcs" of cc_library, cc_binary, etc. and only public headers are to be in "hdrs" [2]. - //src/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. //src/gpu/ganesh/... will be filled in for dawn, vulkan, and GL in the next CL. - //PRESUBMIT.py, which adds a check that runs buildifier [3] on modified BUILD.bazel files to make sure they stay consistently formatted. - //bazel/... to see the new option I added to make sksl opt-in or opt-out, so one could build Skia with sksl, but not with a gpu backend. - Misc .h and .cpp files, whose includes were removed if unnecessary or #ifdef'd out to make the minimal build work without GPU or SkSL includes. - //bazel/Makefile to see the builds that work with this CL. [1] Setting srcs or hdrs is error-prone at best, because those files will be compiled with a different set of defines than the rest of skia_core, because they wouldn't depend on //bazel:defines_from_flags. [2] https://bazel.build/reference/be/c-cpp#cc_library.hdrs [3] https://github.com/bazelbuild/buildtools/releases Change-Id: I5e0e3ae01ad42d672506d5aad1239f2512188191 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/543977 Reviewed-by: Leandro Lovisolo <lovisolo@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
2022-05-27 17:56:03 +00:00
if not files:
return []
try:
subprocess.check_output(
['buildifier', '--version'],
stderr=subprocess.STDOUT)
except:
return [output_api.PresubmitNotifyResult(
[bazel] Add in hierarchical filegroup Bazel rules. The primary goal of this organization structure is to keep our top level BUILD.bazel file short, with as little logic as feasible. The logic required to control which files to include, which third_party deps are needed, what system libraries should be linked again, etc, should be in the BUILD.bazel file best should be as close to the affected files as feasible. In essence, we use filegroup() rules to bubble up the files needed to build Skia (all as one big cc_library call) and cc_library rules to bubble up the other components needed to build. For example, //src/ports/SkFontHost_FreeType.cpp needs FreeType, but only if we are compiling Skia with that type of font support. With the new organization structure in this CL, //src/ports/BUILD.bazel should have the logic that determines if the cpp file should be included in the build of Skia and if it is, that the Skia build should depend on //third_party:freetype2 Another example is //src/gpu/ganesh/BUILD.bazel, which chooses which of the dawn, gl, vulkan, etc backend sources, and the associated dependencies to include in the build. It does not specify what those are, but delegates to the BUILD.bazel files in the subdirectories housing the backend-specific code. The structure guidelines for BUILD.bazel files are as follows: - Have a filegroup() called "hdrs" (for public headers) or "srcs" (for private headers and all .cpp files) that is visible to the parent directory. This should list the files from the containing directory to include in the build. See //include/core/BUILD.bazel and //src/effects/BUILD.bazel as examples. - filegroup() rules can list a child directory's "hdrs" or "srcs" in their "srcs" attributes, but should not contain select statements pertaining to child directory files. See //include/gpu/BUILD.bazel and //src/gpu/ganesh/BUILD.bazel as examples. - May have a cc_library() called "deps". This can specify dependencies, cc_opts, and linkopts, but not srcs or hdrs. [1] See //src/codec/BUILD.bazel as an example. These should be visible to the parent directory. - "hdrs", "srcs", and "deps" for the primary Skia build (currently called "skia_core") should bubble up through //include/BUILD.bazel and //src/BUILD.bazel, one directory at a time. This CL demonstrates a very basic build of Skia with many features turned off (CPU only, no fonts, no codecs). Follow-on CLs will add to these rules as more targets are supported. See bazel/Makefile for the builds that work with just this CL. Suggested Review Order: - //BUILD.bazel to see the very small skia_core rule which delegates all the logic down stack. Note that it has a dependency on //bazel:defines_from_flags which will set all the defines listed there when compiling all the .cpp and .h files in skia_core *and* anything that depends on skia_core, but *not* //src:deps. - //include/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. Note that the filegroups in //include/private/... are called "srcs" to be similar to how Bazel wants "private headers" to be in the "srcs" of cc_library, cc_binary, etc. and only public headers are to be in "hdrs" [2]. - //src/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. //src/gpu/ganesh/... will be filled in for dawn, vulkan, and GL in the next CL. - //PRESUBMIT.py, which adds a check that runs buildifier [3] on modified BUILD.bazel files to make sure they stay consistently formatted. - //bazel/... to see the new option I added to make sksl opt-in or opt-out, so one could build Skia with sksl, but not with a gpu backend. - Misc .h and .cpp files, whose includes were removed if unnecessary or #ifdef'd out to make the minimal build work without GPU or SkSL includes. - //bazel/Makefile to see the builds that work with this CL. [1] Setting srcs or hdrs is error-prone at best, because those files will be compiled with a different set of defines than the rest of skia_core, because they wouldn't depend on //bazel:defines_from_flags. [2] https://bazel.build/reference/be/c-cpp#cc_library.hdrs [3] https://github.com/bazelbuild/buildtools/releases Change-Id: I5e0e3ae01ad42d672506d5aad1239f2512188191 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/543977 Reviewed-by: Leandro Lovisolo <lovisolo@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
2022-05-27 17:56:03 +00:00
'Skipping buildifier check because it is not on PATH. \n' +
'You can download it from https://github.com/bazelbuild/buildtools/releases')]
[bazel] Add in hierarchical filegroup Bazel rules. The primary goal of this organization structure is to keep our top level BUILD.bazel file short, with as little logic as feasible. The logic required to control which files to include, which third_party deps are needed, what system libraries should be linked again, etc, should be in the BUILD.bazel file best should be as close to the affected files as feasible. In essence, we use filegroup() rules to bubble up the files needed to build Skia (all as one big cc_library call) and cc_library rules to bubble up the other components needed to build. For example, //src/ports/SkFontHost_FreeType.cpp needs FreeType, but only if we are compiling Skia with that type of font support. With the new organization structure in this CL, //src/ports/BUILD.bazel should have the logic that determines if the cpp file should be included in the build of Skia and if it is, that the Skia build should depend on //third_party:freetype2 Another example is //src/gpu/ganesh/BUILD.bazel, which chooses which of the dawn, gl, vulkan, etc backend sources, and the associated dependencies to include in the build. It does not specify what those are, but delegates to the BUILD.bazel files in the subdirectories housing the backend-specific code. The structure guidelines for BUILD.bazel files are as follows: - Have a filegroup() called "hdrs" (for public headers) or "srcs" (for private headers and all .cpp files) that is visible to the parent directory. This should list the files from the containing directory to include in the build. See //include/core/BUILD.bazel and //src/effects/BUILD.bazel as examples. - filegroup() rules can list a child directory's "hdrs" or "srcs" in their "srcs" attributes, but should not contain select statements pertaining to child directory files. See //include/gpu/BUILD.bazel and //src/gpu/ganesh/BUILD.bazel as examples. - May have a cc_library() called "deps". This can specify dependencies, cc_opts, and linkopts, but not srcs or hdrs. [1] See //src/codec/BUILD.bazel as an example. These should be visible to the parent directory. - "hdrs", "srcs", and "deps" for the primary Skia build (currently called "skia_core") should bubble up through //include/BUILD.bazel and //src/BUILD.bazel, one directory at a time. This CL demonstrates a very basic build of Skia with many features turned off (CPU only, no fonts, no codecs). Follow-on CLs will add to these rules as more targets are supported. See bazel/Makefile for the builds that work with just this CL. Suggested Review Order: - //BUILD.bazel to see the very small skia_core rule which delegates all the logic down stack. Note that it has a dependency on //bazel:defines_from_flags which will set all the defines listed there when compiling all the .cpp and .h files in skia_core *and* anything that depends on skia_core, but *not* //src:deps. - //include/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. Note that the filegroups in //include/private/... are called "srcs" to be similar to how Bazel wants "private headers" to be in the "srcs" of cc_library, cc_binary, etc. and only public headers are to be in "hdrs" [2]. - //src/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. //src/gpu/ganesh/... will be filled in for dawn, vulkan, and GL in the next CL. - //PRESUBMIT.py, which adds a check that runs buildifier [3] on modified BUILD.bazel files to make sure they stay consistently formatted. - //bazel/... to see the new option I added to make sksl opt-in or opt-out, so one could build Skia with sksl, but not with a gpu backend. - Misc .h and .cpp files, whose includes were removed if unnecessary or #ifdef'd out to make the minimal build work without GPU or SkSL includes. - //bazel/Makefile to see the builds that work with this CL. [1] Setting srcs or hdrs is error-prone at best, because those files will be compiled with a different set of defines than the rest of skia_core, because they wouldn't depend on //bazel:defines_from_flags. [2] https://bazel.build/reference/be/c-cpp#cc_library.hdrs [3] https://github.com/bazelbuild/buildtools/releases Change-Id: I5e0e3ae01ad42d672506d5aad1239f2512188191 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/543977 Reviewed-by: Leandro Lovisolo <lovisolo@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
2022-05-27 17:56:03 +00:00
return _RunCommandAndCheckGitDiff(
# One can change --lint=warn to --lint=fix to have things automatically fixed where possible.
# However, --lint=fix will not cause a presubmit error if there are things that require
# manual intervention, so we leave --lint=warn on by default.
output_api, ['buildifier', '--mode=fix', '--lint=warn'] + files)
def _CommonChecks(input_api, output_api):
"""Presubmit checks common to upload and commit."""
results = []
sources = lambda x: (x.LocalPath().endswith('.h') or
x.LocalPath().endswith('.py') or
x.LocalPath().endswith('.sh') or
x.LocalPath().endswith('.m') or
x.LocalPath().endswith('.mm') or
x.LocalPath().endswith('.go') or
x.LocalPath().endswith('.c') or
x.LocalPath().endswith('.cc') or
x.LocalPath().endswith('.cpp'))
results.extend(_CheckChangeHasEol(
input_api, output_api, source_file_filter=sources))
with _WarningsAsErrors(output_api):
results.extend(input_api.canned_checks.CheckChangeHasNoCR(
input_api, output_api, source_file_filter=sources))
results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
input_api, output_api, source_file_filter=sources))
results.extend(_JsonChecks(input_api, output_api))
results.extend(_IfDefChecks(input_api, output_api))
results.extend(_CopyrightChecks(input_api, output_api,
source_file_filter=sources))
results.extend(_CheckDEPSValid(input_api, output_api))
results.extend(_CheckIncludesFormatted(input_api, output_api))
results.extend(_CheckGNFormatted(input_api, output_api))
results.extend(_CheckGitConflictMarkers(input_api, output_api))
results.extend(_RegenerateAllExamplesCPP(input_api, output_api))
results.extend(_CheckBazelBUILDFiles(input_api, output_api))
return results
def CheckChangeOnUpload(input_api, output_api):
"""Presubmit checks for the change on upload."""
results = []
results.extend(_CommonChecks(input_api, output_api))
# Run on upload, not commit, since the presubmit bot apparently doesn't have
# coverage or Go installed.
results.extend(_InfraTests(input_api, output_api))
results.extend(_CheckReleaseNotesForPublicAPI(input_api, output_api))
# Only check public.bzl on upload because new files are likely to be a source
# of false positives and we don't want to unnecessarily block commits.
results.extend(_CheckPublicBzl(input_api, output_api))
[bazel] Add in hierarchical filegroup Bazel rules. The primary goal of this organization structure is to keep our top level BUILD.bazel file short, with as little logic as feasible. The logic required to control which files to include, which third_party deps are needed, what system libraries should be linked again, etc, should be in the BUILD.bazel file best should be as close to the affected files as feasible. In essence, we use filegroup() rules to bubble up the files needed to build Skia (all as one big cc_library call) and cc_library rules to bubble up the other components needed to build. For example, //src/ports/SkFontHost_FreeType.cpp needs FreeType, but only if we are compiling Skia with that type of font support. With the new organization structure in this CL, //src/ports/BUILD.bazel should have the logic that determines if the cpp file should be included in the build of Skia and if it is, that the Skia build should depend on //third_party:freetype2 Another example is //src/gpu/ganesh/BUILD.bazel, which chooses which of the dawn, gl, vulkan, etc backend sources, and the associated dependencies to include in the build. It does not specify what those are, but delegates to the BUILD.bazel files in the subdirectories housing the backend-specific code. The structure guidelines for BUILD.bazel files are as follows: - Have a filegroup() called "hdrs" (for public headers) or "srcs" (for private headers and all .cpp files) that is visible to the parent directory. This should list the files from the containing directory to include in the build. See //include/core/BUILD.bazel and //src/effects/BUILD.bazel as examples. - filegroup() rules can list a child directory's "hdrs" or "srcs" in their "srcs" attributes, but should not contain select statements pertaining to child directory files. See //include/gpu/BUILD.bazel and //src/gpu/ganesh/BUILD.bazel as examples. - May have a cc_library() called "deps". This can specify dependencies, cc_opts, and linkopts, but not srcs or hdrs. [1] See //src/codec/BUILD.bazel as an example. These should be visible to the parent directory. - "hdrs", "srcs", and "deps" for the primary Skia build (currently called "skia_core") should bubble up through //include/BUILD.bazel and //src/BUILD.bazel, one directory at a time. This CL demonstrates a very basic build of Skia with many features turned off (CPU only, no fonts, no codecs). Follow-on CLs will add to these rules as more targets are supported. See bazel/Makefile for the builds that work with just this CL. Suggested Review Order: - //BUILD.bazel to see the very small skia_core rule which delegates all the logic down stack. Note that it has a dependency on //bazel:defines_from_flags which will set all the defines listed there when compiling all the .cpp and .h files in skia_core *and* anything that depends on skia_core, but *not* //src:deps. - //include/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. Note that the filegroups in //include/private/... are called "srcs" to be similar to how Bazel wants "private headers" to be in the "srcs" of cc_library, cc_binary, etc. and only public headers are to be in "hdrs" [2]. - //src/BUILD.bazel and other BUILD.bazel files in the subdirectories of that folder. //src/gpu/ganesh/... will be filled in for dawn, vulkan, and GL in the next CL. - //PRESUBMIT.py, which adds a check that runs buildifier [3] on modified BUILD.bazel files to make sure they stay consistently formatted. - //bazel/... to see the new option I added to make sksl opt-in or opt-out, so one could build Skia with sksl, but not with a gpu backend. - Misc .h and .cpp files, whose includes were removed if unnecessary or #ifdef'd out to make the minimal build work without GPU or SkSL includes. - //bazel/Makefile to see the builds that work with this CL. [1] Setting srcs or hdrs is error-prone at best, because those files will be compiled with a different set of defines than the rest of skia_core, because they wouldn't depend on //bazel:defines_from_flags. [2] https://bazel.build/reference/be/c-cpp#cc_library.hdrs [3] https://github.com/bazelbuild/buildtools/releases Change-Id: I5e0e3ae01ad42d672506d5aad1239f2512188191 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/543977 Reviewed-by: Leandro Lovisolo <lovisolo@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
2022-05-27 17:56:03 +00:00
# Buildifier might not be on the CI machines.
results.extend(_CheckBuildifier(input_api, output_api))
return results
class CodeReview(object):
"""Abstracts which codereview tool is used for the specified issue."""
def __init__(self, input_api):
self._issue = input_api.change.issue
self._gerrit = input_api.gerrit
def GetOwnerEmail(self):
return self._gerrit.GetChangeOwner(self._issue)
def GetSubject(self):
return self._gerrit.GetChangeInfo(self._issue)['subject']
def GetDescription(self):
return self._gerrit.GetChangeDescription(self._issue)
def GetReviewers(self):
code_review_label = (
self._gerrit.GetChangeInfo(self._issue)['labels']['Code-Review'])
return [r['email'] for r in code_review_label.get('all', [])]
def GetApprovers(self):
approvers = []
code_review_label = (
self._gerrit.GetChangeInfo(self._issue)['labels']['Code-Review'])
for m in code_review_label.get('all', []):
if m.get("value") == 1:
approvers.append(m["email"])
return approvers
def _CheckReleaseNotesForPublicAPI(input_api, output_api):
"""Checks to see if release notes file is updated with public API changes."""
results = []
public_api_changed = False
release_file_changed = False
for affected_file in input_api.AffectedFiles():
affected_file_path = affected_file.LocalPath()
file_path, file_ext = os.path.splitext(affected_file_path)
# We only care about files that end in .h and are under the top-level
# include dir, but not include/private.
if (file_ext == '.h' and
file_path.split(os.path.sep)[0] == 'include' and
'private' not in file_path):
public_api_changed = True
elif affected_file_path == RELEASE_NOTES_FILE_NAME:
release_file_changed = True
if public_api_changed and not release_file_changed:
results.append(output_api.PresubmitPromptWarning(
'If this change affects a client API, please add a summary line '
'to the %s file.' % RELEASE_NOTES_FILE_NAME))
return results
def PostUploadHook(gerrit, change, output_api):
"""git cl upload will call this hook after the issue is created/modified.
This hook does the following:
* Adds a link to preview docs changes if there are any docs changes in the CL.
* Adds 'No-Try: true' if the CL contains only docs changes.
"""
if not change.issue:
return []
# Skip PostUploadHooks for all auto-commit service account bots. New
# patchsets (caused due to PostUploadHooks) invalidates the CQ+2 vote from
# the "--use-commit-queue" flag to "git cl upload".
for suffix in SERVICE_ACCOUNT_SUFFIX:
if change.author_email.endswith(suffix):
return []
results = []
at_least_one_docs_change = False
all_docs_changes = True
for affected_file in change.AffectedFiles():
affected_file_path = affected_file.LocalPath()
file_path, _ = os.path.splitext(affected_file_path)
if 'site' == file_path.split(os.path.sep)[0]:
at_least_one_docs_change = True
else:
all_docs_changes = False
if at_least_one_docs_change and not all_docs_changes:
break
footers = change.GitFootersFromDescription()
description_changed = False
# If the change includes only doc changes then add No-Try: true in the
# CL's description if it does not exist yet.
if all_docs_changes and 'true' not in footers.get('No-Try', []):
description_changed = True
change.AddDescriptionFooter('No-Try', 'true')
results.append(
output_api.PresubmitNotifyResult(
'This change has only doc changes. Automatically added '
'\'No-Try: true\' to the CL\'s description'))
# If the description has changed update it.
if description_changed:
gerrit.UpdateDescription(
change.FullDescriptionText(), change.issue)
return results
def CheckChangeOnCommit(input_api, output_api):
"""Presubmit checks for the change on commit."""
results = []
results.extend(_CommonChecks(input_api, output_api))
# Checks for the presence of 'DO NOT''SUBMIT' in CL description and in
# content of files.
results.extend(
input_api.canned_checks.CheckDoNotSubmit(input_api, output_api))
return results