forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcpplint.bzl
110 lines (96 loc) · 3.28 KB
/
cpplint.bzl
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
# -*- python -*-
# From https://bazel.build/versions/master/docs/be/c-cpp.html#cc_library.srcs
_SOURCE_EXTENSIONS = [source_ext for source_ext in """
.c
.cc
.cpp
.cxx
.c++.C
.h
.hh
.hpp
.hxx
.inc
""".split("\n") if len(source_ext)]
# Do not lint generated protocol buffer files.
_IGNORE_EXTENSIONS = [
".pb.h",
".pb.cc",
]
# The cpplint.py command-line argument so it doesn't skip our files!
_EXTENSIONS_ARGS = ["--extensions=" + ",".join(
[ext[1:] for ext in _SOURCE_EXTENSIONS],
)]
def _extract_labels(srcs):
"""Convert a srcs= or hdrs= value to its set of labels."""
# Tuples are already labels.
if type(srcs) == type(()):
return list(srcs)
# The select() syntax returns an object we (apparently) can't inspect.
# TODO(jwnimmer-tri) Figure out how to cpplint these files. For now,
# folks will have to pass extra_srcs when calling cpplint() macro.
return []
def _is_source_label(label):
for extension in _IGNORE_EXTENSIONS:
if label.endswith(extension):
return False
for extension in _SOURCE_EXTENSIONS:
if label.endswith(extension):
return True
return False
def _add_linter_rules(source_labels, source_filenames, name, data=None):
# Common attributes for all of our py_test invocations.
data = (data or [])
size = "small"
tags = ["cpplint"]
# Google cpplint.
cpplint_cfg = ["//:CPPLINT.cfg"] + native.glob(['CPPLINT.cfg'])
native.py_test(
name = name + "_cpplint",
srcs = ["@google_styleguide//:cpplint"],
data = data + cpplint_cfg + source_labels,
args = _EXTENSIONS_ARGS + source_filenames,
main = "@google_styleguide//:cpplint/cpplint.py",
size = size,
tags = tags,
)
# Additional Drake lint.
native.py_test(
name = name + "_drake_lint",
srcs = ["//tools:drakelint"],
data = data + source_labels,
args = source_filenames,
main = "//tools:drakelint.py",
size = size,
tags = tags,
)
def cpplint(data=None, extra_srcs=None):
"""For every rule in the BUILD file so far, adds a test rule that runs
cpplint over the C++ sources listed in that rule. Thus, BUILD file authors
should call this function at the *end* of every C++-related BUILD file.
By default, only the CPPLINT.cfg from the project root and the current
directory are used. Additional configs can be passed in as data labels.
Sources that are not discoverable through the "sources so far" heuristic can
be passed in as extra_srcs=[].
"""
# Iterate over all rules.
for rule in native.existing_rules().values():
# Extract the list of C++ source code labels and convert to filenames.
candidate_labels = (
_extract_labels(rule.get("srcs", ())) +
_extract_labels(rule.get("hdrs", ()))
)
source_labels = [
label for label in candidate_labels
if _is_source_label(label)
]
source_filenames = ["$(location %s)" % x for x in source_labels]
# Run the cpplint checker as a unit test.
if len(source_filenames) > 0:
_add_linter_rules(source_labels, source_filenames, rule["name"], data)
# Lint all of the extra_srcs separately in a single rule.
if extra_srcs:
source_labels = extra_srcs
source_filenames = ["$(location %s)" % x for x in source_labels]
_add_linter_rules(source_labels, source_filenames,
"extra_srcs_cpplint", data)