1 # See support/scripts/check-package.txt before editing this file.
2 # There are already dependency checks during the build, so below check
3 # functions don't need to check for things already checked by exploring the
4 # menu options using "make menuconfig" and by running "make" with appropriate
9 from checkpackagebase import _CheckFunction
10 # Notice: ignore 'imported but unused' from pyflakes for check functions.
11 from checkpackagelib import ConsecutiveEmptyLines
12 from checkpackagelib import EmptyLastLine
13 from checkpackagelib import NewlineAtEof
14 from checkpackagelib import TrailingSpace
17 class Indent(_CheckFunction):
18 COMMENT = re.compile("^\s*#")
19 CONDITIONAL = re.compile("^\s*(ifeq|ifneq|endif)\s")
20 ENDS_WITH_BACKSLASH = re.compile(r"^[^#].*\\$")
21 END_DEFINE = re.compile("^\s*endef\s")
22 MAKEFILE_TARGET = re.compile("^[^# \t]+:\s")
23 START_DEFINE = re.compile("^\s*define\s")
27 self.backslash = False
28 self.makefile_target = False
30 def check_line(self, lineno, text):
31 if self.START_DEFINE.search(text):
34 if self.END_DEFINE.search(text):
39 if self.define or self.backslash or self.makefile_target:
41 if self.CONDITIONAL.search(text):
44 # calculate for next line
45 if self.ENDS_WITH_BACKSLASH.search(text):
48 self.backslash = False
50 if self.MAKEFILE_TARGET.search(text):
51 self.makefile_target = True
53 if text.strip() == "":
54 self.makefile_target = False
57 # comment can be indented or not inside define ... endef, so ignore it
58 if self.define and self.COMMENT.search(text):
62 if not text.startswith("\t"):
63 return ["{}:{}: expected indent with tabs"
64 .format(self.filename, lineno),
67 if text.startswith("\t"):
68 return ["{}:{}: unexpected indent with tabs"
69 .format(self.filename, lineno),
73 class PackageHeader(_CheckFunction):
77 def check_line(self, lineno, text):
78 if self.skip or lineno > 6:
82 if lineno == 1 and text.startswith("include "):
85 if text.rstrip() != "#" * 80:
86 return ["{}:{}: should be 80 hashes ({}#writing-rules-mk)"
87 .format(self.filename, lineno, self.url_to_manual),
90 elif lineno in [2, 4]:
91 if text.rstrip() != "#":
92 return ["{}:{}: should be 1 hash ({}#writing-rules-mk)"
93 .format(self.filename, lineno, self.url_to_manual),
96 if text.rstrip() != "":
97 return ["{}:{}: should be a blank line ({}#writing-rules-mk)"
98 .format(self.filename, lineno, self.url_to_manual),
102 class SpaceBeforeBackslash(_CheckFunction):
103 TAB_OR_MULTIPLE_SPACES_BEFORE_BACKSLASH = re.compile(r"^.*( |\t)\\$")
105 def check_line(self, lineno, text):
106 if self.TAB_OR_MULTIPLE_SPACES_BEFORE_BACKSLASH.match(text.rstrip()):
107 return ["{}:{}: use only one space before backslash"
108 .format(self.filename, lineno),
112 class TrailingBackslash(_CheckFunction):
113 ENDS_WITH_BACKSLASH = re.compile(r"^[^#].*\\$")
116 self.backslash = False
118 def check_line(self, lineno, text):
119 last_line_ends_in_backslash = self.backslash
121 # calculate for next line
122 if self.ENDS_WITH_BACKSLASH.search(text):
123 self.backslash = True
126 self.backslash = False
128 if last_line_ends_in_backslash and text.strip() == "":
129 return ["{}:{}: remove trailing backslash"
130 .format(self.filename, lineno - 1),
134 class TypoInPackageVariable(_CheckFunction):
135 ALLOWED = re.compile("|".join([
138 "BR_CCACHE_INITIAL_SETUP",
139 "BR_NO_CHECK_HASH_FOR",
140 "LINUX_POST_PATCH_HOOKS",
145 "PKG_CONFIG_HOST_BINARY",
146 "TARGET_FINALIZE_HOOKS",
147 "XTENSA_CORE_NAME"]))
148 PACKAGE_NAME = re.compile("/([^/]+)\.mk")
149 VARIABLE = re.compile("^([A-Z0-9_]+_[A-Z0-9_]+)\s*(\+|)=")
152 package = self.PACKAGE_NAME.search(self.filename).group(1)
153 package = package.replace("-", "_").upper()
154 # linux tools do not use LINUX_TOOL_ prefix for variables
155 package = package.replace("LINUX_TOOL_", "")
156 self.package = package
157 self.REGEX = re.compile("^(HOST_)?({}_[A-Z0-9_]+)".format(package))
158 self.FIND_VIRTUAL = re.compile(
159 "^{}_PROVIDES\s*(\+|)=\s*(.*)".format(package))
162 def check_line(self, lineno, text):
163 m = self.VARIABLE.search(text)
167 variable = m.group(1)
169 # allow to set variables for virtual package this package provides
170 v = self.FIND_VIRTUAL.search(text)
172 self.virtual += v.group(2).upper().split()
174 for virtual in self.virtual:
175 if variable.startswith("{}_".format(virtual)):
178 if self.ALLOWED.match(variable):
180 if self.REGEX.search(text) is None:
181 return ["{}:{}: possible typo: {} -> *{}*"
182 .format(self.filename, lineno, variable, self.package),
186 class UselessFlag(_CheckFunction):
187 DEFAULT_AUTOTOOLS_FLAG = re.compile("^.*{}".format("|".join([
188 "_AUTORECONF\s*=\s*NO",
189 "_LIBTOOL_PATCH\s*=\s*YES"])))
190 DEFAULT_GENERIC_FLAG = re.compile("^.*{}".format("|".join([
191 "_INSTALL_IMAGES\s*=\s*NO",
192 "_INSTALL_REDISTRIBUTE\s*=\s*YES",
193 "_INSTALL_STAGING\s*=\s*NO",
194 "_INSTALL_TARGET\s*=\s*YES"])))
195 END_CONDITIONAL = re.compile("^\s*(endif)")
196 START_CONDITIONAL = re.compile("^\s*(ifeq|ifneq)")
201 def check_line(self, lineno, text):
202 if self.START_CONDITIONAL.search(text):
203 self.conditional += 1
205 if self.END_CONDITIONAL.search(text):
206 self.conditional -= 1
209 # allow non-default conditionally overridden by default
210 if self.conditional > 0:
213 if self.DEFAULT_GENERIC_FLAG.search(text):
214 return ["{}:{}: useless default value ({}#"
215 "_infrastructure_for_packages_with_specific_build_systems)"
216 .format(self.filename, lineno, self.url_to_manual),
219 if self.DEFAULT_AUTOTOOLS_FLAG.search(text):
220 return ["{}:{}: useless default value "
221 "({}#_infrastructure_for_autotools_based_packages)"
222 .format(self.filename, lineno, self.url_to_manual),