makefile.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. """ Functions for working with Makefiles
  2. """
  3. import os
  4. import glob
  5. import re
  6. import qmk.path
  7. from qmk.errors import NoSuchKeyboardError
  8. def parse_rules_mk(file_path):
  9. """ Parse a rules.mk file
  10. Args:
  11. file_path: path to the rules.mk file
  12. Returns:
  13. a dictionary with the file's content
  14. """
  15. # regex to match lines with comment at the end
  16. # group(1) = option's name
  17. # group(2) = operator (eg.: '=', '+=')
  18. # group(3) = value(s)
  19. commented_regex = re.compile(r"^\s*(\w+)\s*([\:\+\-]?=)\s*(.*?)(?=\s*\#)")
  20. # regex to match lines without comment at the end
  21. # group(1) = option's name
  22. # group(2) = operator (eg.: '=', '+=')
  23. # group(3) = value(s)
  24. uncommented_regex = re.compile(r"^\s*(\w+)\s*([\:\+\-]?=)\s*(.*?)(?=\s*$)")
  25. mk_content = qmk.path.unicode_lines(file_path)
  26. parsed_file = dict()
  27. for line in mk_content:
  28. found = commented_regex.search(line) if "#" in line else uncommented_regex.search(line)
  29. if found:
  30. parsed_file[found.group(1)] = dict(operator = found.group(2), value = found.group(3))
  31. return parsed_file
  32. def merge_rules_mk_files(base, revision):
  33. """ Merge a keyboard revision's rules.mk file with
  34. the 'base' rules.mk file
  35. Args:
  36. base: the base rules.mk file's content as dictionary
  37. revision: the revision's rules.mk file's content as dictionary
  38. Returns:
  39. a dictionary with the merged content
  40. """
  41. return {**base, **revision}
  42. def get_rules_mk(keyboard, revision = ""):
  43. """ Get a rules.mk for a keyboard
  44. Args:
  45. keyboard: name of the keyboard
  46. revision: revision of the keyboard
  47. Returns:
  48. a dictionary with the content of the rules.mk file
  49. """
  50. base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep
  51. rules_mk = dict()
  52. if os.path.exists(base_path + os.path.sep + revision):
  53. rules_mk_path_wildcard = os.path.join(base_path, "**", "rules.mk")
  54. rules_mk_regex = re.compile(r"^" + base_path + "(?:" + revision + os.path.sep + ")?rules.mk")
  55. paths = [path for path in glob.iglob(rules_mk_path_wildcard, recursive = True) if rules_mk_regex.search(path)]
  56. for file_path in paths:
  57. rules_mk[revision if revision in file_path else "base"] = parse_rules_mk(file_path)
  58. else:
  59. raise NoSuchKeyboardError("The requested keyboard and/or revision does not exist.")
  60. # if the base or the revision directory does not contain a rules.mk
  61. if len(rules_mk) == 1:
  62. rules_mk = rules_mk[revision]
  63. # if both directories contain rules.mk files
  64. elif len(rules_mk) == 2:
  65. rules_mk = merge_rules_mk_files(rules_mk["base"], rules_mk[revision])
  66. return rules_mk