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
86 'ALTERNATIVE_PRIORITY',
90 'ANGSTROM_EXTRA_INSTALL',
99 'ARM_INSTRUCTION_SET',
112 'COLLIE_MEMORY_SIZE',
114 'COMPATIBLE_MACHINE',
126 'DEFAULT_PREFERENCE',
128 'EXCLUDE_FROM_SHLIBS',
129 'EXCLUDE_FROM_WORLD',
132 'GLIBC_EXTRA_OECONF',
135 'INHIBIT_DEFAULT_DEPS',
136 'INITSCRIPT_PACKAGES',
161 'MACHINE_ESSENTIAL_EXTRA_RDEPENDS',
162 'MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS',
163 'MACHINE_EXTRA_RDEPENDS',
164 'MACHINE_EXTRA_RRECOMMENDS',
174 'OE_QMAKE_INCDIR_QT',
189 'ROOTFS_POSTPROCESS_COMMAND',
204 varRegexp = r'^([a-zA-Z_0-9${}-]*)([ \t]*)([+.:]?=[+.]?)([ \t]*)([^\t]+)'
205 routineRegexp = r'^([a-zA-Z0-9_ ${}-]+?)\('
207 # Variables seen in the processed .bb
212 # _Format guideline #0_:
213 # No spaces are allowed at the beginning of lines that define a variable or
215 def respect_rule0(line):
216 return line.lstrip()==line
217 def conformTo_rule0(line):
220 # _Format guideline #1_:
221 # No spaces are allowed behind the line continuation symbol '\'
222 def respect_rule1(line):
223 if line.rstrip().endswith('\\'):
224 return line.endswith('\\')
227 def conformTo_rule1(line):
230 # _Format guideline #2_:
231 # Tabs should not be used (use spaces instead).
232 def respect_rule2(line):
233 return line.count('\t')==0
234 def conformTo_rule2(line):
235 return line.expandtabs()
237 # _Format guideline #3_:
238 # Comments inside bb files are allowed using the '#' character at the
239 # beginning of a line.
240 def respect_rule3(line):
241 if line.lstrip().startswith('#'):
242 return line.startswith('#')
245 def conformTo_rule3(line):
248 # _Format guideline #4_:
249 # Use quotes on the right hand side of assignments FOO = "BAR"
250 def respect_rule4(line):
251 r = re.search(varRegexp, line)
253 r2 = re.search(r'("?)([^"\\]*)(["\\]?)', r.group(5))
254 # do not test for None it because always match
255 return r2.group(1)=='"' and r2.group(3)!=''
257 def conformTo_rule4(line):
258 r = re.search(varRegexp, line)
259 return ''.join([r.group(1), ' ', r.group(3), ' "', r.group(5), r.group(5).endswith('"') and '' or '"'])
261 # _Format guideline #5_:
262 # The correct spacing for a variable is FOO = "BAR".
263 def respect_rule5(line):
264 r = re.search(varRegexp, line)
265 return r is not None and r.group(2)==" " and r.group(4)==" "
266 def conformTo_rule5(line):
267 r = re.search(varRegexp, line)
268 return ''.join([r.group(1), ' ', r.group(3), ' ', r.group(5)])
270 # _Format guideline #6_:
271 # Don't use spaces or tabs on empty lines
272 def respect_rule6(line):
273 return not line.isspace() or line=="\n"
274 def conformTo_rule6(line):
277 # _Format guideline #7_:
278 # Indentation of multiline variables such as SRC_URI is desireable.
279 def respect_rule7(line):
281 def conformTo_rule7(line):
285 (respect_rule0, conformTo_rule0, "No spaces are allowed at the beginning of lines that define a variable or a do_ routine"),
286 (respect_rule1, conformTo_rule1, "No spaces are allowed behind the line continuation symbol '\\'"),
287 (respect_rule2, conformTo_rule2, "Tabs should not be used (use spaces instead)"),
288 (respect_rule3, conformTo_rule3, "Comments inside bb files are allowed using the '#' character at the beginning of a line"),
289 (respect_rule4, conformTo_rule4, "Use quotes on the right hand side of assignments FOO = \"BAR\""),
290 (respect_rule5, conformTo_rule5, "The correct spacing for a variable is FOO = \"BAR\""),
291 (respect_rule6, conformTo_rule6, "Don't use spaces or tabs on empty lines"),
292 (respect_rule7, conformTo_rule7, "Indentation of multiline variables such as SRC_URI is desireable"),
295 # Function to check that a line respects a rule. If not, it tries to conform
296 # the line to the rule. Reminder or Disgression message are dump accordingly.
297 def follow_rule(i, line):
299 # if the line does not respect the rule
300 if not rules[i][0](line):
301 # try to conform it to the rule
302 line = rules[i][1](line)
303 # if the line still does not respect the rule
304 if not rules[i][0](line):
305 # this is a rule disgression
306 print "## Disgression: ", rules[i][2], " in:", oldline
308 # just remind user about his/her errors
309 print "## Reminder: ", rules[i][2], " in :", oldline
313 if __name__ == "__main__":
315 # -- retrieves the lines of the .bb file --
317 for line in fileinput.input():
318 # use 'if True' to warn user about all the rule he/she breaks
319 # use 'if False' to conform to rules{2,1,6} without warnings
323 # expandtabs on each line so that rule2 is always respected
324 # rstrip each line so that rule1 is always respected
325 line = line.expandtabs().rstrip()
326 # ignore empty lines (or line filled with spaces or tabs only)
327 # so that rule6 is always respected
331 # -- parse the file --
338 # rstrip line to remove line breaks characters
340 line = follow_rule(2, line)
341 line = follow_rule(1, line)
342 line = follow_rule(6, line)
345 if line.isspace() or line is '':
346 # flush comments into the olines
347 for c in commentBloc: olines.append(c)
351 if line.startswith('}'):
353 keep = line.endswith('\\') or in_routine
355 # handles commented lines
356 if line.lstrip().startswith('#'):
357 # check and follow rule3 if not in a variables or routines
359 line = follow_rule(3, line)
360 commentBloc.append(line)
363 if seen_vars.has_key(var):
364 for c in commentBloc: seen_vars[var].append(c)
366 seen_vars[var].append(line)
369 if line.startswith(k):
372 if re.match(routineRegexp, line) is not None:
374 line = follow_rule(0, line)
375 elif re.match(varRegexp, line) is not None:
376 line = follow_rule(0, line)
377 line = follow_rule(4, line)
378 line = follow_rule(5, line)
381 print "## Warning: unknown variable/routine \"%s\"" % originalLine
383 for c in commentBloc: seen_vars[var].append(c)
385 seen_vars[var].append(line)
386 if not keep and not in_routine: var = ""
388 # -- dump the sanitized .bb file --
390 # write comments that are not related to variables nor routines
391 for l in commentBloc: olines.append(l)
392 # write variables and routines
393 previourVarPrefix = "unknown"
395 if k=='SRC_URI': addEmptyLine = True
396 if seen_vars[k] != []:
397 if addEmptyLine and not k.startswith(previourVarPrefix):
399 for l in seen_vars[k]:
401 previourVarPrefix = k.split('_')[0]=='' and "unknown" or k.split('_')[0]
402 for line in olines: print line