123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- #!/usr/bin/env python
- """\
- Sanitize a bitbake file following the OpenEmbedded style guidelines,
- see http://openembedded.org/wiki/StyleGuide
- (C) 2006 Cyril Romain <cyril.romain@gmail.com>
- MIT license
- TODO:
- - add the others OpenEmbedded variables commonly used:
- - parse command arguments and print usage on misuse
- . prevent giving more than one .bb file in arguments
- - write result to a file
- - backup the original .bb file
- - make a diff and ask confirmation for patching ?
- - do not use startswith only:
- /!\ startswith('SOMETHING') is not taken into account due to the previous startswith('S').
- - count rule breaks and displays them in the order frequence
- """
- from __future__ import print_function
- import fileinput
- import string
- import re
- __author__ = "Cyril Romain <cyril.romain@gmail.com>"
- __version__ = "$Revision: 0.5 $"
- # The standard set of variables often found in .bb files in the preferred order
- OE_vars = [
- 'SUMMARY',
- 'DESCRIPTION',
- 'AUTHOR',
- 'HOMEPAGE',
- 'SECTION',
- 'LICENSE',
- 'LIC_FILES_CHKSUM',
- 'DEPENDS',
- 'PROVIDES',
- 'SRCREV',
- 'SRCDATE',
- 'PE',
- 'PV',
- 'PR',
- 'INC_PR',
- 'SRC_URI',
- 'S',
- 'GPE_TARBALL_SUFFIX',
- 'inherit',
- 'EXTRA_',
- 'export',
- 'do_fetch',
- 'do_unpack',
- 'do_patch',
- 'WORKDIR',
- 'acpaths',
- 'do_configure',
- 'do_compile',
- 'do_install',
- 'PACKAGES',
- 'PACKAGE_ARCH',
- 'RDEPENDS',
- 'RRECOMMENDS',
- 'RSUGGESTS',
- 'RPROVIDES',
- 'RCONFLICTS',
- 'FILES',
- 'do_package',
- 'do_stage',
- 'addhandler',
- 'addtask',
- 'bindir',
- 'headers',
- 'include',
- 'includedir',
- 'python',
- 'qtopiadir',
- 'pkg_preins',
- 'pkg_prerm',
- 'pkg_postins',
- 'pkg_postrm',
- 'require',
- 'sbindir',
- 'basesysconfdir',
- 'sysconfdir',
- 'ALLOW_EMPTY',
- 'ALTERNATIVE_NAME',
- 'ALTERNATIVE_PATH',
- 'ALTERNATIVE_LINK',
- 'ALTERNATIVE_PRIORITY',
- 'ALTNAME',
- 'AMD_DRIVER_LABEL',
- 'AMD_DRIVER_VERSION',
- 'ANGSTROM_EXTRA_INSTALL',
- 'APPDESKTOP',
- 'APPIMAGE',
- 'APPNAME',
- 'APPTYPE',
- 'APPWEB_BUILD',
- 'APPWEB_HOST',
- 'AR',
- 'ARCH',
- 'ARM_INSTRUCTION_SET',
- 'MIPS_INSTRUCTION_SET',
- 'ARM_MUTEX',
- 'ART_CONFIG',
- 'B',
- 'BJAM_OPTS',
- 'BJAM_TOOLS',
- 'BONOBO_HEADERS',
- 'BOOTSCRIPTS',
- 'BROKEN',
- 'BUILD_CPPFLAGS',
- 'CFLAGS',
- 'CCFLAGS',
- 'CMDLINE',
- 'COLLIE_MEMORY_SIZE',
- 'COMPATIBLE_HOST',
- 'COMPATIBLE_MACHINE',
- 'COMPILE_HERMES',
- 'CONFFILES',
- 'CONFLICTS',
- 'CORE_EXTRA_D',
- 'CORE_IMAGE_EXTRA_INSTALL',
- 'CORE_PACKAGES_D',
- 'CORE_PACKAGES_RD',
- 'CPPFLAGS',
- 'CVSDATE',
- 'CXXFLAGS',
- 'DEBIAN_NOAUTONAME',
- 'DEBUG_APPS',
- 'DEFAULT_PREFERENCE',
- 'DB4_CONFIG',
- 'EXCLUDE_FROM_SHLIBS',
- 'EXCLUDE_FROM_WORLD',
- 'FIXEDSRCDATE',
- 'GLIBC_ADDONS',
- 'GLIBC_EXTRA_OECONF',
- 'GNOME_VFS_HEADERS',
- 'HEADERS',
- 'INHIBIT_DEFAULT_DEPS',
- 'INITSCRIPT_PACKAGES',
- 'INITSCRIPT_NAME',
- 'INITSCRIPT_PARAMS',
- 'INSANE_SKIP',
- 'PACKAGE_INSTALL',
- 'KERNEL_IMAGETYPE',
- 'KERNEL_IMAGEDEST',
- 'KERNEL_OUTPUT',
- 'KERNEL_RELEASE',
- 'KERNEL_PRIORITY',
- 'KERNEL_SOURCE',
- 'KERNEL_SUFFIX',
- 'KERNEL_VERSION',
- 'K_MAJOR',
- 'K_MICRO',
- 'K_MINOR',
- 'HHV',
- 'KV',
- 'LDFLAGS',
- 'LD',
- 'LD_SO',
- 'LDLIBS',
- 'LEAD_SONAME',
- 'LIBTOOL',
- 'LIBBDB_EXTRA',
- 'LIBV',
- 'MACHINE_ESSENTIAL_EXTRA_RDEPENDS',
- 'MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS',
- 'MACHINE_EXTRA_RDEPENDS',
- 'MACHINE_EXTRA_RRECOMMENDS',
- 'MACHINE_FEATURES',
- 'MACHINE_TASKS',
- 'MACHINE',
- 'MACHTYPE',
- 'MAKE_TARGETS',
- 'MESSAGEUSER',
- 'MESSAGEHOME',
- 'MIRRORS',
- 'MUTEX',
- 'OE_QMAKE_INCDIR_QT',
- 'OE_QMAKE_CXXFLAGS',
- 'ORBIT_IDL_SRC',
- 'PARALLEL_MAKE',
- 'PAKCAGE_ARCH',
- 'PCMCIA_MANAGER',
- 'PKG_BASENAME',
- 'PKG',
- 'QEMU',
- 'QMAKE_PROFILES',
- 'QPEDIR',
- 'QPF_DESCRIPTION',
- 'QPF_PKGPATTERN',
- 'QT_CONFIG_FLAGS',
- 'QT_LIBRARY',
- 'ROOTFS_POSTPROCESS_COMMAND',
- 'RREPLACES',
- 'TARGET_CFLAGS',
- 'TARGET_CPPFLAGS',
- 'TARGET_LDFLAGS',
- 'UBOOT_MACHINE',
- 'UCLIBC_BASE',
- 'UCLIBC_PATCHES',
- 'USERADD_PACKAGES',
- 'USERADD_PARAM',
- 'VIRTUAL_NAME',
- 'XORG_PN',
- 'XSERVER',
- 'others'
- ]
- varRegexp = r'^([a-zA-Z_0-9${}:-]*)([ \t]*)([+.:]?=[+.]?)([ \t]*)([^\t]+)'
- routineRegexp = r'^([a-zA-Z0-9_ ${}:-]+?)\('
- # Variables seen in the processed .bb
- seen_vars = {}
- for v in OE_vars:
- seen_vars[v] = []
- # _Format guideline #0_:
- # No spaces are allowed at the beginning of lines that define a variable or
- # a do_ routine
- def respect_rule0(line):
- return line.lstrip() == line
- def conformTo_rule0(line):
- return line.lstrip()
- # _Format guideline #1_:
- # No spaces are allowed behind the line continuation symbol '\'
- def respect_rule1(line):
- if line.rstrip().endswith('\\'):
- return line.endswith('\\')
- else:
- return True
- def conformTo_rule1(line):
- return line.rstrip()
- # _Format guideline #2_:
- # Tabs should not be used (use spaces instead).
- def respect_rule2(line):
- return line.count('\t') == 0
- def conformTo_rule2(line):
- return line.expandtabs()
- # _Format guideline #3_:
- # Comments inside bb files are allowed using the '#' character at the
- # beginning of a line.
- def respect_rule3(line):
- if line.lstrip().startswith('#'):
- return line.startswith('#')
- else:
- return True
- def conformTo_rule3(line):
- return line.lstrip()
- # _Format guideline #4_:
- # Use quotes on the right hand side of assignments FOO = "BAR"
- def respect_rule4(line):
- r = re.search(varRegexp, line)
- if r is not None:
- r2 = re.search(r'("?)([^"\\]*)(["\\]?)', r.group(5))
- # do not test for None it because always match
- return r2.group(1) == '"' and r2.group(3) != ''
- return False
- def conformTo_rule4(line):
- r = re.search(varRegexp, line)
- return ''.join([r.group(1), ' ', r.group(3), ' "', r.group(5), r.group(5).endswith('"') and '' or '"'])
- # _Format guideline #5_:
- # The correct spacing for a variable is FOO = "BAR".
- def respect_rule5(line):
- r = re.search(varRegexp, line)
- return r is not None and r.group(2) == " " and r.group(4) == " "
- def conformTo_rule5(line):
- r = re.search(varRegexp, line)
- return ''.join([r.group(1), ' ', r.group(3), ' ', r.group(5)])
- # _Format guideline #6_:
- # Don't use spaces or tabs on empty lines
- def respect_rule6(line):
- return not line.isspace() or line == "\n"
- def conformTo_rule6(line):
- return ""
- # _Format guideline #7_:
- # Indentation of multiline variables such as SRC_URI is desireable.
- def respect_rule7(line):
- return True
- def conformTo_rule7(line):
- return line
- rules = (
- (respect_rule0, conformTo_rule0, "No spaces are allowed at the beginning of lines that define a variable or a do_ routine"),
- (respect_rule1, conformTo_rule1, "No spaces are allowed behind the line continuation symbol '\\'"),
- (respect_rule2, conformTo_rule2, "Tabs should not be used (use spaces instead)"),
- (respect_rule3, conformTo_rule3, "Comments inside bb files are allowed using the '#' character at the beginning of a line"),
- (respect_rule4, conformTo_rule4, "Use quotes on the right hand side of assignments FOO = \"BAR\""),
- (respect_rule5, conformTo_rule5, "The correct spacing for a variable is FOO = \"BAR\""),
- (respect_rule6, conformTo_rule6, "Don't use spaces or tabs on empty lines"),
- (respect_rule7, conformTo_rule7, "Indentation of multiline variables such as SRC_URI is desireable"),
- )
- # Function to check that a line respects a rule. If not, it tries to conform
- # the line to the rule. Reminder or Disgression message are dump accordingly.
- def follow_rule(i, line):
- oldline = line
- # if the line does not respect the rule
- if not rules[i][0](line):
- # try to conform it to the rule
- line = rules[i][1](line)
- # if the line still does not respect the rule
- if not rules[i][0](line):
- # this is a rule disgression
- print("## Disgression: ", rules[i][2], " in: '", oldline, "'")
- else:
- # just remind user about his/her errors
- print("## Reminder: ", rules[i][2], " in : '", oldline, "'")
- return line
- if __name__ == "__main__":
- # -- retrieves the lines of the .bb file --
- lines = []
- for line in fileinput.input():
- # use 'if True' to warn user about all the rule he/she breaks
- # use 'if False' to conform to rules{2,1,6} without warnings
- if True:
- lines.append(line)
- else:
- # expandtabs on each line so that rule2 is always respected
- # rstrip each line so that rule1 is always respected
- line = line.expandtabs().rstrip()
- # ignore empty lines (or line filled with spaces or tabs only)
- # so that rule6 is always respected
- if line != '':
- lines.append(line)
- # -- parse the file --
- var = ""
- in_routine = False
- commentBloc = []
- olines = []
- for line in lines:
- originalLine = line
- # rstrip line to remove line breaks characters
- line = line.rstrip()
- line = follow_rule(2, line)
- line = follow_rule(1, line)
- line = follow_rule(6, line)
- # ignore empty lines
- if line.isspace() or line == '':
- # flush comments into the olines
- for c in commentBloc:
- olines.append(c)
- commentBloc = []
- continue
- if line.startswith('}'):
- in_routine = False
- keep = line.endswith('\\') or in_routine
- # handles commented lines
- if line.lstrip().startswith('#'):
- # check and follow rule3 if not in a variables or routines
- if not in_routine:
- line = follow_rule(3, line)
- commentBloc.append(line)
- continue
- if var in seen_vars:
- for c in commentBloc:
- seen_vars[var].append(c)
- commentBloc = []
- seen_vars[var].append(line)
- else:
- for k in OE_vars:
- if line.startswith(k):
- var = k
- break
- if re.match(routineRegexp, line) is not None:
- in_routine = True
- line = follow_rule(0, line)
- elif re.match(varRegexp, line) is not None:
- line = follow_rule(0, line)
- line = follow_rule(4, line)
- line = follow_rule(5, line)
- if var == "":
- if not in_routine:
- print("## Warning: unknown variable/routine \"%s\"" % originalLine.rstrip('\n'))
- var = 'others'
- for c in commentBloc:
- seen_vars[var].append(c)
- commentBloc = []
- seen_vars[var].append(line)
- if not keep and not in_routine:
- var = ""
- # -- dump the sanitized .bb file --
- addEmptyLine = False
- # write comments that are not related to variables nor routines
- for l in commentBloc:
- olines.append(l)
- # write variables and routines
- previourVarPrefix = "unknown"
- for k in OE_vars:
- if k == 'SRC_URI':
- addEmptyLine = True
- if seen_vars[k] != []:
- if addEmptyLine and not k.startswith(previourVarPrefix):
- olines.append("")
- for l in seen_vars[k]:
- olines.append(l)
- previourVarPrefix = k.split('_')[0] == '' and "unknown" or k.split('_')[0]
- for line in olines:
- print(line)
|