Just AUTORECONF = NO is redundant. Just HOST_AUTORECONF = NO is redundant. But the combination of AUTORECONF = YES + HOST_AUTORECONF = NO is valid. So basically for all variables that have inheritance between target and host, having the host variant of the variable set the variable value back to its default is correct if the target variable is set. Instead of increasing complexity of the script to fully detect this case, ignore the host flag set to its default value as it can be overriding a non-default value inherited from the equivalent target flag. Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Yann E. MORIN <yann.morin.1998@free.fr> Reported-by: Yann E. MORIN <yann.morin.1998@free.fr> Signed-off-by: Ricardo Martincoski <ricardo.martincoski@datacom.ind.br> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
224 lines
7.6 KiB
Python
224 lines
7.6 KiB
Python
# See utils/checkpackagelib/readme.txt before editing this file.
|
|
# There are already dependency checks during the build, so below check
|
|
# functions don't need to check for things already checked by exploring the
|
|
# menu options using "make menuconfig" and by running "make" with appropriate
|
|
# packages enabled.
|
|
|
|
import re
|
|
|
|
from base import _CheckFunction
|
|
# Notice: ignore 'imported but unused' from pyflakes for check functions.
|
|
from lib import ConsecutiveEmptyLines
|
|
from lib import EmptyLastLine
|
|
from lib import NewlineAtEof
|
|
from lib import TrailingSpace
|
|
|
|
|
|
class Indent(_CheckFunction):
|
|
COMMENT = re.compile("^\s*#")
|
|
CONDITIONAL = re.compile("^\s*(ifeq|ifneq|endif)\s")
|
|
ENDS_WITH_BACKSLASH = re.compile(r"^[^#].*\\$")
|
|
END_DEFINE = re.compile("^\s*endef\s")
|
|
MAKEFILE_TARGET = re.compile("^[^# \t]+:\s")
|
|
START_DEFINE = re.compile("^\s*define\s")
|
|
|
|
def before(self):
|
|
self.define = False
|
|
self.backslash = False
|
|
self.makefile_target = False
|
|
|
|
def check_line(self, lineno, text):
|
|
if self.START_DEFINE.search(text):
|
|
self.define = True
|
|
return
|
|
if self.END_DEFINE.search(text):
|
|
self.define = False
|
|
return
|
|
|
|
expect_tabs = False
|
|
if self.define or self.backslash or self.makefile_target:
|
|
expect_tabs = True
|
|
if self.CONDITIONAL.search(text):
|
|
expect_tabs = False
|
|
|
|
# calculate for next line
|
|
if self.ENDS_WITH_BACKSLASH.search(text):
|
|
self.backslash = True
|
|
else:
|
|
self.backslash = False
|
|
|
|
if self.MAKEFILE_TARGET.search(text):
|
|
self.makefile_target = True
|
|
return
|
|
if text.strip() == "":
|
|
self.makefile_target = False
|
|
return
|
|
|
|
# comment can be indented or not inside define ... endef, so ignore it
|
|
if self.define and self.COMMENT.search(text):
|
|
return
|
|
|
|
if expect_tabs:
|
|
if not text.startswith("\t"):
|
|
return ["{}:{}: expected indent with tabs"
|
|
.format(self.filename, lineno),
|
|
text]
|
|
else:
|
|
if text.startswith("\t"):
|
|
return ["{}:{}: unexpected indent with tabs"
|
|
.format(self.filename, lineno),
|
|
text]
|
|
|
|
|
|
class PackageHeader(_CheckFunction):
|
|
def before(self):
|
|
self.skip = False
|
|
|
|
def check_line(self, lineno, text):
|
|
if self.skip or lineno > 6:
|
|
return
|
|
|
|
if lineno in [1, 5]:
|
|
if lineno == 1 and text.startswith("include "):
|
|
self.skip = True
|
|
return
|
|
if text.rstrip() != "#" * 80:
|
|
return ["{}:{}: should be 80 hashes ({}#writing-rules-mk)"
|
|
.format(self.filename, lineno, self.url_to_manual),
|
|
text,
|
|
"#" * 80]
|
|
elif lineno in [2, 4]:
|
|
if text.rstrip() != "#":
|
|
return ["{}:{}: should be 1 hash ({}#writing-rules-mk)"
|
|
.format(self.filename, lineno, self.url_to_manual),
|
|
text]
|
|
elif lineno == 6:
|
|
if text.rstrip() != "":
|
|
return ["{}:{}: should be a blank line ({}#writing-rules-mk)"
|
|
.format(self.filename, lineno, self.url_to_manual),
|
|
text]
|
|
|
|
|
|
class SpaceBeforeBackslash(_CheckFunction):
|
|
TAB_OR_MULTIPLE_SPACES_BEFORE_BACKSLASH = re.compile(r"^.*( |\t)\\$")
|
|
|
|
def check_line(self, lineno, text):
|
|
if self.TAB_OR_MULTIPLE_SPACES_BEFORE_BACKSLASH.match(text.rstrip()):
|
|
return ["{}:{}: use only one space before backslash"
|
|
.format(self.filename, lineno),
|
|
text]
|
|
|
|
|
|
class TrailingBackslash(_CheckFunction):
|
|
ENDS_WITH_BACKSLASH = re.compile(r"^[^#].*\\$")
|
|
|
|
def before(self):
|
|
self.backslash = False
|
|
|
|
def check_line(self, lineno, text):
|
|
last_line_ends_in_backslash = self.backslash
|
|
|
|
# calculate for next line
|
|
if self.ENDS_WITH_BACKSLASH.search(text):
|
|
self.backslash = True
|
|
self.lastline = text
|
|
return
|
|
self.backslash = False
|
|
|
|
if last_line_ends_in_backslash and text.strip() == "":
|
|
return ["{}:{}: remove trailing backslash"
|
|
.format(self.filename, lineno - 1),
|
|
self.lastline]
|
|
|
|
|
|
class TypoInPackageVariable(_CheckFunction):
|
|
ALLOWED = re.compile("|".join([
|
|
"ACLOCAL_DIR",
|
|
"ACLOCAL_HOST_DIR",
|
|
"BR_CCACHE_INITIAL_SETUP",
|
|
"BR_NO_CHECK_HASH_FOR",
|
|
"LINUX_POST_PATCH_HOOKS",
|
|
"LINUX_TOOLS",
|
|
"LUA_RUN",
|
|
"MKFS_JFFS2",
|
|
"MKIMAGE_ARCH",
|
|
"PKG_CONFIG_HOST_BINARY",
|
|
"TARGET_FINALIZE_HOOKS",
|
|
"XTENSA_CORE_NAME"]))
|
|
PACKAGE_NAME = re.compile("/([^/]+)\.mk")
|
|
VARIABLE = re.compile("^([A-Z0-9_]+_[A-Z0-9_]+)\s*(\+|)=")
|
|
|
|
def before(self):
|
|
package = self.PACKAGE_NAME.search(self.filename).group(1)
|
|
package = package.replace("-", "_").upper()
|
|
# linux tools do not use LINUX_TOOL_ prefix for variables
|
|
package = package.replace("LINUX_TOOL_", "")
|
|
self.package = package
|
|
self.REGEX = re.compile("^(HOST_)?({}_[A-Z0-9_]+)".format(package))
|
|
self.FIND_VIRTUAL = re.compile(
|
|
"^{}_PROVIDES\s*(\+|)=\s*(.*)".format(package))
|
|
self.virtual = []
|
|
|
|
def check_line(self, lineno, text):
|
|
m = self.VARIABLE.search(text)
|
|
if m is None:
|
|
return
|
|
|
|
variable = m.group(1)
|
|
|
|
# allow to set variables for virtual package this package provides
|
|
v = self.FIND_VIRTUAL.search(text)
|
|
if v:
|
|
self.virtual += v.group(2).upper().split()
|
|
return
|
|
for virtual in self.virtual:
|
|
if variable.startswith("{}_".format(virtual)):
|
|
return
|
|
|
|
if self.ALLOWED.match(variable):
|
|
return
|
|
if self.REGEX.search(text) is None:
|
|
return ["{}:{}: possible typo: {} -> *{}*"
|
|
.format(self.filename, lineno, variable, self.package),
|
|
text]
|
|
|
|
|
|
class UselessFlag(_CheckFunction):
|
|
DEFAULT_AUTOTOOLS_FLAG = re.compile("^.*{}".format("|".join([
|
|
"_AUTORECONF\s*=\s*NO",
|
|
"_LIBTOOL_PATCH\s*=\s*YES"])))
|
|
DEFAULT_GENERIC_FLAG = re.compile("^.*{}".format("|".join([
|
|
"_INSTALL_IMAGES\s*=\s*NO",
|
|
"_INSTALL_REDISTRIBUTE\s*=\s*YES",
|
|
"_INSTALL_STAGING\s*=\s*NO",
|
|
"_INSTALL_TARGET\s*=\s*YES"])))
|
|
END_CONDITIONAL = re.compile("^\s*(endif)")
|
|
START_CONDITIONAL = re.compile("^\s*(ifeq|ifneq)")
|
|
|
|
def before(self):
|
|
self.conditional = 0
|
|
|
|
def check_line(self, lineno, text):
|
|
if self.START_CONDITIONAL.search(text):
|
|
self.conditional += 1
|
|
return
|
|
if self.END_CONDITIONAL.search(text):
|
|
self.conditional -= 1
|
|
return
|
|
|
|
# allow non-default conditionally overridden by default
|
|
if self.conditional > 0:
|
|
return
|
|
|
|
if self.DEFAULT_GENERIC_FLAG.search(text):
|
|
return ["{}:{}: useless default value ({}#"
|
|
"_infrastructure_for_packages_with_specific_build_systems)"
|
|
.format(self.filename, lineno, self.url_to_manual),
|
|
text]
|
|
|
|
if self.DEFAULT_AUTOTOOLS_FLAG.search(text) and not text.lstrip().startswith("HOST_"):
|
|
return ["{}:{}: useless default value "
|
|
"({}#_infrastructure_for_autotools_based_packages)"
|
|
.format(self.filename, lineno, self.url_to_manual),
|
|
text]
|