4 Sanitize a bitbake file following the OpenEmbedded style guidelines,
5 see http://openembedded.org/wiki/StyleGuide
7 (C) 2006 Cyril Romain <cyril.romain@gmail.com>
11 - add the others OpenEmbedded variables commonly used:
12 - parse command arguments and print usage on misuse
13 . prevent giving more than one .bb file in arguments
14 - write result to a file
15 - backup the original .bb file
16 - make a diff and ask confirmation for patching ?
17 - do not use startswith only:
18 /!\ startswith('SOMETHING') is not taken into account due to the previous startswith('S').
19 - count rule breaks and displays them in the order frequence
26 __author__ = "Cyril Romain <cyril.romain@gmail.com>"
27 __version__ = "$Revision: 0.5 $"
29 # The standard set of variables often found in .bb files in the preferred order
87 'ALTERNATIVE_PRIORITY',
91 'ANGSTROM_EXTRA_INSTALL',
100 'ARM_INSTRUCTION_SET',
113 'COLLIE_MEMORY_SIZE',
115 'COMPATIBLE_MACHINE',
127 'DEFAULT_PREFERENCE',
129 'EXCLUDE_FROM_SHLIBS',
130 'EXCLUDE_FROM_WORLD',
133 'GLIBC_EXTRA_OECONF',
136 'INHIBIT_DEFAULT_DEPS',
137 'INITSCRIPT_PACKAGES',
162 'MACHINE_ESSENTIAL_EXTRA_RDEPENDS',
163 'MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS',
164 'MACHINE_EXTRA_RDEPENDS',
165 'MACHINE_EXTRA_RRECOMMENDS',
175 'OE_QMAKE_INCDIR_QT',
190 'ROOTFS_POSTPROCESS_COMMAND',
205 varRegexp = r'^([a-zA-Z_0-9${}-]*)([ \t]*)([+.:]?=[+.]?)([ \t]*)([^\t]+)'
206 routineRegexp = r'^([a-zA-Z0-9_ ${}-]+?)\('
208 # Variables seen in the processed .bb
213 # _Format guideline #0_:
214 # No spaces are allowed at the beginning of lines that define a variable or
216 def respect_rule0(line):
217 return line.lstrip()==line
218 def conformTo_rule0(line):
221 # _Format guideline #1_:
222 # No spaces are allowed behind the line continuation symbol '\'
223 def respect_rule1(line):
224 if line.rstrip().endswith('\\'):
225 return line.endswith('\\')
228 def conformTo_rule1(line):
231 # _Format guideline #2_:
232 # Tabs should not be used (use spaces instead).
233 def respect_rule2(line):
234 return line.count('\t')==0
235 def conformTo_rule2(line):
236 return line.expandtabs()
238 # _Format guideline #3_:
239 # Comments inside bb files are allowed using the '#' character at the
240 # beginning of a line.
241 def respect_rule3(line):
242 if line.lstrip().startswith('#'):
243 return line.startswith('#')
246 def conformTo_rule3(line):
249 # _Format guideline #4_:
250 # Use quotes on the right hand side of assignments FOO = "BAR"
251 def respect_rule4(line):
252 r = re.search(varRegexp, line)
254 r2 = re.search(r'("?)([^"\\]*)(["\\]?)', r.group(5))
255 # do not test for None it because always match
256 return r2.group(1)=='"' and r2.group(3)!=''
258 def conformTo_rule4(line):
259 r = re.search(varRegexp, line)
260 return ''.join([r.group(1), ' ', r.group(3), ' "', r.group(5), r.group(5).endswith('"') and '' or '"'])
262 # _Format guideline #5_:
263 # The correct spacing for a variable is FOO = "BAR".
264 def respect_rule5(line):
265 r = re.search(varRegexp, line)
266 return r is not None and r.group(2)==" " and r.group(4)==" "
267 def conformTo_rule5(line):
268 r = re.search(varRegexp, line)
269 return ''.join([r.group(1), ' ', r.group(3), ' ', r.group(5)])
271 # _Format guideline #6_:
272 # Don't use spaces or tabs on empty lines
273 def respect_rule6(line):
274 return not line.isspace() or line=="\n"
275 def conformTo_rule6(line):
278 # _Format guideline #7_:
279 # Indentation of multiline variables such as SRC_URI is desireable.
280 def respect_rule7(line):
282 def conformTo_rule7(line):
286 (respect_rule0, conformTo_rule0, "No spaces are allowed at the beginning of lines that define a variable or a do_ routine"),
287 (respect_rule1, conformTo_rule1, "No spaces are allowed behind the line continuation symbol '\\'"),
288 (respect_rule2, conformTo_rule2, "Tabs should not be used (use spaces instead)"),
289 (respect_rule3, conformTo_rule3, "Comments inside bb files are allowed using the '#' character at the beginning of a line"),
290 (respect_rule4, conformTo_rule4, "Use quotes on the right hand side of assignments FOO = \"BAR\""),
291 (respect_rule5, conformTo_rule5, "The correct spacing for a variable is FOO = \"BAR\""),
292 (respect_rule6, conformTo_rule6, "Don't use spaces or tabs on empty lines"),
293 (respect_rule7, conformTo_rule7, "Indentation of multiline variables such as SRC_URI is desireable"),
296 # Function to check that a line respects a rule. If not, it tries to conform
297 # the line to the rule. Reminder or Disgression message are dump accordingly.
298 def follow_rule(i, line):
300 # if the line does not respect the rule
301 if not rules[i][0](line):
302 # try to conform it to the rule
303 line = rules[i][1](line)
304 # if the line still does not respect the rule
305 if not rules[i][0](line):
306 # this is a rule disgression
307 print "## Disgression: ", rules[i][2], " in:", oldline
309 # just remind user about his/her errors
310 print "## Reminder: ", rules[i][2], " in :", oldline
314 if __name__ == "__main__":
316 # -- retrieves the lines of the .bb file --
318 for line in fileinput.input():
319 # use 'if True' to warn user about all the rule he/she breaks
320 # use 'if False' to conform to rules{2,1,6} without warnings
324 # expandtabs on each line so that rule2 is always respected
325 # rstrip each line so that rule1 is always respected
326 line = line.expandtabs().rstrip()
327 # ignore empty lines (or line filled with spaces or tabs only)
328 # so that rule6 is always respected
332 # -- parse the file --
339 # rstrip line to remove line breaks characters
341 line = follow_rule(2, line)
342 line = follow_rule(1, line)
343 line = follow_rule(6, line)
346 if line.isspace() or line is '':
347 # flush comments into the olines
348 for c in commentBloc: olines.append(c)
352 if line.startswith('}'):
354 keep = line.endswith('\\') or in_routine
356 # handles commented lines
357 if line.lstrip().startswith('#'):
358 # check and follow rule3 if not in a variables or routines
360 line = follow_rule(3, line)
361 commentBloc.append(line)
364 if seen_vars.has_key(var):
365 for c in commentBloc: seen_vars[var].append(c)
367 seen_vars[var].append(line)
370 if line.startswith(k):
373 if re.match(routineRegexp, line) is not None:
375 line = follow_rule(0, line)
376 elif re.match(varRegexp, line) is not None:
377 line = follow_rule(0, line)
378 line = follow_rule(4, line)
379 line = follow_rule(5, line)
382 print "## Warning: unknown variable/routine \"%s\"" % originalLine
384 for c in commentBloc: seen_vars[var].append(c)
386 seen_vars[var].append(line)
387 if not keep and not in_routine: var = ""
389 # -- dump the sanitized .bb file --
391 # write comments that are not related to variables nor routines
392 for l in commentBloc: olines.append(l)
393 # write variables and routines
394 previourVarPrefix = "unknown"
396 if k=='SRC_URI': addEmptyLine = True
397 if seen_vars[k] != []:
398 if addEmptyLine and not k.startswith(previourVarPrefix):
400 for l in seen_vars[k]:
402 previourVarPrefix = k.split('_')[0]=='' and "unknown" or k.split('_')[0]
403 for line in olines: print line